blob: 78c4531fe8dc9890c257f7cfd6358562f888f05b [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 ):
440 return main.FALSE
441 return main.TRUE
Jon Hall80daded2015-05-27 16:07:00 -0700442 except pexpect.TIMEOUT:
443 main.log.exception( self.name + ": TIMEOUT exception found" )
YPZhangebf9eb52016-05-12 15:20:24 -0700444 if noExit:
445 main.cleanup()
446 return None
447 else:
Devin Lim44075962017-08-11 10:56:37 -0700448 main.cleanAndExit()
kelvin-onlab9f541032015-02-04 16:19:53 -0800449 except pexpect.EOF:
450 main.log.error( self.name + ": EOF exception found" )
451 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700452 if noExit:
453 main.cleanup()
454 return None
455 else:
Devin Lim44075962017-08-11 10:56:37 -0700456 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800457 except Exception:
kelvin-onlabfb521662015-02-27 09:52:40 -0800458 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700459 if noExit:
460 main.cleanup()
461 return None
462 else:
Devin Lim44075962017-08-11 10:56:37 -0700463 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400464
Jon Hall0e240372018-05-02 11:21:57 -0700465 def clearBuffer( self, debug=False, timeout=10, noExit=False ):
kelvin8ec71442015-01-15 16:57:00 -0800466 """
Jon Hall0e240372018-05-02 11:21:57 -0700467 Test cli connection and clear any left over output in the buffer
468 Optional Arguments:
469 debug - Defaults to False. If True, will enable debug logging.
470 timeout - Defaults to 10. Amount of time in seconds for a command to return
471 before a timeout.
472 noExit - Defaults to False. If True, will not exit TestON in the event of a
kelvin8ec71442015-01-15 16:57:00 -0800473 """
andrewonlaba18f6bf2014-10-13 19:31:54 -0400474 try:
Jon Halla495f562016-05-16 18:03:26 -0700475 # Try to reconnect if disconnected from cli
476 self.handle.sendline( "" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800477 i = self.handle.expect( [ self.karafPrompt, self.prompt, pexpect.TIMEOUT ] )
Jon Hall0e240372018-05-02 11:21:57 -0700478 response = self.handle.before
Jon Halla495f562016-05-16 18:03:26 -0700479 if i == 1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700480 main.log.error( self.name + ": onos cli session closed. " )
Jon Halla495f562016-05-16 18:03:26 -0700481 if self.onosIp:
482 main.log.warn( "Trying to reconnect " + self.onosIp )
483 reconnectResult = self.startOnosCli( self.onosIp )
484 if reconnectResult:
485 main.log.info( self.name + ": onos cli session reconnected." )
486 else:
487 main.log.error( self.name + ": reconnection failed." )
YPZhang14a4aa92016-07-15 13:37:15 -0700488 if noExit:
489 return None
490 else:
Devin Lim44075962017-08-11 10:56:37 -0700491 main.cleanAndExit()
Jon Halla495f562016-05-16 18:03:26 -0700492 else:
Devin Lim44075962017-08-11 10:56:37 -0700493 main.cleanAndExit()
Jon Halla495f562016-05-16 18:03:26 -0700494 if i == 2:
Jon Hall7a6ebfd2017-03-13 10:58:58 -0700495 main.log.warn( "Timeout when testing cli responsiveness" )
496 main.log.debug( self.handle.before )
497 self.handle.send( "\x03" ) # Send ctrl-c to clear previous output
Jon Hall6c9e2da2018-11-06 12:01:23 -0800498 self.handle.expect( self.karafPrompt )
Jon Halla495f562016-05-16 18:03:26 -0700499
Jon Hall0e240372018-05-02 11:21:57 -0700500 response += self.handle.before
Jon Hall14a03b52016-05-11 12:07:30 -0700501 if debug:
Jon Hall0e240372018-05-02 11:21:57 -0700502 main.log.debug( self.name + ": Raw output from sending ''" )
503 main.log.debug( self.name + ": " + repr( response ) )
504 except pexpect.TIMEOUT:
505 main.log.error( self.name + ": ONOS timeout" )
506 main.log.debug( self.handle.before )
You Wang141b43b2018-06-26 16:50:18 -0700507 self.handle.send( "\x03" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800508 self.handle.expect( self.karafPrompt )
Jon Hall0e240372018-05-02 11:21:57 -0700509 return None
510 except pexpect.EOF:
511 main.log.error( self.name + ": EOF exception found" )
512 main.log.error( self.name + ": " + self.handle.before )
513 if noExit:
514 return None
515 else:
516 main.cleanAndExit()
517 except Exception:
518 main.log.exception( self.name + ": Uncaught exception!" )
519 if noExit:
520 return None
521 else:
522 main.cleanAndExit()
523
Jon Hall22e94ce2019-01-15 14:52:17 -0800524 def sendline( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False, relaxedRegex=True, expectJson=False ):
Jon Hall0e240372018-05-02 11:21:57 -0700525 """
526 A wrapper around pexpect's sendline/expect. Will return all the output from a given command
527
528 Required Arguments:
529 cmdStr - String to send to the pexpect session
530
531 Optional Arguments:
532 showResponse - Defaults to False. If True will log the response.
533 debug - Defaults to False. If True, will enable debug logging.
534 timeout - Defaults to 10. Amount of time in seconds for a command to return
535 before a timeout.
536 noExit - Defaults to False. If True, will not exit TestON in the event of a
537 closed channel, but instead return None
Jon Hall6c9e2da2018-11-06 12:01:23 -0800538 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 -0700539
540 Warning: There are no sanity checking to commands sent using this method.
541
542 """
543 try:
544 # Try to reconnect if disconnected from cli
545 self.clearBuffer( debug=debug, timeout=timeout, noExit=noExit )
546 if debug:
547 # NOTE: This adds an average of .4 seconds per call
Jon Hall14a03b52016-05-11 12:07:30 -0700548 logStr = "\"Sending CLI command: '" + cmdStr + "'\""
Jon Halle0f0b342017-04-18 11:43:47 -0700549 self.log( logStr, noExit=noExit )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800550 self.handle.sendline( cmdStr )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800551 self.handle.expect( self.karafPrompt, timeout )
Jon Hall63604932015-02-26 17:09:50 -0800552 response = self.handle.before
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000553 main.log.info( "Command '" + str( cmdStr ) + "' sent to "
Jon Hallc6793552016-01-19 14:18:37 -0800554 + self.name + "." )
Jon Hallc6358dd2015-04-10 12:44:28 -0700555 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700556 main.log.debug( self.name + ": Raw output" )
557 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700558
Jon Hall6c9e2da2018-11-06 12:01:23 -0800559 # Remove control codes from karaf 4.2.1
Jon Hallcf31d0f2018-12-13 11:18:48 -0800560 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 -0800561 response = karafEscape.sub( '', response )
562 if debug:
563 main.log.debug( self.name + ": karafEscape output" )
564 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700565 # Remove ANSI color control strings from output
Jon Hall6c9e2da2018-11-06 12:01:23 -0800566 ansiEscape = re.compile( r'((\x9b|\x1b\[)[0-?]*[ -/]*[@-~])' )
Jon Hall63604932015-02-26 17:09:50 -0800567 response = ansiEscape.sub( '', response )
Jon Hallc6358dd2015-04-10 12:44:28 -0700568 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700569 main.log.debug( self.name + ": ansiEscape output" )
570 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700571
Jon Hall6c9e2da2018-11-06 12:01:23 -0800572 # Remove ANSI color control strings from output
Jon Hallcf31d0f2018-12-13 11:18:48 -0800573 # NOTE: karaf is sometimes adding a single character then two
574 # backspaces and sometimes adding 2 characters with 2 backspaces??
Jon Hall6c9e2da2018-11-06 12:01:23 -0800575 backspaceEscape = re.compile( r'((..\x08\x08)|(.|\s)\x08)' )
576 response = backspaceEscape.sub( '', response )
577 if debug:
578 main.log.debug( self.name + ": backspaceEscape output" )
579 main.log.debug( self.name + ": " + repr( response ) )
580
kelvin-onlabfb521662015-02-27 09:52:40 -0800581 # Remove extra return chars that get added
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000582 response = re.sub( r"\s\r", "", response )
Jon Hallc6358dd2015-04-10 12:44:28 -0700583 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700584 main.log.debug( self.name + ": Removed extra returns " +
585 "from output" )
586 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700587
588 # Strip excess whitespace
Jon Hall63604932015-02-26 17:09:50 -0800589 response = response.strip()
Jon Hallc6358dd2015-04-10 12:44:28 -0700590 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700591 main.log.debug( self.name + ": parsed and stripped output" )
592 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700593
Jon Hall63604932015-02-26 17:09:50 -0800594 # parse for just the output, remove the cmd from response
Jon Hallce0d70b2018-12-11 11:01:32 -0800595 cmdPattern = cmdStr.strip()
596 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
597 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800598 if relaxedRegex:
Jon Hallce0d70b2018-12-11 11:01:32 -0800599 cmdPattern = cmdPattern.split( '|' )[ -1 ].strip()
600 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
601 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800602 # This was added because karaf 4.2 is stripping some characters from the command echo
Jon Hallce0d70b2018-12-11 11:01:32 -0800603 output = response.split( cmdPattern, 1 )
Jon Hall22e94ce2019-01-15 14:52:17 -0800604 if expectJson:
605 main.log.warn( "Relaxed Regex: Searching for a json string amongst the output" )
606 jsonPattern = r'\{.*\}'
607 match = re.search( jsonPattern, output[ 0 ] )
608 if match:
609 output = [ '' , match.group( 0 ) ] # We expect a list with the second element to be the output
Jon Hall39e3ffe2018-12-05 11:40:29 -0800610 if len( output ) < 2:
611 main.log.warn( "Relaxing regex match to last 5 characters of the sent command" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800612 cmdPattern = cmdPattern[ -5: ]
613 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
614 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
615 output = response.split( cmdPattern, 1 )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800616 else:
Jon Hallce0d70b2018-12-11 11:01:32 -0800617 output = response.split( cmdPattern, 1 )
618 if len( output ) < 2: # TODO: Should we do this without the relaxedRegex flag?
Jon Hall8c9dd1c2018-11-14 15:40:39 -0800619 main.log.warn( "Relaxing regex match to last 5 characters of the sent command" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800620 output = response.split( cmdPattern[ -5: ], 1 )
Jon Hall0e240372018-05-02 11:21:57 -0700621 if output:
622 if debug:
623 main.log.debug( self.name + ": split output" )
624 for r in output:
625 main.log.debug( self.name + ": " + repr( r ) )
Jon Hallce0d70b2018-12-11 11:01:32 -0800626 if len( output ) == 1:
627 main.log.error( "Could not remove sent command echo from output" )
628 return output
Jon Hall0e240372018-05-02 11:21:57 -0700629 output = output[ 1 ].strip()
GlennRC85870432015-11-23 11:45:51 -0800630 if showResponse:
GlennRCed771242016-01-13 17:02:47 -0800631 main.log.info( "Response from ONOS: {}".format( output ) )
Jon Hall0e240372018-05-02 11:21:57 -0700632 self.clearBuffer( debug=debug, timeout=timeout, noExit=noExit )
GlennRC85870432015-11-23 11:45:51 -0800633 return output
GlennRCed771242016-01-13 17:02:47 -0800634 except pexpect.TIMEOUT:
Jon Hall0e240372018-05-02 11:21:57 -0700635 main.log.error( self.name + ": ONOS timeout" )
GlennRCed771242016-01-13 17:02:47 -0800636 if debug:
637 main.log.debug( self.handle.before )
You Wang6b5e5ba2019-01-31 15:32:40 -0800638 self.exitFromCmd( self.karafPrompt, 100 )
GlennRCed771242016-01-13 17:02:47 -0800639 return None
Jon Hallc6358dd2015-04-10 12:44:28 -0700640 except IndexError:
641 main.log.exception( self.name + ": Object not as expected" )
Jon Halla495f562016-05-16 18:03:26 -0700642 main.log.debug( "response: {}".format( repr( response ) ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700643 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800644 except TypeError:
645 main.log.exception( self.name + ": Object not as expected" )
646 return None
andrewonlaba18f6bf2014-10-13 19:31:54 -0400647 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800648 main.log.error( self.name + ": EOF exception found" )
649 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700650 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700651 return None
652 else:
Devin Lim44075962017-08-11 10:56:37 -0700653 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800654 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800655 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700656 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700657 return None
658 else:
Devin Lim44075962017-08-11 10:56:37 -0700659 main.cleanAndExit()
andrewonlaba18f6bf2014-10-13 19:31:54 -0400660
Jon Halld5a94fb2018-11-13 14:32:23 -0800661 def lineCount( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False, relaxedRegex=True ):
662 """
663 A wrapper around sendline(). Will return the number of lines returned or None on error
664
665 Required Arguments:
666 cmdStr - String to send to the pexpect session
667
668 Optional Arguments:
669 showResponse - Defaults to False. If True will log the response.
670 debug - Defaults to False. If True, will enable debug logging.
671 timeout - Defaults to 10. Amount of time in seconds for a command to return
672 before a timeout.
673 noExit - Defaults to False. If True, will not exit TestON in the event of a
674 closed channel, but instead return None
675 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.
676
677 Warning: There are no sanity checking to commands sent using this method.
678
679 """
680 try:
681 numLines = self.sendline( cmdStr, showResponse, debug, timeout, noExit, relaxedRegex )
You Wang0ce8e0c2019-02-22 12:22:26 -0800682 parsed = re.search( "(\d+)", numLines )
Jon Hall8c9dd1c2018-11-14 15:40:39 -0800683 if not parsed:
684 main.log.error( "Warning, output of karaf's wc may have changed" )
685 return None
686 return parsed.group( 1 )
Jon Halld5a94fb2018-11-13 14:32:23 -0800687 except IndexError:
688 main.log.exception( self.name + ": Object not as expected" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800689 main.log.debug( "response: {}".format( repr( numLines ) ) )
Jon Halld5a94fb2018-11-13 14:32:23 -0800690 return None
691 except TypeError:
692 main.log.exception( self.name + ": Object not as expected" )
693 return None
694 except Exception:
695 main.log.exception( self.name + ": Uncaught exception!" )
696 if noExit:
697 return None
698 else:
699 main.cleanAndExit()
700
kelvin8ec71442015-01-15 16:57:00 -0800701 # IMPORTANT NOTE:
702 # For all cli commands, naming convention should match
kelvin-onlabd3b64892015-01-20 13:26:24 -0800703 # the cli command changing 'a:b' with 'aB'.
704 # Ex ) onos:topology > onosTopology
705 # onos:links > onosLinks
706 # feature:list > featureList
Jon Halle3f39ff2015-01-13 11:50:53 -0800707
kelvin-onlabd3b64892015-01-20 13:26:24 -0800708 def addNode( self, nodeId, ONOSIp, tcpPort="" ):
kelvin8ec71442015-01-15 16:57:00 -0800709 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400710 Adds a new cluster node by ID and address information.
711 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800712 * nodeId
713 * ONOSIp
andrewonlabc2d05aa2014-10-13 16:51:10 -0400714 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800715 * tcpPort
kelvin8ec71442015-01-15 16:57:00 -0800716 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400717 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800718 cmdStr = "add-node " + str( nodeId ) + " " +\
719 str( ONOSIp ) + " " + str( tcpPort )
720 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700721 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800722 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -0800723 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700724 main.log.error( self.name + ": Error in adding node" )
kelvin8ec71442015-01-15 16:57:00 -0800725 main.log.error( handle )
Jon Halle3f39ff2015-01-13 11:50:53 -0800726 return main.FALSE
andrewonlabc2d05aa2014-10-13 16:51:10 -0400727 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800728 main.log.info( "Node " + str( ONOSIp ) + " added" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400729 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800730 except AssertionError:
731 main.log.exception( "" )
732 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800733 except TypeError:
734 main.log.exception( self.name + ": Object not as expected" )
735 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400736 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800737 main.log.error( self.name + ": EOF exception found" )
738 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700739 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800740 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800741 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700742 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400743
kelvin-onlabd3b64892015-01-20 13:26:24 -0800744 def removeNode( self, nodeId ):
kelvin8ec71442015-01-15 16:57:00 -0800745 """
andrewonlab86dc3082014-10-13 18:18:38 -0400746 Removes a cluster by ID
747 Issues command: 'remove-node [<node-id>]'
748 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800749 * nodeId
kelvin8ec71442015-01-15 16:57:00 -0800750 """
andrewonlab86dc3082014-10-13 18:18:38 -0400751 try:
andrewonlab86dc3082014-10-13 18:18:38 -0400752
kelvin-onlabd3b64892015-01-20 13:26:24 -0800753 cmdStr = "remove-node " + str( nodeId )
Jon Hall08f61bc2015-04-13 16:00:30 -0700754 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700755 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800756 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700757 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700758 main.log.error( self.name + ": Error in removing node" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700759 main.log.error( handle )
760 return main.FALSE
761 else:
762 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800763 except AssertionError:
764 main.log.exception( "" )
765 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800766 except TypeError:
767 main.log.exception( self.name + ": Object not as expected" )
768 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400769 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800770 main.log.error( self.name + ": EOF exception found" )
771 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700772 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800773 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800774 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700775 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400776
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700777 def nodes( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800778 """
andrewonlab7c211572014-10-15 16:45:20 -0400779 List the nodes currently visible
780 Issues command: 'nodes'
Jon Hall61282e32015-03-19 11:34:11 -0700781 Optional argument:
782 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800783 """
andrewonlab7c211572014-10-15 16:45:20 -0400784 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700785 cmdStr = "nodes"
Jon Hall61282e32015-03-19 11:34:11 -0700786 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700787 cmdStr += " -j"
788 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700789 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800790 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -0700791 return output
Jon Hallc6793552016-01-19 14:18:37 -0800792 except AssertionError:
793 main.log.exception( "" )
794 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800795 except TypeError:
796 main.log.exception( self.name + ": Object not as expected" )
797 return None
andrewonlab7c211572014-10-15 16:45:20 -0400798 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800799 main.log.error( self.name + ": EOF exception found" )
800 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700801 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800802 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800803 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700804 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400805
kelvin8ec71442015-01-15 16:57:00 -0800806 def topology( self ):
807 """
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700808 Definition:
Jon Hall390696c2015-05-05 17:13:41 -0700809 Returns the output of topology command.
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700810 Return:
811 topology = current ONOS topology
kelvin8ec71442015-01-15 16:57:00 -0800812 """
andrewonlab95ce8322014-10-13 14:12:04 -0400813 try:
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700814 cmdStr = "topology -j"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800815 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800816 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800817 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700818 main.log.info( cmdStr + " returned: " + str( handle ) )
andrewonlab95ce8322014-10-13 14:12:04 -0400819 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800820 except AssertionError:
821 main.log.exception( "" )
Jon Halld4d4b372015-01-28 16:02:41 -0800822 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800823 except TypeError:
824 main.log.exception( self.name + ": Object not as expected" )
825 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400826 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800827 main.log.error( self.name + ": EOF exception found" )
828 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700829 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800830 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800831 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700832 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -0800833
jenkins7ead5a82015-03-13 10:28:21 -0700834 def deviceRemove( self, deviceId ):
835 """
836 Removes particular device from storage
837
838 TODO: refactor this function
839 """
840 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700841 cmdStr = "device-remove " + str( deviceId )
842 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800843 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800844 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700845 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700846 main.log.error( self.name + ": Error in removing device" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700847 main.log.error( handle )
848 return main.FALSE
849 else:
850 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800851 except AssertionError:
852 main.log.exception( "" )
853 return None
jenkins7ead5a82015-03-13 10:28:21 -0700854 except TypeError:
855 main.log.exception( self.name + ": Object not as expected" )
856 return None
857 except pexpect.EOF:
858 main.log.error( self.name + ": EOF exception found" )
859 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700860 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700861 except Exception:
862 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700863 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700864
You Wang3b9689a2018-08-30 12:24:00 -0700865 def devices( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -0800866 """
Jon Hall7b02d952014-10-17 20:14:54 -0400867 Lists all infrastructure devices or switches
andrewonlab86dc3082014-10-13 18:18:38 -0400868 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800869 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800870 """
andrewonlab86dc3082014-10-13 18:18:38 -0400871 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700872 cmdStr = "devices"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800873 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700874 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -0700875 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -0800876 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800877 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700878 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800879 except AssertionError:
880 main.log.exception( "" )
881 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800882 except TypeError:
883 main.log.exception( self.name + ": Object not as expected" )
884 return None
andrewonlab7c211572014-10-15 16:45:20 -0400885 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800886 main.log.error( self.name + ": EOF exception found" )
887 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700888 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800889 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800890 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700891 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400892
kelvin-onlabd3b64892015-01-20 13:26:24 -0800893 def balanceMasters( self ):
kelvin8ec71442015-01-15 16:57:00 -0800894 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800895 This balances the devices across all controllers
896 by issuing command: 'onos> onos:balance-masters'
897 If required this could be extended to return devices balanced output.
kelvin8ec71442015-01-15 16:57:00 -0800898 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800899 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800900 cmdStr = "onos:balance-masters"
Jon Hallc6358dd2015-04-10 12:44:28 -0700901 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800902 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800903 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700904 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700905 main.log.error( self.name + ": Error in balancing masters" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700906 main.log.error( handle )
907 return main.FALSE
908 else:
909 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800910 except AssertionError:
911 main.log.exception( "" )
912 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800913 except TypeError:
914 main.log.exception( self.name + ": Object not as expected" )
915 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800916 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800917 main.log.error( self.name + ": EOF exception found" )
918 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700919 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800920 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800921 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700922 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800923
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000924 def checkMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700925 """
926 Returns the output of the masters command.
927 Optional argument:
928 * jsonFormat - boolean indicating if you want output in json
929 """
930 try:
931 cmdStr = "onos:masters"
932 if jsonFormat:
933 cmdStr += " -j"
934 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700935 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800936 assert "Command not found:" not in output, output
acsmars24950022015-07-30 18:00:43 -0700937 return output
Jon Hallc6793552016-01-19 14:18:37 -0800938 except AssertionError:
939 main.log.exception( "" )
940 return None
acsmars24950022015-07-30 18:00:43 -0700941 except TypeError:
942 main.log.exception( self.name + ": Object not as expected" )
943 return None
944 except pexpect.EOF:
945 main.log.error( self.name + ": EOF exception found" )
946 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700947 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700948 except Exception:
949 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700950 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700951
Jon Hallc6793552016-01-19 14:18:37 -0800952 def checkBalanceMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700953 """
954 Uses the master command to check that the devices' leadership
955 is evenly divided
956
957 Dependencies: checkMasters() and summary()
958
Jon Hall6509dbf2016-06-21 17:01:17 -0700959 Returns main.TRUE if the devices are balanced
960 Returns main.FALSE if the devices are unbalanced
acsmars24950022015-07-30 18:00:43 -0700961 Exits on Exception
962 Returns None on TypeError
963 """
964 try:
Jon Hallc6793552016-01-19 14:18:37 -0800965 summaryOutput = self.summary()
966 totalDevices = json.loads( summaryOutput )[ "devices" ]
967 except ( TypeError, ValueError ):
968 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summaryOutput ) )
969 return None
970 try:
acsmars24950022015-07-30 18:00:43 -0700971 totalOwnedDevices = 0
Jon Hallc6793552016-01-19 14:18:37 -0800972 mastersOutput = self.checkMasters()
973 masters = json.loads( mastersOutput )
acsmars24950022015-07-30 18:00:43 -0700974 first = masters[ 0 ][ "size" ]
975 for master in masters:
976 totalOwnedDevices += master[ "size" ]
977 if master[ "size" ] > first + 1 or master[ "size" ] < first - 1:
978 main.log.error( "Mastership not balanced" )
979 main.log.info( "\n" + self.checkMasters( False ) )
980 return main.FALSE
Jon Halle0f0b342017-04-18 11:43:47 -0700981 main.log.info( "Mastership balanced between " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700982 str( len( masters ) ) + " masters" )
acsmars24950022015-07-30 18:00:43 -0700983 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800984 except ( TypeError, ValueError ):
985 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, mastersOutput ) )
acsmars24950022015-07-30 18:00:43 -0700986 return None
987 except pexpect.EOF:
988 main.log.error( self.name + ": EOF exception found" )
989 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700990 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700991 except Exception:
992 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700993 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700994
YPZhangfebf7302016-05-24 16:45:56 -0700995 def links( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -0800996 """
Jon Halle8217482014-10-17 13:49:14 -0400997 Lists all core links
998 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800999 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001000 """
Jon Halle8217482014-10-17 13:49:14 -04001001 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001002 cmdStr = "links"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001003 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001004 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07001005 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001006 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001007 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001008 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001009 except AssertionError:
1010 main.log.exception( "" )
1011 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001012 except TypeError:
1013 main.log.exception( self.name + ": Object not as expected" )
1014 return None
Jon Halle8217482014-10-17 13:49:14 -04001015 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001016 main.log.error( self.name + ": EOF exception found" )
1017 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001018 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001019 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001020 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001021 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001022
You Wang3b9689a2018-08-30 12:24:00 -07001023 def ports( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -08001024 """
Jon Halle8217482014-10-17 13:49:14 -04001025 Lists all ports
1026 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001027 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001028 """
Jon Halle8217482014-10-17 13:49:14 -04001029 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001030 cmdStr = "ports"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001031 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001032 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -07001033 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001034 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001035 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001036 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001037 except AssertionError:
1038 main.log.exception( "" )
1039 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001040 except TypeError:
1041 main.log.exception( self.name + ": Object not as expected" )
1042 return None
Jon Halle8217482014-10-17 13:49:14 -04001043 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001044 main.log.error( self.name + ": EOF exception found" )
1045 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001046 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001047 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001048 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001049 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001050
kelvin-onlabd3b64892015-01-20 13:26:24 -08001051 def roles( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001052 """
Jon Hall983a1702014-10-28 18:44:22 -04001053 Lists all devices and the controllers with roles assigned to them
1054 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001055 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001056 """
andrewonlab7c211572014-10-15 16:45:20 -04001057 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001058 cmdStr = "roles"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001059 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001060 cmdStr += " -j"
1061 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001062 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001063 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001064 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001065 except AssertionError:
1066 main.log.exception( "" )
1067 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001068 except TypeError:
1069 main.log.exception( self.name + ": Object not as expected" )
1070 return None
Jon Hall983a1702014-10-28 18:44:22 -04001071 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001072 main.log.error( self.name + ": EOF exception found" )
1073 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001074 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001075 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001076 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001077 main.cleanAndExit()
Jon Hall983a1702014-10-28 18:44:22 -04001078
kelvin-onlabd3b64892015-01-20 13:26:24 -08001079 def getRole( self, deviceId ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001080 """
Jon Halle3f39ff2015-01-13 11:50:53 -08001081 Given the a string containing the json representation of the "roles"
1082 cli command and a partial or whole device id, returns a json object
1083 containing the roles output for the first device whose id contains
1084 "device_id"
Jon Hall983a1702014-10-28 18:44:22 -04001085
1086 Returns:
Jon Halle3f39ff2015-01-13 11:50:53 -08001087 A dict of the role assignments for the given device or
1088 None if no match
kelvin8ec71442015-01-15 16:57:00 -08001089 """
Jon Hall983a1702014-10-28 18:44:22 -04001090 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001091 if deviceId is None:
Jon Hall983a1702014-10-28 18:44:22 -04001092 return None
1093 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001094 rawRoles = self.roles()
1095 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001096 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001097 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001098 # print device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001099 if str( deviceId ) in device[ 'id' ]:
Jon Hall983a1702014-10-28 18:44:22 -04001100 return device
1101 return None
Jon Hallc6793552016-01-19 14:18:37 -08001102 except ( TypeError, ValueError ):
1103 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001104 return None
andrewonlab86dc3082014-10-13 18:18:38 -04001105 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001106 main.log.error( self.name + ": EOF exception found" )
1107 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001108 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001109 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001110 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001111 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001112
kelvin-onlabd3b64892015-01-20 13:26:24 -08001113 def rolesNotNull( self ):
kelvin8ec71442015-01-15 16:57:00 -08001114 """
Jon Hall94fd0472014-12-08 11:52:42 -08001115 Iterates through each device and checks if there is a master assigned
1116 Returns: main.TRUE if each device has a master
1117 main.FALSE any device has no master
kelvin8ec71442015-01-15 16:57:00 -08001118 """
Jon Hall94fd0472014-12-08 11:52:42 -08001119 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001120 rawRoles = self.roles()
1121 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001122 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001123 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001124 # print device
1125 if device[ 'master' ] == "none":
1126 main.log.warn( "Device has no master: " + str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08001127 return main.FALSE
1128 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08001129 except ( TypeError, ValueError ):
1130 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001131 return None
Jon Hall94fd0472014-12-08 11:52:42 -08001132 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001133 main.log.error( self.name + ": EOF exception found" )
1134 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001135 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001136 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001137 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001138 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001139
kelvin-onlabd3b64892015-01-20 13:26:24 -08001140 def paths( self, srcId, dstId ):
kelvin8ec71442015-01-15 16:57:00 -08001141 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001142 Returns string of paths, and the cost.
1143 Issues command: onos:paths <src> <dst>
kelvin8ec71442015-01-15 16:57:00 -08001144 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001145 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001146 cmdStr = "onos:paths " + str( srcId ) + " " + str( dstId )
1147 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001148 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001149 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08001150 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001151 main.log.error( self.name + ": Error in getting paths" )
kelvin8ec71442015-01-15 16:57:00 -08001152 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001153 else:
kelvin8ec71442015-01-15 16:57:00 -08001154 path = handle.split( ";" )[ 0 ]
1155 cost = handle.split( ";" )[ 1 ]
1156 return ( path, cost )
Jon Hallc6793552016-01-19 14:18:37 -08001157 except AssertionError:
1158 main.log.exception( "" )
1159 return ( handle, "Error" )
Jon Halld4d4b372015-01-28 16:02:41 -08001160 except TypeError:
1161 main.log.exception( self.name + ": Object not as expected" )
1162 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001163 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001164 main.log.error( self.name + ": EOF exception found" )
1165 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001166 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001167 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001168 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001169 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -08001170
kelvin-onlabd3b64892015-01-20 13:26:24 -08001171 def hosts( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001172 """
Jon Hallffb386d2014-11-21 13:43:38 -08001173 Lists all discovered hosts
Jon Hall42db6dc2014-10-24 19:03:48 -04001174 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001175 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001176 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001177 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001178 cmdStr = "hosts"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001179 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001180 cmdStr += " -j"
1181 handle = self.sendline( cmdStr )
Jeremyd9e4eb12016-04-13 12:09:06 -07001182 if handle:
1183 assert "Command not found:" not in handle, handle
Jon Hallbaf53162015-12-17 17:04:34 -08001184 # TODO: Maybe make this less hardcoded
1185 # ConsistentMap Exceptions
1186 assert "org.onosproject.store.service" not in handle
1187 # Node not leader
1188 assert "java.lang.IllegalStateException" not in handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001189 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001190 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07001191 main.log.exception( self.name + ": Error in processing '" + cmdStr + "' " +
Jeremy Songster6949cea2016-04-19 18:13:18 -07001192 "command: " + str( handle ) )
Jon Hallc6793552016-01-19 14:18:37 -08001193 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001194 except TypeError:
1195 main.log.exception( self.name + ": Object not as expected" )
1196 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001197 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001198 main.log.error( self.name + ": EOF exception found" )
1199 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001200 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001201 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001202 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001203 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001204
kelvin-onlabd3b64892015-01-20 13:26:24 -08001205 def getHost( self, mac ):
kelvin8ec71442015-01-15 16:57:00 -08001206 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001207 Return the first host from the hosts api whose 'id' contains 'mac'
Jon Halle3f39ff2015-01-13 11:50:53 -08001208
Jon Hallefbd9792015-03-05 16:11:36 -08001209 Note: mac must be a colon separated mac address, but could be a
Jon Halle3f39ff2015-01-13 11:50:53 -08001210 partial mac address
1211
Jon Hall42db6dc2014-10-24 19:03:48 -04001212 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08001213 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001214 try:
kelvin8ec71442015-01-15 16:57:00 -08001215 if mac is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04001216 return None
1217 else:
1218 mac = mac
kelvin-onlabd3b64892015-01-20 13:26:24 -08001219 rawHosts = self.hosts()
1220 hostsJson = json.loads( rawHosts )
kelvin8ec71442015-01-15 16:57:00 -08001221 # search json for the host with mac then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001222 for host in hostsJson:
kelvin8ec71442015-01-15 16:57:00 -08001223 # print "%s in %s?" % ( mac, host[ 'id' ] )
Jon Halld4d4b372015-01-28 16:02:41 -08001224 if not host:
1225 pass
1226 elif mac in host[ 'id' ]:
Jon Hall42db6dc2014-10-24 19:03:48 -04001227 return host
1228 return None
Jon Hallc6793552016-01-19 14:18:37 -08001229 except ( TypeError, ValueError ):
1230 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawHosts ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001231 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001232 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001233 main.log.error( self.name + ": EOF exception found" )
1234 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001235 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001236 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001237 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001238 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001239
kelvin-onlabd3b64892015-01-20 13:26:24 -08001240 def getHostsId( self, hostList ):
kelvin8ec71442015-01-15 16:57:00 -08001241 """
1242 Obtain list of hosts
andrewonlab3f0a4af2014-10-17 12:25:14 -04001243 Issues command: 'onos> hosts'
kelvin8ec71442015-01-15 16:57:00 -08001244
andrewonlab3f0a4af2014-10-17 12:25:14 -04001245 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001246 * hostList: List of hosts obtained by Mininet
andrewonlab3f0a4af2014-10-17 12:25:14 -04001247 IMPORTANT:
1248 This function assumes that you started your
kelvin8ec71442015-01-15 16:57:00 -08001249 topology with the option '--mac'.
andrewonlab3f0a4af2014-10-17 12:25:14 -04001250 Furthermore, it assumes that value of VLAN is '-1'
1251 Description:
kelvin8ec71442015-01-15 16:57:00 -08001252 Converts mininet hosts ( h1, h2, h3... ) into
1253 ONOS format ( 00:00:00:00:00:01/-1 , ... )
1254 """
andrewonlab3f0a4af2014-10-17 12:25:14 -04001255 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001256 onosHostList = []
andrewonlab3f0a4af2014-10-17 12:25:14 -04001257
kelvin-onlabd3b64892015-01-20 13:26:24 -08001258 for host in hostList:
kelvin8ec71442015-01-15 16:57:00 -08001259 host = host.replace( "h", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001260 hostHex = hex( int( host ) ).zfill( 12 )
1261 hostHex = str( hostHex ).replace( 'x', '0' )
1262 i = iter( str( hostHex ) )
1263 hostHex = ":".join( a + b for a, b in zip( i, i ) )
1264 hostHex = hostHex + "/-1"
1265 onosHostList.append( hostHex )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001266
kelvin-onlabd3b64892015-01-20 13:26:24 -08001267 return onosHostList
andrewonlab3f0a4af2014-10-17 12:25:14 -04001268
Jon Halld4d4b372015-01-28 16:02:41 -08001269 except TypeError:
1270 main.log.exception( self.name + ": Object not as expected" )
1271 return None
andrewonlab3f0a4af2014-10-17 12:25:14 -04001272 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001273 main.log.error( self.name + ": EOF exception found" )
1274 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001275 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001276 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001277 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001278 main.cleanAndExit()
andrewonlab3e15ead2014-10-15 14:21:34 -04001279
You Wangbc898b82018-05-03 16:22:34 -07001280 def verifyHostLocation( self, hostIp, location ):
1281 """
1282 Description:
1283 Verify the host given is discovered in all locations expected
1284 Required:
1285 hostIp: IP address of the host
1286 location: expected location(s) of the given host. ex. "of:0000000000000005/8"
1287 Could be a string or list
1288 Returns:
1289 main.TRUE if host is discovered on all locations provided
1290 main.FALSE otherwise
1291 """
1292 import json
1293 locations = [ location ] if isinstance( location, str ) else location
1294 assert isinstance( locations, list ), "Wrong type of location: {}".format( type( location ) )
1295 try:
1296 hosts = self.hosts()
1297 hosts = json.loads( hosts )
1298 targetHost = None
1299 for host in hosts:
1300 if hostIp in host[ "ipAddresses" ]:
1301 targetHost = host
You Wangfd80ab42018-05-10 17:21:53 -07001302 assert targetHost, "Not able to find host with IP {}".format( hostIp )
You Wangbc898b82018-05-03 16:22:34 -07001303 result = main.TRUE
1304 locationsDiscovered = [ loc[ "elementId" ] + "/" + loc[ "port" ] for loc in targetHost[ "locations" ] ]
1305 for loc in locations:
1306 discovered = False
1307 for locDiscovered in locationsDiscovered:
You Wang547893e2018-05-08 13:34:59 -07001308 locToMatch = locDiscovered if "/" in loc else locDiscovered.split( "/" )[0]
1309 if loc == locToMatch:
You Wangbc898b82018-05-03 16:22:34 -07001310 main.log.debug( "Host {} discovered with location {}".format( hostIp, loc ) )
You Wang547893e2018-05-08 13:34:59 -07001311 discovered = True
You Wangbc898b82018-05-03 16:22:34 -07001312 break
1313 if discovered:
1314 locationsDiscovered.remove( locDiscovered )
1315 else:
1316 main.log.warn( "Host {} not discovered with location {}".format( hostIp, loc ) )
1317 result = main.FALSE
1318 if locationsDiscovered:
1319 main.log.warn( "Host {} is also discovered with location {}".format( hostIp, locationsDiscovered ) )
1320 result = main.FALSE
1321 return result
1322 except KeyError:
1323 main.log.exception( self.name + ": host data not as expected: " + hosts )
1324 return None
1325 except pexpect.EOF:
1326 main.log.error( self.name + ": EOF exception found" )
1327 main.log.error( self.name + ": " + self.handle.before )
1328 main.cleanAndExit()
1329 except Exception:
1330 main.log.exception( self.name + ": Uncaught exception" )
1331 return None
1332
You Wang53dba1e2018-02-02 17:45:44 -08001333 def verifyHostIp( self, hostList=[], prefix="" ):
1334 """
1335 Description:
1336 Verify that all hosts have IP address assigned to them
1337 Optional:
1338 hostList: If specified, verifications only happen to the hosts
1339 in hostList
1340 prefix: at least one of the ip address assigned to the host
1341 needs to have the specified prefix
1342 Returns:
1343 main.TRUE if all hosts have specific IP address assigned;
1344 main.FALSE otherwise
1345 """
1346 import json
1347 try:
1348 hosts = self.hosts()
1349 hosts = json.loads( hosts )
1350 if not hostList:
1351 hostList = [ host[ "id" ] for host in hosts ]
1352 for host in hosts:
1353 hostId = host[ "id" ]
1354 if hostId not in hostList:
1355 continue
1356 ipList = host[ "ipAddresses" ]
1357 main.log.debug( self.name + ": IP list on host " + str( hostId ) + ": " + str( ipList ) )
1358 if not ipList:
1359 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostId ) )
1360 else:
1361 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
1362 main.log.warn( self.name + ": None of the IPs on host " + str( hostId ) + " has prefix " + str( prefix ) )
1363 else:
1364 main.log.debug( self.name + ": Found matching IP on host " + str( hostId ) )
1365 hostList.remove( hostId )
1366 if hostList:
1367 main.log.warn( self.name + ": failed to verify IP on following hosts: " + str( hostList) )
1368 return main.FALSE
1369 else:
1370 return main.TRUE
1371 except KeyError:
1372 main.log.exception( self.name + ": host data not as expected: " + hosts )
1373 return None
1374 except pexpect.EOF:
1375 main.log.error( self.name + ": EOF exception found" )
1376 main.log.error( self.name + ": " + self.handle.before )
1377 main.cleanAndExit()
1378 except Exception:
1379 main.log.exception( self.name + ": Uncaught exception" )
1380 return None
1381
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001382 def addHostIntent( self, hostIdOne, hostIdTwo, vlanId="", setVlan="", encap="", bandwidth="" ):
kelvin8ec71442015-01-15 16:57:00 -08001383 """
andrewonlabe6745342014-10-17 14:29:13 -04001384 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001385 * hostIdOne: ONOS host id for host1
1386 * hostIdTwo: ONOS host id for host2
Jeremy Songster832f9e92016-05-05 14:30:49 -07001387 Optional:
1388 * vlanId: specify a VLAN id for the intent
Jeremy Songsterff553672016-05-12 17:06:23 -07001389 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001390 * encap: specify an encapsulation type
andrewonlabe6745342014-10-17 14:29:13 -04001391 Description:
Jon Hallefbd9792015-03-05 16:11:36 -08001392 Adds a host-to-host intent ( bidirectional ) by
Jon Hallb1290e82014-11-18 16:17:48 -05001393 specifying the two hosts.
kelvin-onlabfb521662015-02-27 09:52:40 -08001394 Returns:
1395 A string of the intent id or None on Error
kelvin8ec71442015-01-15 16:57:00 -08001396 """
andrewonlabe6745342014-10-17 14:29:13 -04001397 try:
Jeremy Songster832f9e92016-05-05 14:30:49 -07001398 cmdStr = "add-host-intent "
1399 if vlanId:
1400 cmdStr += "-v " + str( vlanId ) + " "
Jeremy Songsterff553672016-05-12 17:06:23 -07001401 if setVlan:
1402 cmdStr += "--setVlan " + str( vlanId ) + " "
Jeremy Songsterc032f162016-08-04 17:14:49 -07001403 if encap:
1404 cmdStr += "--encapsulation " + str( encap ) + " "
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001405 if bandwidth:
1406 cmdStr += "-b " + str( bandwidth ) + " "
Jeremy Songster832f9e92016-05-05 14:30:49 -07001407 cmdStr += str( hostIdOne ) + " " + str( hostIdTwo )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001408 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001409 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001410 assert "Command not found:" not in handle, handle
Hari Krishnaac4e1782015-01-26 12:09:12 -08001411 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001412 main.log.error( self.name + ": Error in adding Host intent" )
Jon Hall61282e32015-03-19 11:34:11 -07001413 main.log.debug( "Response from ONOS was: " + repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001414 return None
Hari Krishnaac4e1782015-01-26 12:09:12 -08001415 else:
1416 main.log.info( "Host intent installed between " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001417 str( hostIdOne ) + " and " + str( hostIdTwo ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001418 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001419 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001420 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001421 else:
1422 main.log.error( "Error, intent ID not found" )
Jon Hall61282e32015-03-19 11:34:11 -07001423 main.log.debug( "Response from ONOS was: " +
1424 repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001425 return None
Jon Hallc6793552016-01-19 14:18:37 -08001426 except AssertionError:
1427 main.log.exception( "" )
1428 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001429 except TypeError:
1430 main.log.exception( self.name + ": Object not as expected" )
1431 return None
andrewonlabe6745342014-10-17 14:29:13 -04001432 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001433 main.log.error( self.name + ": EOF exception found" )
1434 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001435 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001436 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001437 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001438 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04001439
kelvin-onlabd3b64892015-01-20 13:26:24 -08001440 def addOpticalIntent( self, ingressDevice, egressDevice ):
kelvin8ec71442015-01-15 16:57:00 -08001441 """
andrewonlab7b31d232014-10-24 13:31:47 -04001442 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001443 * ingressDevice: device id of ingress device
1444 * egressDevice: device id of egress device
andrewonlab7b31d232014-10-24 13:31:47 -04001445 Optional:
1446 TODO: Still needs to be implemented via dev side
kelvin-onlabfb521662015-02-27 09:52:40 -08001447 Description:
1448 Adds an optical intent by specifying an ingress and egress device
1449 Returns:
1450 A string of the intent id or None on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08001451 """
andrewonlab7b31d232014-10-24 13:31:47 -04001452 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001453 cmdStr = "add-optical-intent " + str( ingressDevice ) +\
1454 " " + str( egressDevice )
1455 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001456 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001457 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08001458 # If error, return error message
Jon Halle3f39ff2015-01-13 11:50:53 -08001459 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001460 main.log.error( self.name + ": Error in adding Optical intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001461 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001462 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001463 main.log.info( "Optical intent installed between " +
1464 str( ingressDevice ) + " and " +
1465 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001466 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001467 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001468 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001469 else:
1470 main.log.error( "Error, intent ID not found" )
1471 return None
Jon Hallc6793552016-01-19 14:18:37 -08001472 except AssertionError:
1473 main.log.exception( "" )
1474 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001475 except TypeError:
1476 main.log.exception( self.name + ": Object not as expected" )
1477 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001478 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001479 main.log.error( self.name + ": EOF exception found" )
1480 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001481 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001482 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001483 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001484 main.cleanAndExit()
andrewonlab7b31d232014-10-24 13:31:47 -04001485
kelvin-onlabd3b64892015-01-20 13:26:24 -08001486 def addPointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001487 self,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001488 ingressDevice,
1489 egressDevice,
1490 portIngress="",
1491 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001492 ethType="",
1493 ethSrc="",
1494 ethDst="",
1495 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001496 lambdaAlloc=False,
alisonda157272016-12-22 01:13:21 -08001497 protected=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001498 ipProto="",
1499 ipSrc="",
1500 ipDst="",
1501 tcpSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001502 tcpDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001503 vlanId="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001504 setVlan="",
1505 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001506 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001507 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001508 * ingressDevice: device id of ingress device
1509 * egressDevice: device id of egress device
andrewonlab289e4b72014-10-21 21:24:18 -04001510 Optional:
1511 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001512 * ethSrc: specify ethSrc ( i.e. src mac addr )
1513 * ethDst: specify ethDst ( i.e. dst mac addr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001514 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001515 * lambdaAlloc: if True, intent will allocate lambda
andrewonlab40ccd8b2014-11-06 16:23:34 -05001516 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001517 * ipProto: specify ip protocol
andrewonlabf77e0cb2014-11-11 17:17:59 -05001518 * ipSrc: specify ip source address
1519 * ipDst: specify ip destination address
1520 * tcpSrc: specify tcp source port
1521 * tcpDst: specify tcp destination port
Jeremy Songster832f9e92016-05-05 14:30:49 -07001522 * vlanId: specify vlan ID
Jeremy Songsterff553672016-05-12 17:06:23 -07001523 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001524 * encap: specify an Encapsulation type to use
andrewonlab4dbb4d82014-10-17 18:22:31 -04001525 Description:
kelvin8ec71442015-01-15 16:57:00 -08001526 Adds a point-to-point intent ( uni-directional ) by
andrewonlab289e4b72014-10-21 21:24:18 -04001527 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001528 Returns:
1529 A string of the intent id or None on error
andrewonlab289e4b72014-10-21 21:24:18 -04001530
Jon Halle3f39ff2015-01-13 11:50:53 -08001531 NOTE: This function may change depending on the
andrewonlab4dbb4d82014-10-17 18:22:31 -04001532 options developers provide for point-to-point
1533 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001534 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001535 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001536 cmd = "add-point-intent"
andrewonlab36af3822014-11-18 17:48:18 -05001537
Jeremy Songsterff553672016-05-12 17:06:23 -07001538 if ethType:
1539 cmd += " --ethType " + str( ethType )
1540 if ethSrc:
1541 cmd += " --ethSrc " + str( ethSrc )
1542 if ethDst:
1543 cmd += " --ethDst " + str( ethDst )
1544 if bandwidth:
1545 cmd += " --bandwidth " + str( bandwidth )
1546 if lambdaAlloc:
1547 cmd += " --lambda "
1548 if ipProto:
1549 cmd += " --ipProto " + str( ipProto )
1550 if ipSrc:
1551 cmd += " --ipSrc " + str( ipSrc )
1552 if ipDst:
1553 cmd += " --ipDst " + str( ipDst )
1554 if tcpSrc:
1555 cmd += " --tcpSrc " + str( tcpSrc )
1556 if tcpDst:
1557 cmd += " --tcpDst " + str( tcpDst )
1558 if vlanId:
1559 cmd += " -v " + str( vlanId )
1560 if setVlan:
1561 cmd += " --setVlan " + str( setVlan )
Jeremy Songsterc032f162016-08-04 17:14:49 -07001562 if encap:
1563 cmd += " --encapsulation " + str( encap )
alisonda157272016-12-22 01:13:21 -08001564 if protected:
1565 cmd += " --protect "
andrewonlab289e4b72014-10-21 21:24:18 -04001566
kelvin8ec71442015-01-15 16:57:00 -08001567 # Check whether the user appended the port
1568 # or provided it as an input
kelvin-onlabd3b64892015-01-20 13:26:24 -08001569 if "/" in ingressDevice:
1570 cmd += " " + str( ingressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001571 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001572 if not portIngress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001573 main.log.error( "You must specify the ingress port" )
kelvin8ec71442015-01-15 16:57:00 -08001574 # TODO: perhaps more meaningful return
kelvin-onlabfb521662015-02-27 09:52:40 -08001575 # Would it make sense to throw an exception and exit
1576 # the test?
1577 return None
andrewonlab36af3822014-11-18 17:48:18 -05001578
kelvin8ec71442015-01-15 16:57:00 -08001579 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001580 str( ingressDevice ) + "/" +\
1581 str( portIngress ) + " "
andrewonlab36af3822014-11-18 17:48:18 -05001582
kelvin-onlabd3b64892015-01-20 13:26:24 -08001583 if "/" in egressDevice:
1584 cmd += " " + str( egressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001585 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001586 if not portEgress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001587 main.log.error( "You must specify the egress port" )
1588 return None
Jon Halle3f39ff2015-01-13 11:50:53 -08001589
kelvin8ec71442015-01-15 16:57:00 -08001590 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001591 str( egressDevice ) + "/" +\
1592 str( portEgress )
kelvin8ec71442015-01-15 16:57:00 -08001593
kelvin-onlab898a6c62015-01-16 14:13:53 -08001594 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001595 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001596 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001597 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001598 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001599 main.log.error( self.name + ": Error in adding point-to-point intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001600 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001601 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001602 # TODO: print out all the options in this message?
1603 main.log.info( "Point-to-point intent installed between " +
1604 str( ingressDevice ) + " and " +
1605 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001606 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001607 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001608 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001609 else:
1610 main.log.error( "Error, intent ID not found" )
1611 return None
Jon Hallc6793552016-01-19 14:18:37 -08001612 except AssertionError:
1613 main.log.exception( "" )
1614 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001615 except TypeError:
1616 main.log.exception( self.name + ": Object not as expected" )
1617 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001618 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001619 main.log.error( self.name + ": EOF exception found" )
1620 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001621 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001622 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001623 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001624 main.cleanAndExit()
andrewonlab4dbb4d82014-10-17 18:22:31 -04001625
kelvin-onlabd3b64892015-01-20 13:26:24 -08001626 def addMultipointToSinglepointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001627 self,
shahshreyac2f97072015-03-19 17:04:29 -07001628 ingressDeviceList,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001629 egressDevice,
shahshreyac2f97072015-03-19 17:04:29 -07001630 portIngressList=None,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001631 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001632 ethType="",
1633 ethSrc="",
1634 ethDst="",
1635 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001636 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001637 ipProto="",
1638 ipSrc="",
1639 ipDst="",
1640 tcpSrc="",
1641 tcpDst="",
1642 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001643 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001644 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001645 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001646 partial=False,
1647 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001648 """
shahshreyad0c80432014-12-04 16:56:05 -08001649 Note:
shahshreya70622b12015-03-19 17:19:00 -07001650 This function assumes the format of all ingress devices
Jon Hallbe379602015-03-24 13:39:32 -07001651 is same. That is, all ingress devices include port numbers
1652 with a "/" or all ingress devices could specify device
1653 ids and port numbers seperately.
shahshreyad0c80432014-12-04 16:56:05 -08001654 Required:
Jon Hallbe379602015-03-24 13:39:32 -07001655 * ingressDeviceList: List of device ids of ingress device
shahshreyac2f97072015-03-19 17:04:29 -07001656 ( Atleast 2 ingress devices required in the list )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001657 * egressDevice: device id of egress device
shahshreyad0c80432014-12-04 16:56:05 -08001658 Optional:
1659 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001660 * ethSrc: specify ethSrc ( i.e. src mac addr )
1661 * ethDst: specify ethDst ( i.e. dst mac addr )
shahshreyad0c80432014-12-04 16:56:05 -08001662 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001663 * lambdaAlloc: if True, intent will allocate lambda
shahshreyad0c80432014-12-04 16:56:05 -08001664 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001665 * ipProto: specify ip protocol
shahshreyad0c80432014-12-04 16:56:05 -08001666 * ipSrc: specify ip source address
1667 * ipDst: specify ip destination address
1668 * tcpSrc: specify tcp source port
1669 * tcpDst: specify tcp destination port
1670 * setEthSrc: action to Rewrite Source MAC Address
1671 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001672 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001673 * setVlan: specify VLAN Id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001674 * encap: specify a type of encapsulation
shahshreyad0c80432014-12-04 16:56:05 -08001675 Description:
kelvin8ec71442015-01-15 16:57:00 -08001676 Adds a multipoint-to-singlepoint intent ( uni-directional ) by
shahshreyad0c80432014-12-04 16:56:05 -08001677 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001678 Returns:
1679 A string of the intent id or None on error
shahshreyad0c80432014-12-04 16:56:05 -08001680
Jon Halle3f39ff2015-01-13 11:50:53 -08001681 NOTE: This function may change depending on the
Jon Hallefbd9792015-03-05 16:11:36 -08001682 options developers provide for multipoint-to-singlepoint
shahshreyad0c80432014-12-04 16:56:05 -08001683 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001684 """
shahshreyad0c80432014-12-04 16:56:05 -08001685 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001686 cmd = "add-multi-to-single-intent"
shahshreyad0c80432014-12-04 16:56:05 -08001687
Jeremy Songsterff553672016-05-12 17:06:23 -07001688 if ethType:
1689 cmd += " --ethType " + str( ethType )
1690 if ethSrc:
1691 cmd += " --ethSrc " + str( ethSrc )
1692 if ethDst:
1693 cmd += " --ethDst " + str( ethDst )
1694 if bandwidth:
1695 cmd += " --bandwidth " + str( bandwidth )
1696 if lambdaAlloc:
1697 cmd += " --lambda "
1698 if ipProto:
1699 cmd += " --ipProto " + str( ipProto )
1700 if ipSrc:
1701 cmd += " --ipSrc " + str( ipSrc )
1702 if ipDst:
1703 cmd += " --ipDst " + str( ipDst )
1704 if tcpSrc:
1705 cmd += " --tcpSrc " + str( tcpSrc )
1706 if tcpDst:
1707 cmd += " --tcpDst " + str( tcpDst )
1708 if setEthSrc:
1709 cmd += " --setEthSrc " + str( setEthSrc )
1710 if setEthDst:
1711 cmd += " --setEthDst " + str( setEthDst )
1712 if vlanId:
1713 cmd += " -v " + str( vlanId )
1714 if setVlan:
1715 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001716 if partial:
1717 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001718 if encap:
1719 cmd += " --encapsulation " + str( encap )
shahshreyad0c80432014-12-04 16:56:05 -08001720
kelvin8ec71442015-01-15 16:57:00 -08001721 # Check whether the user appended the port
1722 # or provided it as an input
shahshreyac2f97072015-03-19 17:04:29 -07001723
1724 if portIngressList is None:
1725 for ingressDevice in ingressDeviceList:
1726 if "/" in ingressDevice:
1727 cmd += " " + str( ingressDevice )
1728 else:
1729 main.log.error( "You must specify " +
Jon Hallbe379602015-03-24 13:39:32 -07001730 "the ingress port" )
shahshreyac2f97072015-03-19 17:04:29 -07001731 # TODO: perhaps more meaningful return
1732 return main.FALSE
shahshreyad0c80432014-12-04 16:56:05 -08001733 else:
Jon Hall71ce4e72015-03-23 14:05:58 -07001734 if len( ingressDeviceList ) == len( portIngressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001735 for ingressDevice, portIngress in zip( ingressDeviceList,
1736 portIngressList ):
shahshreya70622b12015-03-19 17:19:00 -07001737 cmd += " " + \
1738 str( ingressDevice ) + "/" +\
1739 str( portIngress ) + " "
kelvin-onlab38143812015-04-01 15:03:01 -07001740 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001741 main.log.error( "Device list and port list does not " +
1742 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001743 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001744 if "/" in egressDevice:
1745 cmd += " " + str( egressDevice )
shahshreyad0c80432014-12-04 16:56:05 -08001746 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001747 if not portEgress:
kelvin8ec71442015-01-15 16:57:00 -08001748 main.log.error( "You must specify " +
1749 "the egress port" )
shahshreyad0c80432014-12-04 16:56:05 -08001750 return main.FALSE
Jon Halle3f39ff2015-01-13 11:50:53 -08001751
kelvin8ec71442015-01-15 16:57:00 -08001752 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001753 str( egressDevice ) + "/" +\
1754 str( portEgress )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001755 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001756 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001757 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001758 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001759 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001760 main.log.error( self.name + ": Error in adding multipoint-to-singlepoint " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001761 "intent" )
1762 return None
shahshreyad0c80432014-12-04 16:56:05 -08001763 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001764 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001765 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001766 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001767 else:
1768 main.log.error( "Error, intent ID not found" )
1769 return None
Jon Hallc6793552016-01-19 14:18:37 -08001770 except AssertionError:
1771 main.log.exception( "" )
1772 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001773 except TypeError:
1774 main.log.exception( self.name + ": Object not as expected" )
1775 return None
1776 except pexpect.EOF:
1777 main.log.error( self.name + ": EOF exception found" )
1778 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001779 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001780 except Exception:
1781 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001782 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001783
1784 def addSinglepointToMultipointIntent(
1785 self,
1786 ingressDevice,
1787 egressDeviceList,
1788 portIngress="",
1789 portEgressList=None,
1790 ethType="",
1791 ethSrc="",
1792 ethDst="",
1793 bandwidth="",
1794 lambdaAlloc=False,
1795 ipProto="",
1796 ipSrc="",
1797 ipDst="",
1798 tcpSrc="",
1799 tcpDst="",
1800 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001801 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001802 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001803 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001804 partial=False,
1805 encap="" ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001806 """
1807 Note:
1808 This function assumes the format of all egress devices
1809 is same. That is, all egress devices include port numbers
1810 with a "/" or all egress devices could specify device
1811 ids and port numbers seperately.
1812 Required:
1813 * EgressDeviceList: List of device ids of egress device
1814 ( Atleast 2 eress devices required in the list )
1815 * ingressDevice: device id of ingress device
1816 Optional:
1817 * ethType: specify ethType
1818 * ethSrc: specify ethSrc ( i.e. src mac addr )
1819 * ethDst: specify ethDst ( i.e. dst mac addr )
1820 * bandwidth: specify bandwidth capacity of link
1821 * lambdaAlloc: if True, intent will allocate lambda
1822 for the specified intent
1823 * ipProto: specify ip protocol
1824 * ipSrc: specify ip source address
1825 * ipDst: specify ip destination address
1826 * tcpSrc: specify tcp source port
1827 * tcpDst: specify tcp destination port
1828 * setEthSrc: action to Rewrite Source MAC Address
1829 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001830 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001831 * setVlan: specify VLAN ID treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001832 * encap: specify an encapsulation type
kelvin-onlabb9408212015-04-01 13:34:04 -07001833 Description:
1834 Adds a singlepoint-to-multipoint intent ( uni-directional ) by
1835 specifying device id's and optional fields
1836 Returns:
1837 A string of the intent id or None on error
1838
1839 NOTE: This function may change depending on the
1840 options developers provide for singlepoint-to-multipoint
1841 intent via cli
1842 """
1843 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001844 cmd = "add-single-to-multi-intent"
kelvin-onlabb9408212015-04-01 13:34:04 -07001845
Jeremy Songsterff553672016-05-12 17:06:23 -07001846 if ethType:
1847 cmd += " --ethType " + str( ethType )
1848 if ethSrc:
1849 cmd += " --ethSrc " + str( ethSrc )
1850 if ethDst:
1851 cmd += " --ethDst " + str( ethDst )
1852 if bandwidth:
1853 cmd += " --bandwidth " + str( bandwidth )
1854 if lambdaAlloc:
1855 cmd += " --lambda "
1856 if ipProto:
1857 cmd += " --ipProto " + str( ipProto )
1858 if ipSrc:
1859 cmd += " --ipSrc " + str( ipSrc )
1860 if ipDst:
1861 cmd += " --ipDst " + str( ipDst )
1862 if tcpSrc:
1863 cmd += " --tcpSrc " + str( tcpSrc )
1864 if tcpDst:
1865 cmd += " --tcpDst " + str( tcpDst )
1866 if setEthSrc:
1867 cmd += " --setEthSrc " + str( setEthSrc )
1868 if setEthDst:
1869 cmd += " --setEthDst " + str( setEthDst )
1870 if vlanId:
1871 cmd += " -v " + str( vlanId )
1872 if setVlan:
1873 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001874 if partial:
1875 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001876 if encap:
1877 cmd += " --encapsulation " + str( encap )
kelvin-onlabb9408212015-04-01 13:34:04 -07001878
1879 # Check whether the user appended the port
1880 # or provided it as an input
Jon Hall08f61bc2015-04-13 16:00:30 -07001881
kelvin-onlabb9408212015-04-01 13:34:04 -07001882 if "/" in ingressDevice:
1883 cmd += " " + str( ingressDevice )
1884 else:
1885 if not portIngress:
1886 main.log.error( "You must specify " +
1887 "the Ingress port" )
1888 return main.FALSE
1889
1890 cmd += " " +\
1891 str( ingressDevice ) + "/" +\
1892 str( portIngress )
1893
1894 if portEgressList is None:
1895 for egressDevice in egressDeviceList:
1896 if "/" in egressDevice:
1897 cmd += " " + str( egressDevice )
1898 else:
1899 main.log.error( "You must specify " +
1900 "the egress port" )
1901 # TODO: perhaps more meaningful return
1902 return main.FALSE
1903 else:
1904 if len( egressDeviceList ) == len( portEgressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001905 for egressDevice, portEgress in zip( egressDeviceList,
1906 portEgressList ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001907 cmd += " " + \
1908 str( egressDevice ) + "/" +\
1909 str( portEgress )
kelvin-onlab38143812015-04-01 15:03:01 -07001910 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001911 main.log.error( "Device list and port list does not " +
1912 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001913 return main.FALSE
kelvin-onlabb9408212015-04-01 13:34:04 -07001914 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001915 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001916 assert "Command not found:" not in handle, handle
kelvin-onlabb9408212015-04-01 13:34:04 -07001917 # If error, return error message
1918 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001919 main.log.error( self.name + ": Error in adding singlepoint-to-multipoint " +
kelvin-onlabb9408212015-04-01 13:34:04 -07001920 "intent" )
shahshreyac2f97072015-03-19 17:04:29 -07001921 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001922 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001923 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001924 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001925 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001926 else:
1927 main.log.error( "Error, intent ID not found" )
1928 return None
Jon Hallc6793552016-01-19 14:18:37 -08001929 except AssertionError:
1930 main.log.exception( "" )
1931 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001932 except TypeError:
1933 main.log.exception( self.name + ": Object not as expected" )
1934 return None
shahshreyad0c80432014-12-04 16:56:05 -08001935 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001936 main.log.error( self.name + ": EOF exception found" )
1937 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001938 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001939 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001940 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001941 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001942
Hari Krishna9e232602015-04-13 17:29:08 -07001943 def addMplsIntent(
1944 self,
1945 ingressDevice,
1946 egressDevice,
Hari Krishna87a17f12015-04-13 17:42:23 -07001947 ingressPort="",
1948 egressPort="",
Hari Krishna9e232602015-04-13 17:29:08 -07001949 ethType="",
1950 ethSrc="",
1951 ethDst="",
1952 bandwidth="",
1953 lambdaAlloc=False,
1954 ipProto="",
1955 ipSrc="",
1956 ipDst="",
1957 tcpSrc="",
1958 tcpDst="",
Hari Krishna87a17f12015-04-13 17:42:23 -07001959 ingressLabel="",
Hari Krishnadfff6672015-04-13 17:53:27 -07001960 egressLabel="",
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001961 priority="" ):
Hari Krishna9e232602015-04-13 17:29:08 -07001962 """
1963 Required:
1964 * ingressDevice: device id of ingress device
1965 * egressDevice: device id of egress device
1966 Optional:
1967 * ethType: specify ethType
1968 * ethSrc: specify ethSrc ( i.e. src mac addr )
1969 * ethDst: specify ethDst ( i.e. dst mac addr )
1970 * bandwidth: specify bandwidth capacity of link
1971 * lambdaAlloc: if True, intent will allocate lambda
1972 for the specified intent
1973 * ipProto: specify ip protocol
1974 * ipSrc: specify ip source address
1975 * ipDst: specify ip destination address
1976 * tcpSrc: specify tcp source port
1977 * tcpDst: specify tcp destination port
1978 * ingressLabel: Ingress MPLS label
1979 * egressLabel: Egress MPLS label
1980 Description:
1981 Adds MPLS intent by
1982 specifying device id's and optional fields
1983 Returns:
1984 A string of the intent id or None on error
1985
1986 NOTE: This function may change depending on the
1987 options developers provide for MPLS
1988 intent via cli
1989 """
1990 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001991 cmd = "add-mpls-intent"
Hari Krishna9e232602015-04-13 17:29:08 -07001992
Jeremy Songsterff553672016-05-12 17:06:23 -07001993 if ethType:
1994 cmd += " --ethType " + str( ethType )
1995 if ethSrc:
1996 cmd += " --ethSrc " + str( ethSrc )
1997 if ethDst:
1998 cmd += " --ethDst " + str( ethDst )
1999 if bandwidth:
2000 cmd += " --bandwidth " + str( bandwidth )
2001 if lambdaAlloc:
2002 cmd += " --lambda "
2003 if ipProto:
2004 cmd += " --ipProto " + str( ipProto )
2005 if ipSrc:
2006 cmd += " --ipSrc " + str( ipSrc )
2007 if ipDst:
2008 cmd += " --ipDst " + str( ipDst )
2009 if tcpSrc:
2010 cmd += " --tcpSrc " + str( tcpSrc )
2011 if tcpDst:
2012 cmd += " --tcpDst " + str( tcpDst )
2013 if ingressLabel:
2014 cmd += " --ingressLabel " + str( ingressLabel )
2015 if egressLabel:
2016 cmd += " --egressLabel " + str( egressLabel )
2017 if priority:
2018 cmd += " --priority " + str( priority )
Hari Krishna9e232602015-04-13 17:29:08 -07002019
2020 # Check whether the user appended the port
2021 # or provided it as an input
2022 if "/" in ingressDevice:
2023 cmd += " " + str( ingressDevice )
2024 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002025 if not ingressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002026 main.log.error( "You must specify the ingress port" )
2027 return None
2028
2029 cmd += " " + \
2030 str( ingressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002031 str( ingressPort ) + " "
Hari Krishna9e232602015-04-13 17:29:08 -07002032
2033 if "/" in egressDevice:
2034 cmd += " " + str( egressDevice )
2035 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002036 if not egressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002037 main.log.error( "You must specify the egress port" )
2038 return None
2039
2040 cmd += " " +\
2041 str( egressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002042 str( egressPort )
Hari Krishna9e232602015-04-13 17:29:08 -07002043
2044 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08002045 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002046 assert "Command not found:" not in handle, handle
Hari Krishna9e232602015-04-13 17:29:08 -07002047 # If error, return error message
2048 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002049 main.log.error( self.name + ": Error in adding mpls intent" )
Hari Krishna9e232602015-04-13 17:29:08 -07002050 return None
2051 else:
2052 # TODO: print out all the options in this message?
2053 main.log.info( "MPLS intent installed between " +
2054 str( ingressDevice ) + " and " +
2055 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002056 match = re.search( 'id=0x([\da-f]+),', handle )
Hari Krishna9e232602015-04-13 17:29:08 -07002057 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002058 return match.group()[ 3:-1 ]
Hari Krishna9e232602015-04-13 17:29:08 -07002059 else:
2060 main.log.error( "Error, intent ID not found" )
2061 return None
Jon Hallc6793552016-01-19 14:18:37 -08002062 except AssertionError:
2063 main.log.exception( "" )
2064 return None
Hari Krishna9e232602015-04-13 17:29:08 -07002065 except TypeError:
2066 main.log.exception( self.name + ": Object not as expected" )
2067 return None
2068 except pexpect.EOF:
2069 main.log.error( self.name + ": EOF exception found" )
2070 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002071 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002072 except Exception:
2073 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002074 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002075
Jon Hallefbd9792015-03-05 16:11:36 -08002076 def removeIntent( self, intentId, app='org.onosproject.cli',
2077 purge=False, sync=False ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002078 """
shahshreya1c818fc2015-02-26 13:44:08 -08002079 Remove intent for specified application id and intent id
Jon Hall61282e32015-03-19 11:34:11 -07002080 Optional args:-
shahshreya1c818fc2015-02-26 13:44:08 -08002081 -s or --sync: Waits for the removal before returning
Jon Hall61282e32015-03-19 11:34:11 -07002082 -p or --purge: Purge the intent from the store after removal
2083
Jon Halle3f39ff2015-01-13 11:50:53 -08002084 Returns:
Jon Hall6509dbf2016-06-21 17:01:17 -07002085 main.FALSE on error and
Jon Halle3f39ff2015-01-13 11:50:53 -08002086 cli output otherwise
kelvin-onlab898a6c62015-01-16 14:13:53 -08002087 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002088 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002089 cmdStr = "remove-intent"
shahshreya1c818fc2015-02-26 13:44:08 -08002090 if purge:
2091 cmdStr += " -p"
2092 if sync:
2093 cmdStr += " -s"
2094
2095 cmdStr += " " + app + " " + str( intentId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002096 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002097 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002098 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08002099 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002100 main.log.error( self.name + ": Error in removing intent" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002101 return main.FALSE
andrewonlab9a50dfe2014-10-17 17:22:31 -04002102 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002103 # TODO: Should this be main.TRUE
2104 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002105 except AssertionError:
2106 main.log.exception( "" )
2107 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002108 except TypeError:
2109 main.log.exception( self.name + ": Object not as expected" )
2110 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002111 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002112 main.log.error( self.name + ": EOF exception found" )
2113 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002114 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002115 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002116 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002117 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04002118
YPZhangfebf7302016-05-24 16:45:56 -07002119 def removeAllIntents( self, purge=False, sync=False, app='org.onosproject.cli', timeout=30 ):
Jeremy42df2e72016-02-23 16:37:46 -08002120 """
2121 Description:
2122 Remove all the intents
2123 Optional args:-
2124 -s or --sync: Waits for the removal before returning
2125 -p or --purge: Purge the intent from the store after removal
2126 Returns:
2127 Returns main.TRUE if all intents are removed, otherwise returns
2128 main.FALSE; Returns None for exception
2129 """
2130 try:
2131 cmdStr = "remove-intent"
2132 if purge:
2133 cmdStr += " -p"
2134 if sync:
2135 cmdStr += " -s"
2136
2137 cmdStr += " " + app
YPZhangfebf7302016-05-24 16:45:56 -07002138 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08002139 assert handle is not None, "Error in sendline"
Jeremy42df2e72016-02-23 16:37:46 -08002140 assert "Command not found:" not in handle, handle
2141 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002142 main.log.error( self.name + ": Error in removing intent" )
Jeremy42df2e72016-02-23 16:37:46 -08002143 return main.FALSE
2144 else:
2145 return main.TRUE
2146 except AssertionError:
2147 main.log.exception( "" )
2148 return None
2149 except TypeError:
2150 main.log.exception( self.name + ": Object not as expected" )
2151 return None
2152 except pexpect.EOF:
2153 main.log.error( self.name + ": EOF exception found" )
2154 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002155 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002156 except Exception:
2157 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002158 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002159
Hari Krishnaacabd5a2015-07-01 17:10:19 -07002160 def purgeWithdrawnIntents( self ):
Hari Krishna0ce0e152015-06-23 09:55:29 -07002161 """
2162 Purges all WITHDRAWN Intents
2163 """
2164 try:
2165 cmdStr = "purge-intents"
2166 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002167 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002168 assert "Command not found:" not in handle, handle
Hari Krishna0ce0e152015-06-23 09:55:29 -07002169 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002170 main.log.error( self.name + ": Error in purging intents" )
Hari Krishna0ce0e152015-06-23 09:55:29 -07002171 return main.FALSE
2172 else:
2173 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002174 except AssertionError:
2175 main.log.exception( "" )
2176 return None
Hari Krishna0ce0e152015-06-23 09:55:29 -07002177 except TypeError:
2178 main.log.exception( self.name + ": Object not as expected" )
2179 return None
2180 except pexpect.EOF:
2181 main.log.error( self.name + ": EOF exception found" )
2182 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002183 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002184 except Exception:
2185 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002186 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002187
Devin Lime6fe3c42017-10-18 16:28:40 -07002188 def wipeout( self ):
2189 """
2190 Wipe out the flows,intents,links,devices,hosts, and groups from the ONOS.
2191 """
2192 try:
2193 cmdStr = "wipe-out please"
2194 handle = self.sendline( cmdStr, timeout=60 )
2195 assert handle is not None, "Error in sendline"
2196 assert "Command not found:" not in handle, handle
2197 return main.TRUE
2198 except AssertionError:
2199 main.log.exception( "" )
2200 return None
2201 except TypeError:
2202 main.log.exception( self.name + ": Object not as expected" )
2203 return None
2204 except pexpect.EOF:
2205 main.log.error( self.name + ": EOF exception found" )
2206 main.log.error( self.name + ": " + self.handle.before )
2207 main.cleanAndExit()
2208 except Exception:
2209 main.log.exception( self.name + ": Uncaught exception!" )
2210 main.cleanAndExit()
2211
kelvin-onlabd3b64892015-01-20 13:26:24 -08002212 def routes( self, jsonFormat=False ):
kelvin8ec71442015-01-15 16:57:00 -08002213 """
kelvin-onlab898a6c62015-01-16 14:13:53 -08002214 NOTE: This method should be used after installing application:
2215 onos-app-sdnip
pingping-lin8b306ac2014-11-17 18:13:51 -08002216 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002217 * jsonFormat: enable output formatting in json
pingping-lin8b306ac2014-11-17 18:13:51 -08002218 Description:
2219 Obtain all routes in the system
kelvin8ec71442015-01-15 16:57:00 -08002220 """
pingping-lin8b306ac2014-11-17 18:13:51 -08002221 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002222 cmdStr = "routes"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002223 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002224 cmdStr += " -j"
2225 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002226 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002227 assert "Command not found:" not in handle, handle
pingping-lin8b306ac2014-11-17 18:13:51 -08002228 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002229 except AssertionError:
2230 main.log.exception( "" )
2231 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002232 except TypeError:
2233 main.log.exception( self.name + ": Object not as expected" )
2234 return None
pingping-lin8b306ac2014-11-17 18:13:51 -08002235 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002236 main.log.error( self.name + ": EOF exception found" )
2237 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002238 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002239 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002240 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002241 main.cleanAndExit()
pingping-lin8b306ac2014-11-17 18:13:51 -08002242
pingping-lin54b03372015-08-13 14:43:10 -07002243 def ipv4RouteNumber( self ):
2244 """
2245 NOTE: This method should be used after installing application:
2246 onos-app-sdnip
2247 Description:
2248 Obtain the total IPv4 routes number in the system
2249 """
2250 try:
Pratik Parab57963572017-05-09 11:37:54 -07002251 cmdStr = "routes -j"
pingping-lin54b03372015-08-13 14:43:10 -07002252 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002253 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002254 assert "Command not found:" not in handle, handle
pingping-lin54b03372015-08-13 14:43:10 -07002255 jsonResult = json.loads( handle )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002256 return len( jsonResult[ 'routes4' ] )
Jon Hallc6793552016-01-19 14:18:37 -08002257 except AssertionError:
2258 main.log.exception( "" )
2259 return None
2260 except ( TypeError, ValueError ):
2261 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002262 return None
2263 except pexpect.EOF:
2264 main.log.error( self.name + ": EOF exception found" )
2265 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002266 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002267 except Exception:
2268 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002269 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002270
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002271 # =============Function to check Bandwidth allocation========
Jon Hall0e240372018-05-02 11:21:57 -07002272 def allocations( self, jsonFormat = True ):
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002273 """
2274 Description:
2275 Obtain Bandwidth Allocation Information from ONOS cli.
2276 """
2277 try:
2278 cmdStr = "allocations"
2279 if jsonFormat:
2280 cmdStr += " -j"
Jon Hall0e240372018-05-02 11:21:57 -07002281 handle = self.sendline( cmdStr, timeout=300 )
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002282 assert handle is not None, "Error in sendline"
2283 assert "Command not found:" not in handle, handle
2284 return handle
2285 except AssertionError:
2286 main.log.exception( "" )
2287 return None
2288 except ( TypeError, ValueError ):
2289 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
2290 return None
2291 except pexpect.EOF:
2292 main.log.error( self.name + ": EOF exception found" )
2293 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002294 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002295 except Exception:
2296 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002297 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002298
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002299 def intents( self, jsonFormat = True, summary = False, **intentargs ):
kelvin8ec71442015-01-15 16:57:00 -08002300 """
andrewonlabe6745342014-10-17 14:29:13 -04002301 Description:
Jon Hallff566d52016-01-15 14:45:36 -08002302 Obtain intents from the ONOS cli.
2303 Optional:
2304 * jsonFormat: Enable output formatting in json, default to True
2305 * summary: Whether only output the intent summary, defaults to False
2306 * type: Only output a certain type of intent. This options is valid
2307 only when jsonFormat is True and summary is True.
kelvin-onlab898a6c62015-01-16 14:13:53 -08002308 """
andrewonlabe6745342014-10-17 14:29:13 -04002309 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002310 cmdStr = "intents"
pingping-lin8244a3b2015-09-16 13:36:56 -07002311 if summary:
2312 cmdStr += " -s"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002313 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002314 cmdStr += " -j"
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002315 handle = self.sendline( cmdStr, timeout=300 )
You Wangb5a55f72017-03-03 12:51:05 -08002316 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002317 assert "Command not found:" not in handle, handle
pingping-lin8244a3b2015-09-16 13:36:56 -07002318 args = utilities.parse_args( [ "TYPE" ], **intentargs )
acsmars5b5fbaf2015-09-18 10:38:20 -07002319 if "TYPE" in args.keys():
Jon Hallff566d52016-01-15 14:45:36 -08002320 intentType = args[ "TYPE" ]
acsmars5b5fbaf2015-09-18 10:38:20 -07002321 else:
Jon Hallff566d52016-01-15 14:45:36 -08002322 intentType = ""
2323 # IF we want the summary of a specific intent type
2324 if jsonFormat and summary and ( intentType != "" ):
pingping-lin8244a3b2015-09-16 13:36:56 -07002325 jsonResult = json.loads( handle )
Jon Hallff566d52016-01-15 14:45:36 -08002326 if intentType in jsonResult.keys():
2327 return jsonResult[ intentType ]
pingping-lin8244a3b2015-09-16 13:36:56 -07002328 else:
Jon Hallff566d52016-01-15 14:45:36 -08002329 main.log.error( "unknown TYPE, returning all types of intents" )
pingping-lin8244a3b2015-09-16 13:36:56 -07002330 return handle
2331 else:
2332 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002333 except AssertionError:
2334 main.log.exception( "" )
2335 return None
2336 except ( TypeError, ValueError ):
2337 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002338 return None
2339 except pexpect.EOF:
2340 main.log.error( self.name + ": EOF exception found" )
2341 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002342 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002343 except Exception:
2344 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002345 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002346
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002347 def getIntentState( self, intentsId, intentsJson=None ):
kelvin-onlab54400a92015-02-26 18:05:51 -08002348 """
You Wangfdcbfc42016-05-16 12:16:53 -07002349 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002350 Gets intent state. Accepts a single intent ID (string type) or a
You Wangfdcbfc42016-05-16 12:16:53 -07002351 list of intent IDs.
2352 Parameters:
2353 intentsId: intent ID, both string type and list type are acceptable
kelvin-onlab54400a92015-02-26 18:05:51 -08002354 intentsJson: parsed json object from the onos:intents api
You Wangfdcbfc42016-05-16 12:16:53 -07002355 Returns:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002356 Returns the state (string type) of the ID if a single intent ID is
You Wangfdcbfc42016-05-16 12:16:53 -07002357 accepted.
2358 Returns a list of dictionaries if a list of intent IDs is accepted,
2359 and each dictionary maps 'id' to the Intent ID and 'state' to
2360 corresponding intent state.
kelvin-onlab54400a92015-02-26 18:05:51 -08002361 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002362
kelvin-onlab54400a92015-02-26 18:05:51 -08002363 try:
2364 state = "State is Undefined"
2365 if not intentsJson:
Jon Hallc6793552016-01-19 14:18:37 -08002366 rawJson = self.intents()
kelvin-onlab54400a92015-02-26 18:05:51 -08002367 else:
Jon Hallc6793552016-01-19 14:18:37 -08002368 rawJson = intentsJson
2369 parsedIntentsJson = json.loads( rawJson )
Jon Hallefbd9792015-03-05 16:11:36 -08002370 if isinstance( intentsId, types.StringType ):
Jon Hallc6793552016-01-19 14:18:37 -08002371 for intent in parsedIntentsJson:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002372 if intentsId == intent[ 'id' ]:
2373 state = intent[ 'state' ]
kelvin-onlab54400a92015-02-26 18:05:51 -08002374 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002375 main.log.info( "Cannot find intent ID" + str( intentsId ) +
Jon Hall53158082017-05-18 11:17:00 -07002376 " in the list" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002377 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002378 elif isinstance( intentsId, types.ListType ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002379 dictList = []
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002380 for i in xrange( len( intentsId ) ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002381 stateDict = {}
Jon Hall53158082017-05-18 11:17:00 -07002382 for intent in parsedIntentsJson:
2383 if intentsId[ i ] == intent[ 'id' ]:
2384 stateDict[ 'state' ] = intent[ 'state' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002385 stateDict[ 'id' ] = intentsId[ i ]
Jon Hallefbd9792015-03-05 16:11:36 -08002386 dictList.append( stateDict )
kelvin-onlab54400a92015-02-26 18:05:51 -08002387 break
Jon Hallefbd9792015-03-05 16:11:36 -08002388 if len( intentsId ) != len( dictList ):
Jon Hall53158082017-05-18 11:17:00 -07002389 main.log.warn( "Could not find all intents in ONOS output" )
2390 main.log.debug( "expected ids: {} \n ONOS intents: {}".format( intentsId, parsedIntentsJson ) )
kelvin-onlab07dbd012015-03-04 16:29:39 -08002391 return dictList
kelvin-onlab54400a92015-02-26 18:05:51 -08002392 else:
Jon Hall53158082017-05-18 11:17:00 -07002393 main.log.info( "Invalid type for intentsId argument" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002394 return None
Jon Hallc6793552016-01-19 14:18:37 -08002395 except ( TypeError, ValueError ):
2396 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
kelvin-onlab54400a92015-02-26 18:05:51 -08002397 return None
2398 except pexpect.EOF:
2399 main.log.error( self.name + ": EOF exception found" )
2400 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002401 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002402 except Exception:
kelvin-onlab54400a92015-02-26 18:05:51 -08002403 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002404 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07002405
Jon Hallf539eb92017-05-22 17:18:42 -07002406 def checkIntentState( self, intentsId, expectedState='INSTALLED' ):
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002407 """
2408 Description:
2409 Check intents state
2410 Required:
2411 intentsId - List of intents ID to be checked
2412 Optional:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002413 expectedState - Check the expected state(s) of each intents
kelvin-onlabf512e942015-06-08 19:42:59 -07002414 state in the list.
2415 *NOTE: You can pass in a list of expected state,
2416 Eg: expectedState = [ 'INSTALLED' , 'INSTALLING' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002417 Return:
Jon Hall53158082017-05-18 11:17:00 -07002418 Returns main.TRUE only if all intent are the same as expected states,
2419 otherwise returns main.FALSE.
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002420 """
2421 try:
kelvin-onlabf512e942015-06-08 19:42:59 -07002422 returnValue = main.TRUE
Jon Hallf539eb92017-05-22 17:18:42 -07002423 # Generating a dictionary: intent id as a key and state as value
Devin Lim752dd7b2017-06-27 14:40:03 -07002424
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002425 # intentsDict = self.getIntentState( intentsId )
Devin Lim752dd7b2017-06-27 14:40:03 -07002426 intentsDict = []
2427 for intent in json.loads( self.intents() ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002428 if isinstance( intentsId, types.StringType ) \
2429 and intent.get( 'id' ) == intentsId:
2430 intentsDict.append( intent )
2431 elif isinstance( intentsId, types.ListType ) \
Devin Lim752dd7b2017-06-27 14:40:03 -07002432 and any( intent.get( 'id' ) == ids for ids in intentsId ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002433 intentsDict.append( intent )
Devin Lim752dd7b2017-06-27 14:40:03 -07002434
2435 if not intentsDict:
Jon Hallae04e622016-01-27 10:38:05 -08002436 main.log.info( self.name + ": There is something wrong " +
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002437 "getting intents state" )
2438 return main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002439
2440 if isinstance( expectedState, types.StringType ):
2441 for intents in intentsDict:
2442 if intents.get( 'state' ) != expectedState:
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002443 main.log.debug( self.name + " : Intent ID - " +
2444 intents.get( 'id' ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002445 " actual state = " +
2446 intents.get( 'state' )
2447 + " does not equal expected state = "
2448 + expectedState )
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002449 returnValue = main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002450 elif isinstance( expectedState, types.ListType ):
2451 for intents in intentsDict:
2452 if not any( state == intents.get( 'state' ) for state in
2453 expectedState ):
2454 main.log.debug( self.name + " : Intent ID - " +
2455 intents.get( 'id' ) +
2456 " actual state = " +
2457 intents.get( 'state' ) +
2458 " does not equal expected states = "
2459 + str( expectedState ) )
2460 returnValue = main.FALSE
2461
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002462 if returnValue == main.TRUE:
2463 main.log.info( self.name + ": All " +
2464 str( len( intentsDict ) ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002465 " intents are in " + str( expectedState ) +
2466 " state" )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002467 return returnValue
2468 except TypeError:
2469 main.log.exception( self.name + ": Object not as expected" )
2470 return None
2471 except pexpect.EOF:
2472 main.log.error( self.name + ": EOF exception found" )
2473 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002474 main.cleanAndExit()
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002475 except Exception:
2476 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002477 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04002478
Jon Hallf539eb92017-05-22 17:18:42 -07002479 def compareBandwidthAllocations( self, expectedAllocations ):
2480 """
2481 Description:
2482 Compare the allocated bandwidth with the given allocations
2483 Required:
2484 expectedAllocations - The expected ONOS output of the allocations command
2485 Return:
2486 Returns main.TRUE only if all intent are the same as expected states,
2487 otherwise returns main.FALSE.
2488 """
2489 # FIXME: Convert these string comparisons to object comparisons
2490 try:
2491 returnValue = main.TRUE
2492 bandwidthFailed = False
2493 rawAlloc = self.allocations()
2494 expectedFormat = StringIO( expectedAllocations )
2495 ONOSOutput = StringIO( rawAlloc )
2496 main.log.debug( "ONOSOutput: {}\nexpected output: {}".format( str( ONOSOutput ),
2497 str( expectedFormat ) ) )
2498
2499 for actual, expected in izip( ONOSOutput, expectedFormat ):
2500 actual = actual.rstrip()
2501 expected = expected.rstrip()
2502 main.log.debug( "Expect: {}\nactual: {}".format( expected, actual ) )
2503 if actual != expected and 'allocated' in actual and 'allocated' in expected:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002504 marker1 = actual.find( 'allocated' )
2505 m1 = actual[ :marker1 ]
2506 marker2 = expected.find( 'allocated' )
2507 m2 = expected[ :marker2 ]
Jon Hallf539eb92017-05-22 17:18:42 -07002508 if m1 != m2:
2509 bandwidthFailed = True
2510 elif actual != expected and 'allocated' not in actual and 'allocated' not in expected:
2511 bandwidthFailed = True
2512 expectedFormat.close()
2513 ONOSOutput.close()
2514
2515 if bandwidthFailed:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002516 main.log.error( "Bandwidth not allocated correctly using Intents!!" )
Jon Hallf539eb92017-05-22 17:18:42 -07002517 returnValue = main.FALSE
2518 return returnValue
2519 except TypeError:
2520 main.log.exception( self.name + ": Object not as expected" )
2521 return None
2522 except pexpect.EOF:
2523 main.log.error( self.name + ": EOF exception found" )
2524 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002525 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002526 except Exception:
2527 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002528 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002529
You Wang66518af2016-05-16 15:32:59 -07002530 def compareIntent( self, intentDict ):
2531 """
2532 Description:
2533 Compare the intent ids and states provided in the argument with all intents in ONOS
2534 Return:
2535 Returns main.TRUE if the two sets of intents match exactly, otherwise main.FALSE
2536 Arguments:
2537 intentDict: a dictionary which maps intent ids to intent states
2538 """
2539 try:
2540 intentsRaw = self.intents()
2541 intentsJson = json.loads( intentsRaw )
2542 intentDictONOS = {}
2543 for intent in intentsJson:
2544 intentDictONOS[ intent[ 'id' ] ] = intent[ 'state' ]
You Wang58d04452016-09-21 15:13:05 -07002545 returnValue = main.TRUE
You Wang66518af2016-05-16 15:32:59 -07002546 if len( intentDict ) != len( intentDictONOS ):
You Wang58d04452016-09-21 15:13:05 -07002547 main.log.warn( self.name + ": expected intent count does not match that in ONOS, " +
You Wang66518af2016-05-16 15:32:59 -07002548 str( len( intentDict ) ) + " expected and " +
2549 str( len( intentDictONOS ) ) + " actual" )
You Wang58d04452016-09-21 15:13:05 -07002550 returnValue = main.FALSE
You Wang66518af2016-05-16 15:32:59 -07002551 for intentID in intentDict.keys():
Jon Halle0f0b342017-04-18 11:43:47 -07002552 if intentID not in intentDictONOS.keys():
You Wang66518af2016-05-16 15:32:59 -07002553 main.log.debug( self.name + ": intent ID - " + intentID + " is not in ONOS" )
2554 returnValue = main.FALSE
You Wang58d04452016-09-21 15:13:05 -07002555 else:
2556 if intentDict[ intentID ] != intentDictONOS[ intentID ]:
2557 main.log.debug( self.name + ": intent ID - " + intentID +
2558 " expected state is " + intentDict[ intentID ] +
2559 " but actual state is " + intentDictONOS[ intentID ] )
2560 returnValue = main.FALSE
2561 intentDictONOS.pop( intentID )
2562 if len( intentDictONOS ) > 0:
2563 returnValue = main.FALSE
2564 for intentID in intentDictONOS.keys():
2565 main.log.debug( self.name + ": find extra intent in ONOS: intent ID " + intentID )
You Wang66518af2016-05-16 15:32:59 -07002566 if returnValue == main.TRUE:
2567 main.log.info( self.name + ": all intent IDs and states match that in ONOS" )
2568 return returnValue
You Wang1be9a512016-05-26 16:54:17 -07002569 except KeyError:
2570 main.log.exception( self.name + ": KeyError exception found" )
2571 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002572 except ( TypeError, ValueError ):
2573 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intentsRaw ) )
You Wang85560372016-05-18 10:44:33 -07002574 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002575 except pexpect.EOF:
2576 main.log.error( self.name + ": EOF exception found" )
2577 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002578 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002579 except Exception:
2580 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002581 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002582
YPZhang14a4aa92016-07-15 13:37:15 -07002583 def checkIntentSummary( self, timeout=60, noExit=True ):
GlennRCed771242016-01-13 17:02:47 -08002584 """
2585 Description:
2586 Check the number of installed intents.
2587 Optional:
2588 timeout - the timeout for pexcept
YPZhang14a4aa92016-07-15 13:37:15 -07002589 noExit - If noExit, TestON will not exit if any except.
GlennRCed771242016-01-13 17:02:47 -08002590 Return:
2591 Returns main.TRUE only if the number of all installed intents are the same as total intents number
2592 , otherwise, returns main.FALSE.
2593 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002594
GlennRCed771242016-01-13 17:02:47 -08002595 try:
2596 cmd = "intents -s -j"
2597
2598 # Check response if something wrong
YPZhang14a4aa92016-07-15 13:37:15 -07002599 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002600 if response is None:
YPZhang0584d432016-06-21 15:20:13 -07002601 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002602 response = json.loads( response )
2603
2604 # get total and installed number, see if they are match
2605 allState = response.get( 'all' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002606 if allState.get( 'total' ) == allState.get( 'installed' ):
Jon Halla478b852017-12-04 15:00:15 -08002607 main.log.info( 'Total Intents: {} Installed Intents: {}'.format(
2608 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002609 return main.TRUE
Jon Halla478b852017-12-04 15:00:15 -08002610 main.log.info( 'Verified Intents failed Expected intents: {} installed intents: {}'.format(
2611 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002612 return main.FALSE
2613
Jon Hallc6793552016-01-19 14:18:37 -08002614 except ( TypeError, ValueError ):
2615 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
GlennRCed771242016-01-13 17:02:47 -08002616 return None
2617 except pexpect.EOF:
2618 main.log.error( self.name + ": EOF exception found" )
2619 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002620 if noExit:
2621 return main.FALSE
2622 else:
Devin Lim44075962017-08-11 10:56:37 -07002623 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07002624 except pexpect.TIMEOUT:
2625 main.log.error( self.name + ": ONOS timeout" )
2626 return None
GlennRCed771242016-01-13 17:02:47 -08002627 except Exception:
2628 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002629 if noExit:
2630 return main.FALSE
2631 else:
Devin Lim44075962017-08-11 10:56:37 -07002632 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002633
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002634 def flows( self, state="any", jsonFormat=True, timeout=60, noExit=False, noCore=False, device=""):
kelvin8ec71442015-01-15 16:57:00 -08002635 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002636 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002637 * jsonFormat: enable output formatting in json
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002638 * noCore: suppress core flows
Shreya Shah0f01c812014-10-26 20:15:28 -04002639 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002640 Obtain flows currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08002641 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002642 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002643 cmdStr = "flows"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002644 if jsonFormat:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002645 cmdStr += " -j"
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002646 if noCore:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002647 cmdStr += " -n"
2648 cmdStr += " " + state
2649 cmdStr += " " + device
YPZhangebf9eb52016-05-12 15:20:24 -07002650 handle = self.sendline( cmdStr, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002651 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002652 assert "Command not found:" not in handle, handle
2653 if re.search( "Error:", handle ):
2654 main.log.error( self.name + ": flows() response: " +
2655 str( handle ) )
2656 return handle
2657 except AssertionError:
2658 main.log.exception( "" )
GlennRCed771242016-01-13 17:02:47 -08002659 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002660 except TypeError:
2661 main.log.exception( self.name + ": Object not as expected" )
2662 return None
Jon Hallc6793552016-01-19 14:18:37 -08002663 except pexpect.TIMEOUT:
2664 main.log.error( self.name + ": ONOS timeout" )
2665 return None
Shreya Shah0f01c812014-10-26 20:15:28 -04002666 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002667 main.log.error( self.name + ": EOF exception found" )
2668 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002669 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002670 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002671 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002672 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002673
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002674 def checkFlowCount( self, min=0, timeout=60 ):
Flavio Castroa1286fe2016-07-25 14:48:51 -07002675 count = self.getTotalFlowsNum( timeout=timeout )
Jon Halle0f0b342017-04-18 11:43:47 -07002676 count = int( count ) if count else 0
steven30801eccfe212019-01-24 13:00:42 +08002677 main.log.debug( "found {} flows".format( count ) )
Jon Halle0f0b342017-04-18 11:43:47 -07002678 return count if ( count > min ) else False
GlennRCed771242016-01-13 17:02:47 -08002679
Jon Halle0f0b342017-04-18 11:43:47 -07002680 def checkFlowsState( self, isPENDING=True, timeout=60, noExit=False ):
kelvin-onlab4df89f22015-04-13 18:10:23 -07002681 """
2682 Description:
GlennRCed771242016-01-13 17:02:47 -08002683 Check the if all the current flows are in ADDED state
Jon Hallc6793552016-01-19 14:18:37 -08002684 We check PENDING_ADD, PENDING_REMOVE, REMOVED, and FAILED flows,
2685 if the count of those states is 0, which means all current flows
2686 are in ADDED state, and return main.TRUE otherwise return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002687 Optional:
GlennRCed771242016-01-13 17:02:47 -08002688 * isPENDING: whether the PENDING_ADD is also a correct status
kelvin-onlab4df89f22015-04-13 18:10:23 -07002689 Return:
2690 returnValue - Returns main.TRUE only if all flows are in
Jon Hallc6793552016-01-19 14:18:37 -08002691 ADDED state or PENDING_ADD if the isPENDING
pingping-linbab7f8a2015-09-21 17:33:36 -07002692 parameter is set true, return main.FALSE otherwise.
kelvin-onlab4df89f22015-04-13 18:10:23 -07002693 """
2694 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002695 states = [ "PENDING_ADD", "PENDING_REMOVE", "REMOVED", "FAILED" ]
GlennRCed771242016-01-13 17:02:47 -08002696 checkedStates = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002697 statesCount = [ 0, 0, 0, 0 ]
GlennRCed771242016-01-13 17:02:47 -08002698 for s in states:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002699 rawFlows = self.flows( state=s, timeout = timeout )
YPZhang240842b2016-05-17 12:00:50 -07002700 if rawFlows:
2701 # if we didn't get flows or flows function return None, we should return
2702 # main.Flase
2703 checkedStates.append( json.loads( rawFlows ) )
2704 else:
2705 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002706 for i in range( len( states ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002707 for c in checkedStates[ i ]:
Jon Hallc6793552016-01-19 14:18:37 -08002708 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002709 statesCount[ i ] += int( c.get( "flowCount" ) )
Jon Hallc6793552016-01-19 14:18:37 -08002710 except TypeError:
2711 main.log.exception( "Json object not as expected" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002712 main.log.info( states[ i ] + " flows: " + str( statesCount[ i ] ) )
kelvin-onlabf2ec6e02015-05-27 14:15:28 -07002713
GlennRCed771242016-01-13 17:02:47 -08002714 # We want to count PENDING_ADD if isPENDING is true
2715 if isPENDING:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002716 if statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002717 return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002718 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002719 if statesCount[ 0 ] + statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002720 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002721 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002722 except ( TypeError, ValueError ):
2723 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawFlows ) )
kelvin-onlab4df89f22015-04-13 18:10:23 -07002724 return None
Jeremy Songster9385d412016-06-02 17:57:36 -07002725
YPZhang240842b2016-05-17 12:00:50 -07002726 except AssertionError:
2727 main.log.exception( "" )
2728 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002729 except pexpect.TIMEOUT:
2730 main.log.error( self.name + ": ONOS timeout" )
2731 return None
kelvin-onlab4df89f22015-04-13 18:10:23 -07002732 except pexpect.EOF:
2733 main.log.error( self.name + ": EOF exception found" )
2734 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002735 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002736 except Exception:
2737 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002738 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002739
GlennRCed771242016-01-13 17:02:47 -08002740 def pushTestIntents( self, ingress, egress, batchSize, offset="",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002741 options="", timeout=10, background = False, noExit=False, getResponse=False ):
kelvin8ec71442015-01-15 16:57:00 -08002742 """
andrewonlab87852b02014-11-19 18:44:19 -05002743 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002744 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05002745 a specific point-to-point intent definition
2746 Required:
GlennRCed771242016-01-13 17:02:47 -08002747 * ingress: specify source dpid
2748 * egress: specify destination dpid
2749 * batchSize: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05002750 Optional:
GlennRCed771242016-01-13 17:02:47 -08002751 * offset: the keyOffset is where the next batch of intents
2752 will be installed
YPZhangb34b7e12016-06-14 14:28:19 -07002753 * noExit: If set to True, TestON will not exit if any error when issus command
2754 * getResponse: If set to True, function will return ONOS response.
2755
GlennRCed771242016-01-13 17:02:47 -08002756 Returns: If failed to push test intents, it will returen None,
2757 if successful, return true.
2758 Timeout expection will return None,
2759 TypeError will return false
2760 other expections will exit()
kelvin8ec71442015-01-15 16:57:00 -08002761 """
andrewonlab87852b02014-11-19 18:44:19 -05002762 try:
GlennRCed771242016-01-13 17:02:47 -08002763 if background:
2764 back = "&"
andrewonlab87852b02014-11-19 18:44:19 -05002765 else:
GlennRCed771242016-01-13 17:02:47 -08002766 back = ""
2767 cmd = "push-test-intents {} {} {} {} {} {}".format( options,
Jon Hallc6793552016-01-19 14:18:37 -08002768 ingress,
2769 egress,
2770 batchSize,
2771 offset,
2772 back )
YPZhangebf9eb52016-05-12 15:20:24 -07002773 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002774 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002775 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08002776 main.log.info( response )
YPZhangb34b7e12016-06-14 14:28:19 -07002777 if getResponse:
2778 return response
2779
GlennRCed771242016-01-13 17:02:47 -08002780 # TODO: We should handle if there is failure in installation
2781 return main.TRUE
2782
Jon Hallc6793552016-01-19 14:18:37 -08002783 except AssertionError:
2784 main.log.exception( "" )
2785 return None
GlennRCed771242016-01-13 17:02:47 -08002786 except pexpect.TIMEOUT:
2787 main.log.error( self.name + ": ONOS timeout" )
Jon Halld4d4b372015-01-28 16:02:41 -08002788 return None
andrewonlab87852b02014-11-19 18:44:19 -05002789 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002790 main.log.error( self.name + ": EOF exception found" )
2791 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002792 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002793 except TypeError:
2794 main.log.exception( self.name + ": Object not as expected" )
Jon Hallc6793552016-01-19 14:18:37 -08002795 return None
Jon Hallfebb1c72015-03-05 13:30:09 -08002796 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002797 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002798 main.cleanAndExit()
andrewonlab87852b02014-11-19 18:44:19 -05002799
YPZhangebf9eb52016-05-12 15:20:24 -07002800 def getTotalFlowsNum( self, timeout=60, noExit=False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002801 """
2802 Description:
YPZhangf6f14a02016-01-28 15:17:31 -08002803 Get the number of ADDED flows.
YPZhangb5d3f832016-01-23 22:54:26 -08002804 Return:
YPZhangf6f14a02016-01-28 15:17:31 -08002805 The number of ADDED flows
YPZhang14a4aa92016-07-15 13:37:15 -07002806 Or return None if any exceptions
YPZhangb5d3f832016-01-23 22:54:26 -08002807 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002808
YPZhangb5d3f832016-01-23 22:54:26 -08002809 try:
YPZhange3109a72016-02-02 11:25:37 -08002810 # get total added flows number
YPZhang14a4aa92016-07-15 13:37:15 -07002811 cmd = "flows -c added"
2812 rawFlows = self.sendline( cmd, timeout=timeout, noExit=noExit )
2813 if rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002814 rawFlows = rawFlows.split( "\n" )
YPZhange3109a72016-02-02 11:25:37 -08002815 totalFlows = 0
YPZhang14a4aa92016-07-15 13:37:15 -07002816 for l in rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002817 totalFlows += int( l.split( "Count=" )[ 1 ] )
YPZhang14a4aa92016-07-15 13:37:15 -07002818 else:
You Wang68568b12019-03-04 11:49:57 -08002819 main.log.warn( "Response not as expected!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002820 return None
2821 return totalFlows
YPZhange3109a72016-02-02 11:25:37 -08002822
You Wangd3097f72018-12-12 11:56:03 -08002823 except IndexError:
2824 main.log.exception( "{}: Object not as expected!".format( self.name ) )
2825 main.log.debug( "rawFlows: {}".format( rawFlows ) )
2826 return None
You Wangd3cb2ce2016-05-16 14:01:24 -07002827 except ( TypeError, ValueError ):
YPZhang14a4aa92016-07-15 13:37:15 -07002828 main.log.exception( "{}: Object not as expected!".format( self.name ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002829 return None
2830 except pexpect.EOF:
2831 main.log.error( self.name + ": EOF exception found" )
2832 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002833 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002834 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002835 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002836 except pexpect.TIMEOUT:
2837 main.log.error( self.name + ": ONOS timeout" )
2838 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002839 except Exception:
2840 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002841 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002842 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002843 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002844
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002845 def getTotalIntentsNum( self, timeout=60, noExit = False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002846 """
2847 Description:
2848 Get the total number of intents, include every states.
YPZhang14a4aa92016-07-15 13:37:15 -07002849 Optional:
2850 noExit - If noExit, TestON will not exit if any except.
YPZhangb5d3f832016-01-23 22:54:26 -08002851 Return:
2852 The number of intents
2853 """
2854 try:
2855 cmd = "summary -j"
YPZhang14a4aa92016-07-15 13:37:15 -07002856 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002857 if response is None:
2858 return -1
YPZhangb5d3f832016-01-23 22:54:26 -08002859 response = json.loads( response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002860 return int( response.get( "intents" ) )
You Wangd3cb2ce2016-05-16 14:01:24 -07002861 except ( TypeError, ValueError ):
2862 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002863 return None
2864 except pexpect.EOF:
2865 main.log.error( self.name + ": EOF exception found" )
2866 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002867 if noExit:
2868 return -1
2869 else:
Devin Lim44075962017-08-11 10:56:37 -07002870 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002871 except Exception:
2872 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002873 if noExit:
2874 return -1
2875 else:
Devin Lim44075962017-08-11 10:56:37 -07002876 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002877
kelvin-onlabd3b64892015-01-20 13:26:24 -08002878 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002879 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002880 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002881 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002882 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002883 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002884 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002885 cmdStr = "intents-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002886 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002887 cmdStr += " -j"
2888 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002889 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002890 assert "Command not found:" not in handle, handle
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002891 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002892 except AssertionError:
2893 main.log.exception( "" )
2894 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002895 except TypeError:
2896 main.log.exception( self.name + ": Object not as expected" )
2897 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002898 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002899 main.log.error( self.name + ": EOF exception found" )
2900 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002901 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002902 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002903 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002904 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002905
kelvin-onlabd3b64892015-01-20 13:26:24 -08002906 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002907 """
2908 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04002909 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002910 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002911 """
andrewonlab867212a2014-10-22 20:13:38 -04002912 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002913 cmdStr = "topology-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002914 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002915 cmdStr += " -j"
2916 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002917 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002918 assert "Command not found:" not in handle, handle
jenkins7ead5a82015-03-13 10:28:21 -07002919 if handle:
2920 return handle
Jon Hallc6358dd2015-04-10 12:44:28 -07002921 elif jsonFormat:
Jon Hallbe379602015-03-24 13:39:32 -07002922 # Return empty json
jenkins7ead5a82015-03-13 10:28:21 -07002923 return '{}'
Jon Hallc6358dd2015-04-10 12:44:28 -07002924 else:
2925 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002926 except AssertionError:
2927 main.log.exception( "" )
2928 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002929 except TypeError:
2930 main.log.exception( self.name + ": Object not as expected" )
2931 return None
andrewonlab867212a2014-10-22 20:13:38 -04002932 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002933 main.log.error( self.name + ": EOF exception found" )
2934 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002935 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002936 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002937 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002938 main.cleanAndExit()
andrewonlab867212a2014-10-22 20:13:38 -04002939
kelvin8ec71442015-01-15 16:57:00 -08002940 # Wrapper functions ****************
2941 # Wrapper functions use existing driver
2942 # functions and extends their use case.
2943 # For example, we may use the output of
2944 # a normal driver function, and parse it
2945 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04002946
kelvin-onlabd3b64892015-01-20 13:26:24 -08002947 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002948 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002949 Description:
2950 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08002951 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002952 try:
kelvin8ec71442015-01-15 16:57:00 -08002953 # Obtain output of intents function
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002954 intentsStr = self.intents( jsonFormat=True )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07002955 if intentsStr is None:
2956 raise TypeError
Jon Hall6021e062017-01-30 11:10:06 -08002957 # Convert to a dictionary
2958 intents = json.loads( intentsStr )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002959 intentIdList = []
Jon Hall6021e062017-01-30 11:10:06 -08002960 for intent in intents:
2961 intentIdList.append( intent[ 'id' ] )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002962 return intentIdList
Jon Halld4d4b372015-01-28 16:02:41 -08002963 except TypeError:
2964 main.log.exception( self.name + ": Object not as expected" )
2965 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002966 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002967 main.log.error( self.name + ": EOF exception found" )
2968 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002969 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002970 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002971 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002972 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04002973
You Wang3c276252016-09-21 15:21:36 -07002974 def flowAddedCount( self, deviceId, core=False ):
Jon Hall30b82fa2015-03-04 17:15:43 -08002975 """
2976 Determine the number of flow rules for the given device id that are
2977 in the added state
You Wang3c276252016-09-21 15:21:36 -07002978 Params:
2979 core: if True, only return the number of core flows added
Jon Hall30b82fa2015-03-04 17:15:43 -08002980 """
2981 try:
You Wang3c276252016-09-21 15:21:36 -07002982 if core:
2983 cmdStr = "flows any " + str( deviceId ) + " | " +\
2984 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
2985 else:
2986 cmdStr = "flows any " + str( deviceId ) + " | " +\
2987 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08002988 handle = self.lineCount( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002989 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002990 assert "Command not found:" not in handle, handle
Jon Hall30b82fa2015-03-04 17:15:43 -08002991 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002992 except AssertionError:
2993 main.log.exception( "" )
2994 return None
Jon Hall30b82fa2015-03-04 17:15:43 -08002995 except pexpect.EOF:
2996 main.log.error( self.name + ": EOF exception found" )
2997 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002998 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002999 except Exception:
Jon Hall30b82fa2015-03-04 17:15:43 -08003000 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003001 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -04003002
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003003 def groupAddedCount( self, deviceId, core=False ):
3004 """
3005 Determine the number of group rules for the given device id that are
3006 in the added state
3007 Params:
3008 core: if True, only return the number of core groups added
3009 """
3010 try:
3011 if core:
3012 cmdStr = "groups any " + str( deviceId ) + " | " +\
3013 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
3014 else:
3015 cmdStr = "groups any " + str( deviceId ) + " | " +\
3016 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003017 handle = self.lineCount( cmdStr )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003018 assert handle is not None, "Error in sendline"
3019 assert "Command not found:" not in handle, handle
3020 return handle
3021 except AssertionError:
3022 main.log.exception( "" )
3023 return None
3024 except pexpect.EOF:
3025 main.log.error( self.name + ": EOF exception found" )
3026 main.log.error( self.name + ": " + self.handle.before )
3027 main.cleanAndExit()
3028 except Exception:
3029 main.log.exception( self.name + ": Uncaught exception!" )
3030 main.cleanAndExit()
3031
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003032 def addStaticRoute( self, subnet, intf):
3033 """
3034 Adds a static route to onos.
3035 Params:
3036 subnet: The subnet reaching through this route
3037 intf: The interface this route is reachable through
3038 """
3039 try:
3040 cmdStr = "route-add " + subnet + " " + intf
3041 handle = self.sendline( cmdStr )
3042 assert handle is not None, "Error in sendline"
3043 assert "Command not found:" not in handle, handle
3044 return handle
3045 except AssertionError:
3046 main.log.exception( "" )
3047 return None
3048 except pexpect.EOF:
3049 main.log.error( self.name + ": EOF exception found" )
3050 main.log.error( self.name + ": " + self.handle.before )
3051 main.cleanAndExit()
3052 except Exception:
3053 main.log.exception( self.name + ": Uncaught exception!" )
3054 main.cleanAndExit()
3055
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003056 def checkGroupAddedCount( self, deviceId, expectedGroupCount=0, core=False, comparison=0):
3057 """
3058 Description:
3059 Check whether the number of groups for the given device id that
3060 are in ADDED state is bigger than minGroupCount.
3061 Required:
3062 * deviceId: device id to check the number of added group rules
3063 Optional:
3064 * minGroupCount: the number of groups to compare
3065 * core: if True, only check the number of core groups added
3066 * comparison: if 0, compare with greater than minFlowCount
3067 * if 1, compare with equal to minFlowCount
3068 Return:
3069 Returns the number of groups if it is bigger than minGroupCount,
3070 returns main.FALSE otherwise.
3071 """
3072 count = self.groupAddedCount( deviceId, core )
3073 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003074 main.log.debug( "found {} groups".format( count ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003075 return count if ((count > expectedGroupCount) if (comparison == 0) else (count == expectedGroupCount)) else main.FALSE
3076
You Wangc02f3be2018-05-18 12:14:23 -07003077 def getGroups( self, deviceId, groupType="any" ):
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003078 """
3079 Retrieve groups from a specific device.
You Wangc02f3be2018-05-18 12:14:23 -07003080 deviceId: Id of the device from which we retrieve groups
3081 groupType: Type of group
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003082 """
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003083 try:
You Wangc02f3be2018-05-18 12:14:23 -07003084 groupCmd = "groups -t {0} any {1}".format( groupType, deviceId )
3085 handle = self.sendline( groupCmd )
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003086 assert handle is not None, "Error in sendline"
3087 assert "Command not found:" not in handle, handle
3088 return handle
3089 except AssertionError:
3090 main.log.exception( "" )
3091 return None
3092 except TypeError:
3093 main.log.exception( self.name + ": Object not as expected" )
3094 return None
3095 except pexpect.EOF:
3096 main.log.error( self.name + ": EOF exception found" )
3097 main.log.error( self.name + ": " + self.handle.before )
3098 main.cleanAndExit()
3099 except Exception:
3100 main.log.exception( self.name + ": Uncaught exception!" )
3101 main.cleanAndExit()
3102
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003103 def checkFlowAddedCount( self, deviceId, expectedFlowCount=0, core=False, comparison=0):
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003104 """
3105 Description:
3106 Check whether the number of flow rules for the given device id that
3107 are in ADDED state is bigger than minFlowCount.
3108 Required:
3109 * deviceId: device id to check the number of added flow rules
3110 Optional:
3111 * minFlowCount: the number of flow rules to compare
3112 * core: if True, only check the number of core flows added
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003113 * comparison: if 0, compare with greater than minFlowCount
3114 * if 1, compare with equal to minFlowCount
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003115 Return:
3116 Returns the number of flow rules if it is bigger than minFlowCount,
3117 returns main.FALSE otherwise.
3118 """
3119 count = self.flowAddedCount( deviceId, core )
3120 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003121 main.log.debug( "found {} flows".format( count ) )
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003122 return count if ((count > expectedFlowCount) if (comparison == 0) else (count == expectedFlowCount)) else main.FALSE
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003123
kelvin-onlabd3b64892015-01-20 13:26:24 -08003124 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003125 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003126 Use 'devices' function to obtain list of all devices
3127 and parse the result to obtain a list of all device
3128 id's. Returns this list. Returns empty list if no
3129 devices exist
kelvin8ec71442015-01-15 16:57:00 -08003130 List is ordered sequentially
3131
andrewonlab3e15ead2014-10-15 14:21:34 -04003132 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08003133 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04003134 the ids. By obtaining the list of device ids on the fly,
3135 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08003136 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003137 try:
kelvin8ec71442015-01-15 16:57:00 -08003138 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08003139 devicesStr = self.devices( jsonFormat=False )
3140 idList = []
kelvin8ec71442015-01-15 16:57:00 -08003141
kelvin-onlabd3b64892015-01-20 13:26:24 -08003142 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08003143 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003144 return idList
kelvin8ec71442015-01-15 16:57:00 -08003145
3146 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08003147 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08003148 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08003149 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08003150 # Split list further into arguments before and after string
3151 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08003152 # append to idList
3153 for arg in tempList:
3154 idList.append( arg.split( "id=" )[ 1 ] )
3155 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04003156
Jon Halld4d4b372015-01-28 16:02:41 -08003157 except TypeError:
3158 main.log.exception( self.name + ": Object not as expected" )
3159 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04003160 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003161 main.log.error( self.name + ": EOF exception found" )
3162 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003163 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003164 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003165 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003166 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003167
kelvin-onlabd3b64892015-01-20 13:26:24 -08003168 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003169 """
andrewonlab7c211572014-10-15 16:45:20 -04003170 Uses 'nodes' function to obtain list of all nodes
3171 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08003172 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04003173 Returns:
3174 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08003175 """
andrewonlab7c211572014-10-15 16:45:20 -04003176 try:
Jon Hall5aa168b2015-03-23 14:23:09 -07003177 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003178 idList = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003179 # Sample nodesStr output
Jon Hallbd182782016-03-28 16:42:22 -07003180 # id=local, address=127.0.0.1:9876, state=READY *
kelvin-onlabd3b64892015-01-20 13:26:24 -08003181 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08003182 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003183 return idList
Jon Hall5aa168b2015-03-23 14:23:09 -07003184 nodesJson = json.loads( nodesStr )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003185 idList = [ node.get( 'id' ) for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08003186 return idList
Jon Hallc6793552016-01-19 14:18:37 -08003187 except ( TypeError, ValueError ):
3188 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, nodesStr ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003189 return None
andrewonlab7c211572014-10-15 16:45:20 -04003190 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003191 main.log.error( self.name + ": EOF exception found" )
3192 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003193 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003194 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003195 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003196 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003197
kelvin-onlabd3b64892015-01-20 13:26:24 -08003198 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08003199 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003200 Return the first device from the devices api whose 'id' contains 'dpid'
3201 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08003202 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003203 try:
kelvin8ec71442015-01-15 16:57:00 -08003204 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04003205 return None
3206 else:
kelvin8ec71442015-01-15 16:57:00 -08003207 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003208 rawDevices = self.devices()
3209 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08003210 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08003211 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08003212 # print "%s in %s?" % ( dpid, device[ 'id' ] )
3213 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04003214 return device
3215 return None
Jon Hallc6793552016-01-19 14:18:37 -08003216 except ( TypeError, ValueError ):
3217 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawDevices ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003218 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04003219 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003220 main.log.error( self.name + ": EOF exception found" )
3221 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003222 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003223 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003224 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003225 main.cleanAndExit()
Jon Halla91c4dc2014-10-22 12:57:04 -04003226
You Wang24139872016-05-03 11:48:47 -07003227 def getTopology( self, topologyOutput ):
3228 """
3229 Definition:
3230 Loads a json topology output
3231 Return:
3232 topology = current ONOS topology
3233 """
3234 import json
3235 try:
3236 # either onos:topology or 'topology' will work in CLI
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003237 topology = json.loads( topologyOutput )
Jeremy Songsterbc2d8ac2016-05-04 11:25:42 -07003238 main.log.debug( topology )
You Wang24139872016-05-03 11:48:47 -07003239 return topology
You Wangd3cb2ce2016-05-16 14:01:24 -07003240 except ( TypeError, ValueError ):
3241 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, topologyOutput ) )
3242 return None
You Wang24139872016-05-03 11:48:47 -07003243 except pexpect.EOF:
3244 main.log.error( self.name + ": EOF exception found" )
3245 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003246 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003247 except Exception:
3248 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003249 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003250
Pier6a0c4de2018-03-18 16:01:30 -07003251 def checkStatus( self, numoswitch, numolink = -1, numoctrl = -1, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08003252 """
Jon Hallefbd9792015-03-05 16:11:36 -08003253 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08003254 supplied values. By default this will report to main.log, but the
You Wang24139872016-05-03 11:48:47 -07003255 log level can be specific.
kelvin8ec71442015-01-15 16:57:00 -08003256
Flavio Castro82ee2f62016-06-07 15:04:12 -07003257 Params: numoswitch = expected number of switches
Jon Hallefbd9792015-03-05 16:11:36 -08003258 numolink = expected number of links
Flavio Castro82ee2f62016-06-07 15:04:12 -07003259 numoctrl = expected number of controllers
You Wang24139872016-05-03 11:48:47 -07003260 logLevel = level to log to.
3261 Currently accepts 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04003262
Jon Hallefbd9792015-03-05 16:11:36 -08003263 Returns: main.TRUE if the number of switches and links are correct,
3264 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04003265 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08003266 """
Flavio Castro82ee2f62016-06-07 15:04:12 -07003267 import json
Jon Hall42db6dc2014-10-24 19:03:48 -04003268 try:
You Wang13310252016-07-31 10:56:14 -07003269 summary = self.summary()
3270 summary = json.loads( summary )
Flavio Castrof5b3f872016-06-23 17:52:31 -07003271 except ( TypeError, ValueError ):
3272 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summary ) )
3273 return main.ERROR
3274 try:
3275 topology = self.getTopology( self.topology() )
Jon Halle0f0b342017-04-18 11:43:47 -07003276 if topology == {} or topology is None or summary == {} or summary is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04003277 return main.ERROR
3278 output = ""
kelvin8ec71442015-01-15 16:57:00 -08003279 # Is the number of switches is what we expected
3280 devices = topology.get( 'devices', False )
3281 links = topology.get( 'links', False )
Flavio Castro82ee2f62016-06-07 15:04:12 -07003282 nodes = summary.get( 'nodes', False )
3283 if devices is False or links is False or nodes is False:
Jon Hall42db6dc2014-10-24 19:03:48 -04003284 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08003285 switchCheck = ( int( devices ) == int( numoswitch ) )
kelvin8ec71442015-01-15 16:57:00 -08003286 # Is the number of links is what we expected
Pier6a0c4de2018-03-18 16:01:30 -07003287 linkCheck = ( int( links ) == int( numolink ) ) or int( numolink ) == -1
Flavio Castro82ee2f62016-06-07 15:04:12 -07003288 nodeCheck = ( int( nodes ) == int( numoctrl ) ) or int( numoctrl ) == -1
3289 if switchCheck and linkCheck and nodeCheck:
kelvin8ec71442015-01-15 16:57:00 -08003290 # We expected the correct numbers
You Wang24139872016-05-03 11:48:47 -07003291 output = output + "The number of links and switches match "\
3292 + "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003293 result = main.TRUE
3294 else:
You Wang24139872016-05-03 11:48:47 -07003295 output = output + \
3296 "The number of links and switches does not match " + \
3297 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003298 result = main.FALSE
You Wang24139872016-05-03 11:48:47 -07003299 output = output + "\n ONOS sees %i devices" % int( devices )
3300 output = output + " (%i expected) " % int( numoswitch )
Pier6a0c4de2018-03-18 16:01:30 -07003301 if int( numolink ) > 0:
3302 output = output + "and %i links " % int( links )
3303 output = output + "(%i expected)" % int( numolink )
YPZhangd7e4b6e2016-06-17 16:07:55 -07003304 if int( numoctrl ) > 0:
Flavio Castro82ee2f62016-06-07 15:04:12 -07003305 output = output + "and %i controllers " % int( nodes )
3306 output = output + "(%i expected)" % int( numoctrl )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003307 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08003308 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003309 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08003310 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04003311 else:
You Wang24139872016-05-03 11:48:47 -07003312 main.log.info( output )
kelvin8ec71442015-01-15 16:57:00 -08003313 return result
Jon Hall42db6dc2014-10-24 19:03:48 -04003314 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003315 main.log.error( self.name + ": EOF exception found" )
3316 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003317 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003318 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003319 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003320 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003321
kelvin-onlabd3b64892015-01-20 13:26:24 -08003322 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08003323 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003324 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08003325 deviceId must be the id of a device as seen in the onos devices command
3326 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04003327 role must be either master, standby, or none
3328
Jon Halle3f39ff2015-01-13 11:50:53 -08003329 Returns:
3330 main.TRUE or main.FALSE based on argument verification and
3331 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003332 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003333 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003334 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04003335 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08003336 cmdStr = "device-role " +\
3337 str( deviceId ) + " " +\
3338 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003339 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003340 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003341 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003342 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08003343 if re.search( "Error", handle ):
3344 # end color output to escape any colours
3345 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08003346 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003347 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08003348 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08003349 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04003350 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003351 main.log.error( "Invalid 'role' given to device_role(). " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003352 "Value was '" + str( role ) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04003353 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003354 except AssertionError:
3355 main.log.exception( "" )
3356 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003357 except TypeError:
3358 main.log.exception( self.name + ": Object not as expected" )
3359 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04003360 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003361 main.log.error( self.name + ": EOF exception found" )
3362 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003363 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003364 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003365 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003366 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003367
kelvin-onlabd3b64892015-01-20 13:26:24 -08003368 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08003369 """
Jon Hall0dd09952018-04-19 09:59:11 -07003370 Lists all topology clusters
Jon Hallffb386d2014-11-21 13:43:38 -08003371 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003372 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08003373 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08003374 try:
Jon Hall0dd09952018-04-19 09:59:11 -07003375 cmdStr = "topo-clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003376 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003377 cmdStr += " -j"
3378 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003379 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003380 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07003381 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003382 except AssertionError:
3383 main.log.exception( "" )
3384 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003385 except TypeError:
3386 main.log.exception( self.name + ": Object not as expected" )
3387 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08003388 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003389 main.log.error( self.name + ": EOF exception found" )
3390 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003391 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003392 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003393 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003394 main.cleanAndExit()
Jon Hall73cf9cc2014-11-20 22:28:38 -08003395
kelvin-onlabd3b64892015-01-20 13:26:24 -08003396 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003397 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003398 CLI command to get the current leader for the Election test application
3399 NOTE: Requires installation of the onos-app-election feature
3400 Returns: Node IP of the leader if one exists
3401 None if none exists
3402 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003403 """
Jon Hall94fd0472014-12-08 11:52:42 -08003404 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003405 cmdStr = "election-test-leader"
3406 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003407 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003408 assert "Command not found:" not in response, response
Jon Halle3f39ff2015-01-13 11:50:53 -08003409 # Leader
3410 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003411 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08003412 nodeSearch = re.search( leaderPattern, response )
3413 if nodeSearch:
3414 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08003415 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003416 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08003417 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08003418 # no leader
3419 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003420 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003421 nullSearch = re.search( nullPattern, response )
3422 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08003423 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003424 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08003425 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08003426 # error
Jon Hall0e240372018-05-02 11:21:57 -07003427 main.log.error( self.name + ": Error in electionTestLeader on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003428 ": " + "unexpected response" )
3429 main.log.error( repr( response ) )
3430 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003431 except AssertionError:
3432 main.log.exception( "" )
3433 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003434 except TypeError:
3435 main.log.exception( self.name + ": Object not as expected" )
3436 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003437 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003438 main.log.error( self.name + ": EOF exception found" )
3439 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003440 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003441 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003442 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003443 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003444
kelvin-onlabd3b64892015-01-20 13:26:24 -08003445 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003446 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003447 CLI command to run for leadership of the Election test application.
3448 NOTE: Requires installation of the onos-app-election feature
3449 Returns: Main.TRUE on success
3450 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003451 """
Jon Hall94fd0472014-12-08 11:52:42 -08003452 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003453 cmdStr = "election-test-run"
3454 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003455 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003456 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003457 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003458 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003459 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003460 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08003461 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08003462 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003463 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003464 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003465 # error
Jon Hall0e240372018-05-02 11:21:57 -07003466 main.log.error( self.name + ": Error in electionTestRun on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003467 ": " + "unexpected response" )
3468 main.log.error( repr( response ) )
3469 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003470 except AssertionError:
3471 main.log.exception( "" )
3472 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003473 except TypeError:
3474 main.log.exception( self.name + ": Object not as expected" )
3475 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003476 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003477 main.log.error( self.name + ": EOF exception found" )
3478 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003479 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003480 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003481 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003482 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003483
kelvin-onlabd3b64892015-01-20 13:26:24 -08003484 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08003485 """
Jon Hall94fd0472014-12-08 11:52:42 -08003486 * CLI command to withdraw the local node from leadership election for
3487 * the Election test application.
3488 #NOTE: Requires installation of the onos-app-election feature
3489 Returns: Main.TRUE on success
3490 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08003491 """
Jon Hall94fd0472014-12-08 11:52:42 -08003492 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003493 cmdStr = "election-test-withdraw"
3494 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003495 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003496 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003497 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003498 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003499 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003500 if re.search( successPattern, response ):
3501 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003502 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003503 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003504 # error
Jon Hall0e240372018-05-02 11:21:57 -07003505 main.log.error( self.name + ": Error in electionTestWithdraw on " +
Jon Hall97cf84a2016-06-20 13:35:58 -07003506 self.name + ": " + "unexpected response" )
3507 main.log.error( repr( response ) )
3508 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003509 except AssertionError:
3510 main.log.exception( "" )
3511 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003512 except TypeError:
3513 main.log.exception( self.name + ": Object not as expected" )
3514 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003515 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003516 main.log.error( self.name + ": EOF exception found" )
3517 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003518 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003519 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003520 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003521 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003522
kelvin8ec71442015-01-15 16:57:00 -08003523 def getDevicePortsEnabledCount( self, dpid ):
3524 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003525 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003526 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003527 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003528 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003529 cmdStr = "onos:ports -e " + dpid + " | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003530 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003531 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003532 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003533 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003534 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003535 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003536 return output
Jon Hallc6793552016-01-19 14:18:37 -08003537 except AssertionError:
3538 main.log.exception( "" )
3539 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003540 except TypeError:
3541 main.log.exception( self.name + ": Object not as expected" )
3542 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003543 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003544 main.log.error( self.name + ": EOF exception found" )
3545 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003546 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003547 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003548 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003549 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003550
kelvin8ec71442015-01-15 16:57:00 -08003551 def getDeviceLinksActiveCount( self, dpid ):
3552 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003553 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003554 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003555 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003556 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003557 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003558 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003559 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003560 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003561 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003562 main.log.error( self.name + ": Error in getting ports " )
kelvin-onlab898a6c62015-01-16 14:13:53 -08003563 return ( output, "Error " )
Jon Halla495f562016-05-16 18:03:26 -07003564 return output
Jon Hallc6793552016-01-19 14:18:37 -08003565 except AssertionError:
3566 main.log.exception( "" )
3567 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003568 except TypeError:
3569 main.log.exception( self.name + ": Object not as expected" )
3570 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003571 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003572 main.log.error( self.name + ": EOF exception found" )
3573 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003574 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003575 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003576 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003577 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003578
kelvin8ec71442015-01-15 16:57:00 -08003579 def getAllIntentIds( self ):
3580 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003581 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08003582 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003583 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003584 cmdStr = "onos:intents | grep id="
3585 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003586 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003587 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003588 if re.search( "Error", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003589 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003590 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003591 return output
Jon Hallc6793552016-01-19 14:18:37 -08003592 except AssertionError:
3593 main.log.exception( "" )
3594 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003595 except TypeError:
3596 main.log.exception( self.name + ": Object not as expected" )
3597 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003598 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003599 main.log.error( self.name + ": EOF exception found" )
3600 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003601 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003602 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003603 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003604 main.cleanAndExit()
Jon Halld4d4b372015-01-28 16:02:41 -08003605
Jon Hall73509952015-02-24 16:42:56 -08003606 def intentSummary( self ):
3607 """
Jon Hallefbd9792015-03-05 16:11:36 -08003608 Returns a dictionary containing the current intent states and the count
Jon Hall73509952015-02-24 16:42:56 -08003609 """
3610 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003611 intents = self.intents( )
Jon Hall08f61bc2015-04-13 16:00:30 -07003612 states = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003613 for intent in json.loads( intents ):
Jon Hall08f61bc2015-04-13 16:00:30 -07003614 states.append( intent.get( 'state', None ) )
3615 out = [ ( i, states.count( i ) ) for i in set( states ) ]
Jon Hall63604932015-02-26 17:09:50 -08003616 main.log.info( dict( out ) )
Jon Hall73509952015-02-24 16:42:56 -08003617 return dict( out )
Jon Hallc6793552016-01-19 14:18:37 -08003618 except ( TypeError, ValueError ):
3619 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intents ) )
Jon Hall73509952015-02-24 16:42:56 -08003620 return None
3621 except pexpect.EOF:
3622 main.log.error( self.name + ": EOF exception found" )
3623 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003624 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003625 except Exception:
Jon Hall73509952015-02-24 16:42:56 -08003626 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003627 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003628
Jon Hall61282e32015-03-19 11:34:11 -07003629 def leaders( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003630 """
3631 Returns the output of the leaders command.
Jon Hall61282e32015-03-19 11:34:11 -07003632 Optional argument:
3633 * jsonFormat - boolean indicating if you want output in json
Jon Hall63604932015-02-26 17:09:50 -08003634 """
Jon Hall63604932015-02-26 17:09:50 -08003635 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003636 cmdStr = "onos:leaders"
Jon Hall61282e32015-03-19 11:34:11 -07003637 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003638 cmdStr += " -j"
3639 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003640 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003641 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003642 return output
Jon Hallc6793552016-01-19 14:18:37 -08003643 except AssertionError:
3644 main.log.exception( "" )
3645 return None
Jon Hall63604932015-02-26 17:09:50 -08003646 except TypeError:
3647 main.log.exception( self.name + ": Object not as expected" )
3648 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003649 except pexpect.EOF:
3650 main.log.error( self.name + ": EOF exception found" )
3651 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003652 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003653 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003654 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003655 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003656
acsmarsa4a4d1e2015-07-10 16:01:24 -07003657 def leaderCandidates( self, jsonFormat=True ):
3658 """
3659 Returns the output of the leaders -c command.
3660 Optional argument:
3661 * jsonFormat - boolean indicating if you want output in json
3662 """
3663 try:
3664 cmdStr = "onos:leaders -c"
3665 if jsonFormat:
3666 cmdStr += " -j"
3667 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003668 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003669 assert "Command not found:" not in output, output
acsmarsa4a4d1e2015-07-10 16:01:24 -07003670 return output
Jon Hallc6793552016-01-19 14:18:37 -08003671 except AssertionError:
3672 main.log.exception( "" )
3673 return None
acsmarsa4a4d1e2015-07-10 16:01:24 -07003674 except TypeError:
3675 main.log.exception( self.name + ": Object not as expected" )
3676 return None
3677 except pexpect.EOF:
3678 main.log.error( self.name + ": EOF exception found" )
3679 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003680 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003681 except Exception:
3682 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003683 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003684
Jon Hallc6793552016-01-19 14:18:37 -08003685 def specificLeaderCandidate( self, topic ):
acsmarsa4a4d1e2015-07-10 16:01:24 -07003686 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003687 Returns a list in format [leader,candidate1,candidate2,...] for a given
acsmarsa4a4d1e2015-07-10 16:01:24 -07003688 topic parameter and an empty list if the topic doesn't exist
3689 If no leader is elected leader in the returned list will be "none"
3690 Returns None if there is a type error processing the json object
3691 """
3692 try:
Jon Hall6e709752016-02-01 13:38:46 -08003693 cmdStr = "onos:leaders -j"
Jon Hallc6793552016-01-19 14:18:37 -08003694 rawOutput = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003695 assert rawOutput is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003696 assert "Command not found:" not in rawOutput, rawOutput
3697 output = json.loads( rawOutput )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003698 results = []
3699 for dict in output:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003700 if dict[ "topic" ] == topic:
3701 leader = dict[ "leader" ]
3702 candidates = re.split( ", ", dict[ "candidates" ][ 1:-1 ] )
Jon Hallc6793552016-01-19 14:18:37 -08003703 results.append( leader )
3704 results.extend( candidates )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003705 return results
Jon Hallc6793552016-01-19 14:18:37 -08003706 except AssertionError:
3707 main.log.exception( "" )
3708 return None
3709 except ( TypeError, ValueError ):
3710 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawOutput ) )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003711 return None
3712 except pexpect.EOF:
3713 main.log.error( self.name + ": EOF exception found" )
3714 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003715 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003716 except Exception:
3717 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003718 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003719
Jon Hall61282e32015-03-19 11:34:11 -07003720 def pendingMap( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003721 """
3722 Returns the output of the intent Pending map.
3723 """
Jon Hall63604932015-02-26 17:09:50 -08003724 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003725 cmdStr = "onos:intents -p"
Jon Hall61282e32015-03-19 11:34:11 -07003726 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003727 cmdStr += " -j"
3728 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003729 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003730 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003731 return output
Jon Hallc6793552016-01-19 14:18:37 -08003732 except AssertionError:
3733 main.log.exception( "" )
3734 return None
Jon Hall63604932015-02-26 17:09:50 -08003735 except TypeError:
3736 main.log.exception( self.name + ": Object not as expected" )
3737 return None
3738 except pexpect.EOF:
3739 main.log.error( self.name + ": EOF exception found" )
3740 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003741 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003742 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003743 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003744 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003745
Jon Hall2c8959e2016-12-16 12:17:34 -08003746 def partitions( self, candidates=False, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003747 """
3748 Returns the output of the raft partitions command for ONOS.
3749 """
Jon Hall61282e32015-03-19 11:34:11 -07003750 # Sample JSON
3751 # {
3752 # "leader": "tcp://10.128.30.11:7238",
3753 # "members": [
3754 # "tcp://10.128.30.11:7238",
3755 # "tcp://10.128.30.17:7238",
3756 # "tcp://10.128.30.13:7238",
3757 # ],
3758 # "name": "p1",
3759 # "term": 3
3760 # },
Jon Hall63604932015-02-26 17:09:50 -08003761 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003762 cmdStr = "onos:partitions"
Jon Hall2c8959e2016-12-16 12:17:34 -08003763 if candidates:
3764 cmdStr += " -c"
Jon Hall61282e32015-03-19 11:34:11 -07003765 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003766 cmdStr += " -j"
3767 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003768 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003769 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003770 return output
Jon Hallc6793552016-01-19 14:18:37 -08003771 except AssertionError:
3772 main.log.exception( "" )
3773 return None
Jon Hall63604932015-02-26 17:09:50 -08003774 except TypeError:
3775 main.log.exception( self.name + ": Object not as expected" )
3776 return None
3777 except pexpect.EOF:
3778 main.log.error( self.name + ": EOF exception found" )
3779 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003780 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003781 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003782 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003783 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003784
Jon Halle9f909e2016-09-23 10:43:12 -07003785 def apps( self, summary=False, active=False, jsonFormat=True ):
Jon Hallbe379602015-03-24 13:39:32 -07003786 """
3787 Returns the output of the apps command for ONOS. This command lists
3788 information about installed ONOS applications
3789 """
3790 # Sample JSON object
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003791 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
Jon Hallbe379602015-03-24 13:39:32 -07003792 # "description":"ONOS OpenFlow protocol southbound providers",
3793 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003794 # "features":"[onos-openflow]","state":"ACTIVE"}]
Jon Hallbe379602015-03-24 13:39:32 -07003795 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003796 cmdStr = "onos:apps"
Jon Hallf03ae762019-01-22 13:25:27 -08003797 expectJson = False
Jon Halle9f909e2016-09-23 10:43:12 -07003798 if summary:
3799 cmdStr += " -s"
3800 if active:
3801 cmdStr += " -a"
Jon Hallbe379602015-03-24 13:39:32 -07003802 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003803 cmdStr += " -j"
Jon Hallf03ae762019-01-22 13:25:27 -08003804 expectJson = True
3805 output = self.sendline( cmdStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07003806 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003807 assert "Command not found:" not in output, output
3808 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003809 return output
Jon Hallbe379602015-03-24 13:39:32 -07003810 # FIXME: look at specific exceptions/Errors
3811 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07003812 main.log.exception( self.name + ": Error in processing onos:app command." )
Jon Hallbe379602015-03-24 13:39:32 -07003813 return None
3814 except TypeError:
3815 main.log.exception( self.name + ": Object not as expected" )
3816 return None
3817 except pexpect.EOF:
3818 main.log.error( self.name + ": EOF exception found" )
3819 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003820 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003821 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003822 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003823 main.cleanAndExit()
Jon Hallbe379602015-03-24 13:39:32 -07003824
You Wangcdc51fe2018-08-12 17:14:56 -07003825 def appStatus( self, appName ):
Jon Hall146f1522015-03-24 15:33:24 -07003826 """
3827 Uses the onos:apps cli command to return the status of an application.
3828 Returns:
3829 "ACTIVE" - If app is installed and activated
3830 "INSTALLED" - If app is installed and deactivated
3831 "UNINSTALLED" - If app is not installed
3832 None - on error
3833 """
Jon Hall146f1522015-03-24 15:33:24 -07003834 try:
3835 if not isinstance( appName, types.StringType ):
3836 main.log.error( self.name + ".appStatus(): appName must be" +
3837 " a string" )
3838 return None
3839 output = self.apps( jsonFormat=True )
3840 appsJson = json.loads( output )
3841 state = None
3842 for app in appsJson:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003843 if appName == app.get( 'name' ):
3844 state = app.get( 'state' )
Jon Hall146f1522015-03-24 15:33:24 -07003845 break
3846 if state == "ACTIVE" or state == "INSTALLED":
3847 return state
3848 elif state is None:
You Wang0d9f2c02018-08-10 14:56:32 -07003849 main.log.warn( "{} app not found".format( appName ) )
Jon Hall146f1522015-03-24 15:33:24 -07003850 return "UNINSTALLED"
3851 elif state:
3852 main.log.error( "Unexpected state from 'onos:apps': " +
3853 str( state ) )
3854 return state
Jon Hallc6793552016-01-19 14:18:37 -08003855 except ( TypeError, ValueError ):
3856 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003857 return None
3858 except pexpect.EOF:
3859 main.log.error( self.name + ": EOF exception found" )
3860 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003861 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003862 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003863 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003864 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003865
Jon Hallbe379602015-03-24 13:39:32 -07003866 def app( self, appName, option ):
3867 """
3868 Interacts with the app command for ONOS. This command manages
3869 application inventory.
3870 """
Jon Hallbe379602015-03-24 13:39:32 -07003871 try:
Jon Hallbd16b922015-03-26 17:53:15 -07003872 # Validate argument types
3873 valid = True
3874 if not isinstance( appName, types.StringType ):
3875 main.log.error( self.name + ".app(): appName must be a " +
3876 "string" )
3877 valid = False
3878 if not isinstance( option, types.StringType ):
3879 main.log.error( self.name + ".app(): option must be a string" )
3880 valid = False
3881 if not valid:
3882 return main.FALSE
3883 # Validate Option
3884 option = option.lower()
3885 # NOTE: Install may become a valid option
3886 if option == "activate":
3887 pass
3888 elif option == "deactivate":
3889 pass
3890 elif option == "uninstall":
3891 pass
3892 else:
3893 # Invalid option
3894 main.log.error( "The ONOS app command argument only takes " +
3895 "the values: (activate|deactivate|uninstall)" +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003896 "; was given '" + option + "'" )
Jon Hallbd16b922015-03-26 17:53:15 -07003897 return main.FALSE
Jon Hall146f1522015-03-24 15:33:24 -07003898 cmdStr = "onos:app " + option + " " + appName
Jon Hallbe379602015-03-24 13:39:32 -07003899 output = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003900 assert output is not None, "Error in sendline"
3901 assert "Command not found:" not in output, output
Jon Hallbe379602015-03-24 13:39:32 -07003902 if "Error executing command" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003903 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hallbe379602015-03-24 13:39:32 -07003904 str( output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003905 return main.FALSE
Jon Hallbe379602015-03-24 13:39:32 -07003906 elif "No such application" in output:
3907 main.log.error( "The application '" + appName +
3908 "' is not installed in ONOS" )
Jon Hall146f1522015-03-24 15:33:24 -07003909 return main.FALSE
3910 elif "Command not found:" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003911 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hall146f1522015-03-24 15:33:24 -07003912 str( output ) )
3913 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003914 elif "Unsupported command:" in output:
3915 main.log.error( "Incorrect command given to 'app': " +
3916 str( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003917 # NOTE: we may need to add more checks here
Jon Hallbd16b922015-03-26 17:53:15 -07003918 # else: Command was successful
Jon Hall08f61bc2015-04-13 16:00:30 -07003919 # main.log.debug( "app response: " + repr( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003920 return main.TRUE
You Wangb5a55f72017-03-03 12:51:05 -08003921 except AssertionError:
3922 main.log.exception( self.name + ": AssertionError exception found" )
3923 return main.ERROR
Jon Hallbe379602015-03-24 13:39:32 -07003924 except TypeError:
3925 main.log.exception( self.name + ": Object not as expected" )
3926 return main.ERROR
3927 except pexpect.EOF:
3928 main.log.error( self.name + ": EOF exception found" )
3929 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003930 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003931 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003932 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003933 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003934
Jon Hallbd16b922015-03-26 17:53:15 -07003935 def activateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003936 """
3937 Activate an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003938 appName is the hierarchical app name, not the feature name
3939 If check is True, method will check the status of the app after the
3940 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003941 Returns main.TRUE if the command was successfully sent
3942 main.FALSE if the cli responded with an error or given
3943 incorrect input
3944 """
3945 try:
3946 if not isinstance( appName, types.StringType ):
3947 main.log.error( self.name + ".activateApp(): appName must be" +
3948 " a string" )
3949 return main.FALSE
3950 status = self.appStatus( appName )
3951 if status == "INSTALLED":
3952 response = self.app( appName, "activate" )
Jon Hallbd16b922015-03-26 17:53:15 -07003953 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003954 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07003955 status = self.appStatus( appName )
3956 if status == "ACTIVE":
3957 return main.TRUE
3958 else:
Jon Hall050e1bd2015-03-30 13:33:02 -07003959 main.log.debug( "The state of application " +
3960 appName + " is " + status )
Jon Hallbd16b922015-03-26 17:53:15 -07003961 time.sleep( 1 )
3962 return main.FALSE
3963 else: # not 'check' or command didn't succeed
3964 return response
Jon Hall146f1522015-03-24 15:33:24 -07003965 elif status == "ACTIVE":
3966 return main.TRUE
3967 elif status == "UNINSTALLED":
3968 main.log.error( self.name + ": Tried to activate the " +
3969 "application '" + appName + "' which is not " +
3970 "installed." )
3971 else:
3972 main.log.error( "Unexpected return value from appStatus: " +
3973 str( status ) )
3974 return main.ERROR
3975 except TypeError:
3976 main.log.exception( self.name + ": Object not as expected" )
3977 return main.ERROR
3978 except pexpect.EOF:
3979 main.log.error( self.name + ": EOF exception found" )
3980 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003981 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003982 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003983 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003984 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003985
Jon Hallbd16b922015-03-26 17:53:15 -07003986 def deactivateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003987 """
3988 Deactivate an app that is already activated in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003989 appName is the hierarchical app name, not the feature name
3990 If check is True, method will check the status of the app after the
3991 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003992 Returns main.TRUE if the command was successfully sent
3993 main.FALSE if the cli responded with an error or given
3994 incorrect input
3995 """
3996 try:
3997 if not isinstance( appName, types.StringType ):
3998 main.log.error( self.name + ".deactivateApp(): appName must " +
3999 "be a string" )
4000 return main.FALSE
4001 status = self.appStatus( appName )
4002 if status == "INSTALLED":
4003 return main.TRUE
4004 elif status == "ACTIVE":
4005 response = self.app( appName, "deactivate" )
Jon Hallbd16b922015-03-26 17:53:15 -07004006 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004007 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004008 status = self.appStatus( appName )
4009 if status == "INSTALLED":
4010 return main.TRUE
4011 else:
4012 time.sleep( 1 )
4013 return main.FALSE
4014 else: # not check or command didn't succeed
4015 return response
Jon Hall146f1522015-03-24 15:33:24 -07004016 elif status == "UNINSTALLED":
4017 main.log.warn( self.name + ": Tried to deactivate the " +
4018 "application '" + appName + "' which is not " +
4019 "installed." )
4020 return main.TRUE
4021 else:
4022 main.log.error( "Unexpected return value from appStatus: " +
4023 str( status ) )
4024 return main.ERROR
4025 except TypeError:
4026 main.log.exception( self.name + ": Object not as expected" )
4027 return main.ERROR
4028 except pexpect.EOF:
4029 main.log.error( self.name + ": EOF exception found" )
4030 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004031 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004032 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004033 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004034 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004035
Jon Hallbd16b922015-03-26 17:53:15 -07004036 def uninstallApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004037 """
4038 Uninstall an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004039 appName is the hierarchical app name, not the feature name
4040 If check is True, method will check the status of the app after the
4041 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004042 Returns main.TRUE if the command was successfully sent
4043 main.FALSE if the cli responded with an error or given
4044 incorrect input
4045 """
4046 # TODO: check with Thomas about the state machine for apps
4047 try:
4048 if not isinstance( appName, types.StringType ):
4049 main.log.error( self.name + ".uninstallApp(): appName must " +
4050 "be a string" )
4051 return main.FALSE
4052 status = self.appStatus( appName )
4053 if status == "INSTALLED":
4054 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004055 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004056 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004057 status = self.appStatus( appName )
4058 if status == "UNINSTALLED":
4059 return main.TRUE
4060 else:
4061 time.sleep( 1 )
4062 return main.FALSE
4063 else: # not check or command didn't succeed
4064 return response
Jon Hall146f1522015-03-24 15:33:24 -07004065 elif status == "ACTIVE":
4066 main.log.warn( self.name + ": Tried to uninstall the " +
4067 "application '" + appName + "' which is " +
4068 "currently active." )
4069 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004070 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004071 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004072 status = self.appStatus( appName )
4073 if status == "UNINSTALLED":
4074 return main.TRUE
4075 else:
4076 time.sleep( 1 )
4077 return main.FALSE
4078 else: # not check or command didn't succeed
4079 return response
Jon Hall146f1522015-03-24 15:33:24 -07004080 elif status == "UNINSTALLED":
4081 return main.TRUE
4082 else:
4083 main.log.error( "Unexpected return value from appStatus: " +
4084 str( status ) )
4085 return main.ERROR
4086 except TypeError:
4087 main.log.exception( self.name + ": Object not as expected" )
4088 return main.ERROR
4089 except pexpect.EOF:
4090 main.log.error( self.name + ": EOF exception found" )
4091 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004092 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004093 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004094 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004095 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004096
4097 def appIDs( self, jsonFormat=True ):
4098 """
4099 Show the mappings between app id and app names given by the 'app-ids'
4100 cli command
4101 """
4102 try:
4103 cmdStr = "app-ids"
4104 if jsonFormat:
4105 cmdStr += " -j"
Jon Hallc6358dd2015-04-10 12:44:28 -07004106 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004107 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004108 assert "Command not found:" not in output, output
4109 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07004110 return output
Jon Hallbd16b922015-03-26 17:53:15 -07004111 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004112 main.log.exception( self.name + ": Error in processing onos:app-ids command." )
Jon Hallbd16b922015-03-26 17:53:15 -07004113 return None
4114 except TypeError:
4115 main.log.exception( self.name + ": Object not as expected" )
4116 return None
4117 except pexpect.EOF:
4118 main.log.error( self.name + ": EOF exception found" )
4119 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004120 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004121 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004122 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004123 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004124
4125 def appToIDCheck( self ):
4126 """
4127 This method will check that each application's ID listed in 'apps' is
4128 the same as the ID listed in 'app-ids'. The check will also check that
4129 there are no duplicate IDs issued. Note that an app ID should be
4130 a globaly unique numerical identifier for app/app-like features. Once
4131 an ID is registered, the ID is never freed up so that if an app is
4132 reinstalled it will have the same ID.
4133
4134 Returns: main.TRUE if the check passes and
4135 main.FALSE if the check fails or
4136 main.ERROR if there is some error in processing the test
4137 """
4138 try:
Jon Hall0e240372018-05-02 11:21:57 -07004139 # Grab IDs
Jon Hallc6793552016-01-19 14:18:37 -08004140 rawJson = self.appIDs( jsonFormat=True )
4141 if rawJson:
4142 ids = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004143 else:
Jon Hall0e240372018-05-02 11:21:57 -07004144 main.log.error( "app-ids returned nothing: " + repr( rawJson ) )
4145 return main.FALSE
4146
4147 # Grab Apps
Jon Hallc6793552016-01-19 14:18:37 -08004148 rawJson = self.apps( jsonFormat=True )
4149 if rawJson:
4150 apps = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004151 else:
Jon Hallc6793552016-01-19 14:18:37 -08004152 main.log.error( "apps returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07004153 return main.FALSE
Jon Hall0e240372018-05-02 11:21:57 -07004154
Jon Hallbd16b922015-03-26 17:53:15 -07004155 result = main.TRUE
4156 for app in apps:
4157 appID = app.get( 'id' )
4158 if appID is None:
4159 main.log.error( "Error parsing app: " + str( app ) )
4160 result = main.FALSE
4161 appName = app.get( 'name' )
4162 if appName is None:
4163 main.log.error( "Error parsing app: " + str( app ) )
4164 result = main.FALSE
4165 # get the entry in ids that has the same appID
Jon Hall390696c2015-05-05 17:13:41 -07004166 current = filter( lambda item: item[ 'id' ] == appID, ids )
Jon Hallbd16b922015-03-26 17:53:15 -07004167 if not current: # if ids doesn't have this id
4168 result = main.FALSE
4169 main.log.error( "'app-ids' does not have the ID for " +
4170 str( appName ) + " that apps does." )
Jon Hallb9d381e2018-02-05 12:02:10 -08004171 main.log.debug( "apps command returned: " + str( app ) +
4172 "; app-ids has: " + str( ids ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004173 elif len( current ) > 1:
4174 # there is more than one app with this ID
4175 result = main.FALSE
4176 # We will log this later in the method
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004177 elif not current[ 0 ][ 'name' ] == appName:
4178 currentName = current[ 0 ][ 'name' ]
Jon Hallbd16b922015-03-26 17:53:15 -07004179 result = main.FALSE
4180 main.log.error( "'app-ids' has " + str( currentName ) +
4181 " registered under id:" + str( appID ) +
4182 " but 'apps' has " + str( appName ) )
4183 else:
4184 pass # id and name match!
Jon Hall0e240372018-05-02 11:21:57 -07004185
Jon Hallbd16b922015-03-26 17:53:15 -07004186 # now make sure that app-ids has no duplicates
4187 idsList = []
4188 namesList = []
4189 for item in ids:
4190 idsList.append( item[ 'id' ] )
4191 namesList.append( item[ 'name' ] )
4192 if len( idsList ) != len( set( idsList ) ) or\
4193 len( namesList ) != len( set( namesList ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004194 main.log.error( "'app-ids' has some duplicate entries: \n"
4195 + json.dumps( ids,
4196 sort_keys=True,
4197 indent=4,
4198 separators=( ',', ': ' ) ) )
4199 result = main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07004200 return result
Jon Hallc6793552016-01-19 14:18:37 -08004201 except ( TypeError, ValueError ):
4202 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004203 return main.ERROR
4204 except pexpect.EOF:
4205 main.log.error( self.name + ": EOF exception found" )
4206 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004207 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004208 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004209 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004210 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004211
Jon Hallfb760a02015-04-13 15:35:03 -07004212 def getCfg( self, component=None, propName=None, short=False,
4213 jsonFormat=True ):
4214 """
4215 Get configuration settings from onos cli
4216 Optional arguments:
4217 component - Optionally only list configurations for a specific
4218 component. If None, all components with configurations
4219 are displayed. Case Sensitive string.
4220 propName - If component is specified, propName option will show
4221 only this specific configuration from that component.
4222 Case Sensitive string.
4223 jsonFormat - Returns output as json. Note that this will override
4224 the short option
4225 short - Short, less verbose, version of configurations.
4226 This is overridden by the json option
4227 returns:
4228 Output from cli as a string or None on error
4229 """
4230 try:
4231 baseStr = "cfg"
4232 cmdStr = " get"
4233 componentStr = ""
4234 if component:
4235 componentStr += " " + component
4236 if propName:
4237 componentStr += " " + propName
4238 if jsonFormat:
4239 baseStr += " -j"
Jon Hall22e94ce2019-01-15 14:52:17 -08004240 expectJson = True
Jon Hallfb760a02015-04-13 15:35:03 -07004241 elif short:
4242 baseStr += " -s"
Jon Hall22e94ce2019-01-15 14:52:17 -08004243 expectJson = False
4244 output = self.sendline( baseStr + cmdStr + componentStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07004245 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004246 assert "Command not found:" not in output, output
4247 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004248 return output
4249 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004250 main.log.exception( self.name + ": Error in processing 'cfg get' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004251 return None
4252 except TypeError:
4253 main.log.exception( self.name + ": Object not as expected" )
4254 return None
4255 except pexpect.EOF:
4256 main.log.error( self.name + ": EOF exception found" )
4257 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004258 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004259 except Exception:
4260 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004261 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004262
4263 def setCfg( self, component, propName, value=None, check=True ):
4264 """
4265 Set/Unset configuration settings from ONOS cli
Jon Hall390696c2015-05-05 17:13:41 -07004266 Required arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004267 component - The case sensitive name of the component whose
4268 property is to be set
4269 propName - The case sensitive name of the property to be set/unset
Jon Hall390696c2015-05-05 17:13:41 -07004270 Optional arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004271 value - The value to set the property to. If None, will unset the
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004272 property and revert it to it's default value(if applicable)
Jon Hallfb760a02015-04-13 15:35:03 -07004273 check - Boolean, Check whether the option was successfully set this
4274 only applies when a value is given.
4275 returns:
4276 main.TRUE on success or main.FALSE on failure. If check is False,
4277 will return main.TRUE unless there is an error
4278 """
4279 try:
4280 baseStr = "cfg"
4281 cmdStr = " set " + str( component ) + " " + str( propName )
4282 if value is not None:
4283 cmdStr += " " + str( value )
4284 output = self.sendline( baseStr + cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004285 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004286 assert "Command not found:" not in output, output
4287 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004288 if value and check:
4289 results = self.getCfg( component=str( component ),
4290 propName=str( propName ),
4291 jsonFormat=True )
4292 # Check if current value is what we just set
4293 try:
4294 jsonOutput = json.loads( results )
4295 current = jsonOutput[ 'value' ]
Jon Hallc6793552016-01-19 14:18:37 -08004296 except ( TypeError, ValueError ):
Jon Hallfb760a02015-04-13 15:35:03 -07004297 main.log.exception( "Error parsing cfg output" )
4298 main.log.error( "output:" + repr( results ) )
4299 return main.FALSE
4300 if current == str( value ):
4301 return main.TRUE
4302 return main.FALSE
4303 return main.TRUE
4304 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004305 main.log.exception( self.name + ": Error in processing 'cfg set' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004306 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08004307 except ( TypeError, ValueError ):
4308 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, results ) )
Jon Hallfb760a02015-04-13 15:35:03 -07004309 return main.FALSE
4310 except pexpect.EOF:
4311 main.log.error( self.name + ": EOF exception found" )
4312 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004313 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004314 except Exception:
4315 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004316 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004317
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004318 def distPrimitivesSend( self, cmd ):
4319 """
4320 Function to handle sending cli commands for the distributed primitives test app
4321
4322 This command will catch some exceptions and retry the command on some
4323 specific store exceptions.
4324
4325 Required arguments:
4326 cmd - The command to send to the cli
4327 returns:
4328 string containing the cli output
4329 None on Error
4330 """
4331 try:
4332 output = self.sendline( cmd )
4333 try:
4334 assert output is not None, "Error in sendline"
4335 # TODO: Maybe make this less hardcoded
4336 # ConsistentMap Exceptions
4337 assert "org.onosproject.store.service" not in output
4338 # Node not leader
4339 assert "java.lang.IllegalStateException" not in output
4340 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004341 main.log.error( self.name + ": Error in processing '" + cmd + "' " +
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004342 "command: " + str( output ) )
4343 retryTime = 30 # Conservative time, given by Madan
4344 main.log.info( "Waiting " + str( retryTime ) +
4345 "seconds before retrying." )
4346 time.sleep( retryTime ) # Due to change in mastership
4347 output = self.sendline( cmd )
4348 assert output is not None, "Error in sendline"
4349 assert "Command not found:" not in output, output
4350 assert "Error executing command" not in output, output
4351 main.log.info( self.name + ": " + output )
4352 return output
4353 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004354 main.log.exception( self.name + ": Error in processing '" + cmd + "' command." )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004355 return None
4356 except TypeError:
4357 main.log.exception( self.name + ": Object not as expected" )
4358 return None
4359 except pexpect.EOF:
4360 main.log.error( self.name + ": EOF exception found" )
4361 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004362 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004363 except Exception:
4364 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004365 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004366
Jon Hall390696c2015-05-05 17:13:41 -07004367 def setTestAdd( self, setName, values ):
4368 """
4369 CLI command to add elements to a distributed set.
4370 Arguments:
4371 setName - The name of the set to add to.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004372 values - The value(s) to add to the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004373 Example usages:
4374 setTestAdd( "set1", "a b c" )
4375 setTestAdd( "set2", "1" )
4376 returns:
4377 main.TRUE on success OR
4378 main.FALSE if elements were already in the set OR
4379 main.ERROR on error
4380 """
4381 try:
4382 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004383 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004384 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
4385 negativeMatch = "\[(.*)\] was already in set " + str( setName )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004386 if re.search( positiveMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004387 return main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004388 elif re.search( negativeMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004389 return main.FALSE
4390 else:
4391 main.log.error( self.name + ": setTestAdd did not" +
4392 " match expected output" )
Jon Hall390696c2015-05-05 17:13:41 -07004393 main.log.debug( self.name + " actual: " + repr( output ) )
4394 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004395 except TypeError:
4396 main.log.exception( self.name + ": Object not as expected" )
4397 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004398 except Exception:
4399 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004400 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004401
4402 def setTestRemove( self, setName, values, clear=False, retain=False ):
4403 """
4404 CLI command to remove elements from a distributed set.
4405 Required arguments:
4406 setName - The name of the set to remove from.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004407 values - The value(s) to remove from the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004408 Optional arguments:
4409 clear - Clear all elements from the set
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004410 retain - Retain only the given values. (intersection of the
4411 original set and the given set)
Jon Hall390696c2015-05-05 17:13:41 -07004412 returns:
4413 main.TRUE on success OR
4414 main.FALSE if the set was not changed OR
4415 main.ERROR on error
4416 """
4417 try:
4418 cmdStr = "set-test-remove "
4419 if clear:
4420 cmdStr += "-c " + str( setName )
4421 elif retain:
4422 cmdStr += "-r " + str( setName ) + " " + str( values )
4423 else:
4424 cmdStr += str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004425 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004426 if clear:
4427 pattern = "Set " + str( setName ) + " cleared"
4428 if re.search( pattern, output ):
4429 return main.TRUE
4430 elif retain:
4431 positivePattern = str( setName ) + " was pruned to contain " +\
4432 "only elements of set \[(.*)\]"
4433 negativePattern = str( setName ) + " was not changed by " +\
4434 "retaining only elements of the set " +\
4435 "\[(.*)\]"
4436 if re.search( positivePattern, output ):
4437 return main.TRUE
4438 elif re.search( negativePattern, output ):
4439 return main.FALSE
4440 else:
4441 positivePattern = "\[(.*)\] was removed from the set " +\
4442 str( setName )
4443 if ( len( values.split() ) == 1 ):
4444 negativePattern = "\[(.*)\] was not in set " +\
4445 str( setName )
4446 else:
4447 negativePattern = "No element of \[(.*)\] was in set " +\
4448 str( setName )
4449 if re.search( positivePattern, output ):
4450 return main.TRUE
4451 elif re.search( negativePattern, output ):
4452 return main.FALSE
4453 main.log.error( self.name + ": setTestRemove did not" +
4454 " match expected output" )
4455 main.log.debug( self.name + " expected: " + pattern )
4456 main.log.debug( self.name + " actual: " + repr( output ) )
4457 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004458 except TypeError:
4459 main.log.exception( self.name + ": Object not as expected" )
4460 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004461 except Exception:
4462 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004463 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004464
4465 def setTestGet( self, setName, values="" ):
4466 """
4467 CLI command to get the elements in a distributed set.
4468 Required arguments:
4469 setName - The name of the set to remove from.
4470 Optional arguments:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004471 values - The value(s) to check if in the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004472 returns:
4473 main.ERROR on error OR
4474 A list of elements in the set if no optional arguments are
4475 supplied OR
4476 A tuple containing the list then:
4477 main.FALSE if the given values are not in the set OR
4478 main.TRUE if the given values are in the set OR
4479 """
4480 try:
4481 values = str( values ).strip()
4482 setName = str( setName ).strip()
4483 length = len( values.split() )
4484 containsCheck = None
4485 # Patterns to match
4486 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004487 pattern = "Items in set " + setName + ":\r\n" + setPattern
Jon Hall390696c2015-05-05 17:13:41 -07004488 containsTrue = "Set " + setName + " contains the value " + values
4489 containsFalse = "Set " + setName + " did not contain the value " +\
4490 values
4491 containsAllTrue = "Set " + setName + " contains the the subset " +\
4492 setPattern
4493 containsAllFalse = "Set " + setName + " did not contain the the" +\
4494 " subset " + setPattern
4495
4496 cmdStr = "set-test-get "
4497 cmdStr += setName + " " + values
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004498 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004499 if length == 0:
4500 match = re.search( pattern, output )
4501 else: # if given values
4502 if length == 1: # Contains output
Jon Hall54b994f2016-12-05 10:48:59 -08004503 patternTrue = pattern + "\r\n" + containsTrue
4504 patternFalse = pattern + "\r\n" + containsFalse
Jon Hall390696c2015-05-05 17:13:41 -07004505 else: # ContainsAll output
Jon Hall54b994f2016-12-05 10:48:59 -08004506 patternTrue = pattern + "\r\n" + containsAllTrue
4507 patternFalse = pattern + "\r\n" + containsAllFalse
Jon Hall390696c2015-05-05 17:13:41 -07004508 matchTrue = re.search( patternTrue, output )
4509 matchFalse = re.search( patternFalse, output )
4510 if matchTrue:
4511 containsCheck = main.TRUE
4512 match = matchTrue
4513 elif matchFalse:
4514 containsCheck = main.FALSE
4515 match = matchFalse
4516 else:
Jon Halle0f0b342017-04-18 11:43:47 -07004517 main.log.error( self.name + " setTestGet did not match " +
Jon Hall390696c2015-05-05 17:13:41 -07004518 "expected output" )
4519 main.log.debug( self.name + " expected: " + pattern )
4520 main.log.debug( self.name + " actual: " + repr( output ) )
4521 match = None
4522 if match:
4523 setMatch = match.group( 1 )
4524 if setMatch == '':
4525 setList = []
4526 else:
4527 setList = setMatch.split( ", " )
4528 if length > 0:
4529 return ( setList, containsCheck )
4530 else:
4531 return setList
4532 else: # no match
4533 main.log.error( self.name + ": setTestGet did not" +
4534 " match expected output" )
4535 main.log.debug( self.name + " expected: " + pattern )
4536 main.log.debug( self.name + " actual: " + repr( output ) )
4537 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004538 except TypeError:
4539 main.log.exception( self.name + ": Object not as expected" )
4540 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004541 except Exception:
4542 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004543 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004544
4545 def setTestSize( self, setName ):
4546 """
4547 CLI command to get the elements in a distributed set.
4548 Required arguments:
4549 setName - The name of the set to remove from.
4550 returns:
Jon Hallfeff3082015-05-19 10:23:26 -07004551 The integer value of the size returned or
Jon Hall390696c2015-05-05 17:13:41 -07004552 None on error
4553 """
4554 try:
4555 # TODO: Should this check against the number of elements returned
4556 # and then return true/false based on that?
4557 setName = str( setName ).strip()
4558 # Patterns to match
4559 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004560 pattern = "There are (\d+) items in set " + setName + ":\r\n" +\
Jon Hall390696c2015-05-05 17:13:41 -07004561 setPattern
4562 cmdStr = "set-test-get -s "
4563 cmdStr += setName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004564 output = self.distPrimitivesSend( cmdStr )
Jon Hall0e240372018-05-02 11:21:57 -07004565 if output:
4566 match = re.search( pattern, output )
4567 if match:
4568 setSize = int( match.group( 1 ) )
4569 setMatch = match.group( 2 )
4570 if len( setMatch.split() ) == setSize:
4571 main.log.info( "The size returned by " + self.name +
4572 " matches the number of elements in " +
4573 "the returned set" )
4574 else:
4575 main.log.error( "The size returned by " + self.name +
4576 " does not match the number of " +
4577 "elements in the returned set." )
4578 return setSize
Jon Hall390696c2015-05-05 17:13:41 -07004579 else: # no match
4580 main.log.error( self.name + ": setTestGet did not" +
4581 " match expected output" )
4582 main.log.debug( self.name + " expected: " + pattern )
4583 main.log.debug( self.name + " actual: " + repr( output ) )
4584 return None
Jon Hall390696c2015-05-05 17:13:41 -07004585 except TypeError:
4586 main.log.exception( self.name + ": Object not as expected" )
4587 return None
Jon Hall390696c2015-05-05 17:13:41 -07004588 except Exception:
4589 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004590 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004591
Jon Hall80daded2015-05-27 16:07:00 -07004592 def counters( self, jsonFormat=True ):
Jon Hall390696c2015-05-05 17:13:41 -07004593 """
4594 Command to list the various counters in the system.
4595 returns:
Jon Hall80daded2015-05-27 16:07:00 -07004596 if jsonFormat, a string of the json object returned by the cli
4597 command
4598 if not jsonFormat, the normal string output of the cli command
Jon Hall390696c2015-05-05 17:13:41 -07004599 None on error
4600 """
Jon Hall390696c2015-05-05 17:13:41 -07004601 try:
Jon Hall390696c2015-05-05 17:13:41 -07004602 cmdStr = "counters"
Jon Hall80daded2015-05-27 16:07:00 -07004603 if jsonFormat:
4604 cmdStr += " -j"
Jon Hall390696c2015-05-05 17:13:41 -07004605 output = self.sendline( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004606 main.log.debug( self.name + ": Counters unparsed: " + output )
4607 output = output.split( "\r\n" )[ -1 ]
4608 main.log.debug( self.name + ": Counters parsed: " + output )
Jon Halla495f562016-05-16 18:03:26 -07004609 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004610 assert "Command not found:" not in output, output
4611 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004612 main.log.info( self.name + ": " + output )
Jon Hall80daded2015-05-27 16:07:00 -07004613 return output
Jon Hall390696c2015-05-05 17:13:41 -07004614 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004615 main.log.exception( self.name + ": Error in processing 'counters' command." )
Jon Hall80daded2015-05-27 16:07:00 -07004616 return None
Jon Hall390696c2015-05-05 17:13:41 -07004617 except TypeError:
4618 main.log.exception( self.name + ": Object not as expected" )
Jon Hall80daded2015-05-27 16:07:00 -07004619 return None
Jon Hall390696c2015-05-05 17:13:41 -07004620 except pexpect.EOF:
4621 main.log.error( self.name + ": EOF exception found" )
4622 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004623 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004624 except Exception:
4625 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004626 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004627
Jon Hall935db192016-04-19 00:22:04 -07004628 def counterTestAddAndGet( self, counter, delta=1 ):
Jon Hall390696c2015-05-05 17:13:41 -07004629 """
Jon Halle1a3b752015-07-22 13:02:46 -07004630 CLI command to add a delta to then get a distributed counter.
Jon Hall390696c2015-05-05 17:13:41 -07004631 Required arguments:
4632 counter - The name of the counter to increment.
4633 Optional arguments:
Jon Halle1a3b752015-07-22 13:02:46 -07004634 delta - The long to add to the counter
Jon Hall390696c2015-05-05 17:13:41 -07004635 returns:
4636 integer value of the counter or
4637 None on Error
4638 """
4639 try:
4640 counter = str( counter )
Jon Halle1a3b752015-07-22 13:02:46 -07004641 delta = int( delta )
Jon Hall390696c2015-05-05 17:13:41 -07004642 cmdStr = "counter-test-increment "
Jon Hall390696c2015-05-05 17:13:41 -07004643 cmdStr += counter
Jon Halle1a3b752015-07-22 13:02:46 -07004644 if delta != 1:
4645 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004646 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004647 pattern = counter + " was updated to (-?\d+)"
Jon Hall390696c2015-05-05 17:13:41 -07004648 match = re.search( pattern, output )
4649 if match:
4650 return int( match.group( 1 ) )
4651 else:
Jon Halle1a3b752015-07-22 13:02:46 -07004652 main.log.error( self.name + ": counterTestAddAndGet did not" +
Jon Hall390696c2015-05-05 17:13:41 -07004653 " match expected output." )
4654 main.log.debug( self.name + " expected: " + pattern )
4655 main.log.debug( self.name + " actual: " + repr( output ) )
4656 return None
Jon Hall390696c2015-05-05 17:13:41 -07004657 except TypeError:
4658 main.log.exception( self.name + ": Object not as expected" )
4659 return None
Jon Hall390696c2015-05-05 17:13:41 -07004660 except Exception:
4661 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004662 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004663
Jon Hall935db192016-04-19 00:22:04 -07004664 def counterTestGetAndAdd( self, counter, delta=1 ):
Jon Halle1a3b752015-07-22 13:02:46 -07004665 """
4666 CLI command to get a distributed counter then add a delta to it.
4667 Required arguments:
4668 counter - The name of the counter to increment.
4669 Optional arguments:
4670 delta - The long to add to the counter
Jon Halle1a3b752015-07-22 13:02:46 -07004671 returns:
4672 integer value of the counter or
4673 None on Error
4674 """
4675 try:
4676 counter = str( counter )
4677 delta = int( delta )
4678 cmdStr = "counter-test-increment -g "
Jon Halle1a3b752015-07-22 13:02:46 -07004679 cmdStr += counter
4680 if delta != 1:
4681 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004682 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004683 pattern = counter + " was updated to (-?\d+)"
4684 match = re.search( pattern, output )
4685 if match:
4686 return int( match.group( 1 ) )
4687 else:
4688 main.log.error( self.name + ": counterTestGetAndAdd did not" +
4689 " match expected output." )
4690 main.log.debug( self.name + " expected: " + pattern )
4691 main.log.debug( self.name + " actual: " + repr( output ) )
4692 return None
Jon Halle1a3b752015-07-22 13:02:46 -07004693 except TypeError:
4694 main.log.exception( self.name + ": Object not as expected" )
4695 return None
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004696 except Exception:
4697 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004698 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004699
4700 def valueTestGet( self, valueName ):
4701 """
4702 CLI command to get the value of an atomic value.
4703 Required arguments:
4704 valueName - The name of the value to get.
4705 returns:
4706 string value of the value or
4707 None on Error
4708 """
4709 try:
4710 valueName = str( valueName )
4711 cmdStr = "value-test "
4712 operation = "get"
4713 cmdStr = "value-test {} {}".format( valueName,
4714 operation )
4715 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004716 main.log.debug( self.name + ": value test unparsed: " + output )
4717 output = output.split( "\r\n" )[ -1 ]
4718 main.log.debug( self.name + ": value test parsed: " + output )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004719 pattern = "(\w+)"
4720 match = re.search( pattern, output )
4721 if match:
4722 return match.group( 1 )
4723 else:
4724 main.log.error( self.name + ": valueTestGet did not" +
4725 " match expected output." )
4726 main.log.debug( self.name + " expected: " + pattern )
4727 main.log.debug( self.name + " actual: " + repr( output ) )
4728 return None
4729 except TypeError:
4730 main.log.exception( self.name + ": Object not as expected" )
4731 return None
4732 except Exception:
4733 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004734 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004735
4736 def valueTestSet( self, valueName, newValue ):
4737 """
4738 CLI command to set the value of an atomic value.
4739 Required arguments:
4740 valueName - The name of the value to set.
4741 newValue - The value to assign to the given value.
4742 returns:
4743 main.TRUE on success or
4744 main.ERROR on Error
4745 """
4746 try:
4747 valueName = str( valueName )
4748 newValue = str( newValue )
4749 operation = "set"
4750 cmdStr = "value-test {} {} {}".format( valueName,
4751 operation,
4752 newValue )
4753 output = self.distPrimitivesSend( cmdStr )
4754 if output is not None:
4755 return main.TRUE
4756 else:
4757 return main.ERROR
4758 except TypeError:
4759 main.log.exception( self.name + ": Object not as expected" )
4760 return main.ERROR
4761 except Exception:
4762 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004763 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004764
4765 def valueTestCompareAndSet( self, valueName, oldValue, newValue ):
4766 """
4767 CLI command to compareAndSet the value of an atomic value.
4768 Required arguments:
4769 valueName - The name of the value.
4770 oldValue - Compare the current value of the atomic value to this
4771 newValue - If the value equals oldValue, set the value to newValue
4772 returns:
4773 main.TRUE on success or
4774 main.FALSE on failure or
4775 main.ERROR on Error
4776 """
4777 try:
4778 valueName = str( valueName )
4779 oldValue = str( oldValue )
4780 newValue = str( newValue )
4781 operation = "compareAndSet"
4782 cmdStr = "value-test {} {} {} {}".format( valueName,
4783 operation,
4784 oldValue,
4785 newValue )
4786 output = self.distPrimitivesSend( cmdStr )
4787 pattern = "(\w+)"
4788 match = re.search( pattern, output )
4789 if match:
4790 result = match.group( 1 )
4791 if result == "true":
4792 return main.TRUE
4793 elif result == "false":
4794 return main.FALSE
4795 else:
4796 main.log.error( self.name + ": valueTestCompareAndSet did not" +
4797 " match expected output." )
4798 main.log.debug( self.name + " expected: " + pattern )
4799 main.log.debug( self.name + " actual: " + repr( output ) )
4800 return main.ERROR
4801 except TypeError:
4802 main.log.exception( self.name + ": Object not as expected" )
4803 return main.ERROR
4804 except Exception:
4805 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004806 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004807
4808 def valueTestGetAndSet( self, valueName, newValue ):
4809 """
4810 CLI command to getAndSet the value of an atomic value.
4811 Required arguments:
4812 valueName - The name of the value to get.
4813 newValue - The value to assign to the given value
4814 returns:
4815 string value of the value or
4816 None on Error
4817 """
4818 try:
4819 valueName = str( valueName )
4820 cmdStr = "value-test "
4821 operation = "getAndSet"
4822 cmdStr += valueName + " " + operation
4823 cmdStr = "value-test {} {} {}".format( valueName,
4824 operation,
4825 newValue )
4826 output = self.distPrimitivesSend( cmdStr )
4827 pattern = "(\w+)"
4828 match = re.search( pattern, output )
4829 if match:
4830 return match.group( 1 )
4831 else:
4832 main.log.error( self.name + ": valueTestGetAndSet did not" +
4833 " match expected output." )
4834 main.log.debug( self.name + " expected: " + pattern )
4835 main.log.debug( self.name + " actual: " + repr( output ) )
4836 return None
4837 except TypeError:
4838 main.log.exception( self.name + ": Object not as expected" )
4839 return None
4840 except Exception:
4841 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004842 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004843
4844 def valueTestDestroy( self, valueName ):
4845 """
4846 CLI command to destroy an atomic value.
4847 Required arguments:
4848 valueName - The name of the value to destroy.
4849 returns:
4850 main.TRUE on success or
4851 main.ERROR on Error
4852 """
4853 try:
4854 valueName = str( valueName )
4855 cmdStr = "value-test "
4856 operation = "destroy"
4857 cmdStr += valueName + " " + operation
4858 output = self.distPrimitivesSend( cmdStr )
4859 if output is not None:
4860 return main.TRUE
4861 else:
4862 return main.ERROR
4863 except TypeError:
4864 main.log.exception( self.name + ": Object not as expected" )
4865 return main.ERROR
Jon Halle1a3b752015-07-22 13:02:46 -07004866 except Exception:
4867 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004868 main.cleanAndExit()
Jon Halle1a3b752015-07-22 13:02:46 -07004869
YPZhangfebf7302016-05-24 16:45:56 -07004870 def summary( self, jsonFormat=True, timeout=30 ):
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004871 """
4872 Description: Execute summary command in onos
4873 Returns: json object ( summary -j ), returns main.FALSE if there is
4874 no output
4875
4876 """
4877 try:
4878 cmdStr = "summary"
4879 if jsonFormat:
4880 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07004881 handle = self.sendline( cmdStr, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07004882 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004883 assert "Command not found:" not in handle, handle
Jon Hall6e709752016-02-01 13:38:46 -08004884 assert "Error:" not in handle, handle
Devin Lima7cfdbd2017-09-29 15:02:22 -07004885 assert "Error executing" not in handle, handle
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004886 if not handle:
4887 main.log.error( self.name + ": There is no output in " +
4888 "summary command" )
4889 return main.FALSE
4890 return handle
Jon Hallc6793552016-01-19 14:18:37 -08004891 except AssertionError:
Jon Hall6e709752016-02-01 13:38:46 -08004892 main.log.exception( "{} Error in summary output:".format( self.name ) )
Jon Hallc6793552016-01-19 14:18:37 -08004893 return None
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004894 except TypeError:
4895 main.log.exception( self.name + ": Object not as expected" )
4896 return None
4897 except pexpect.EOF:
4898 main.log.error( self.name + ": EOF exception found" )
4899 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004900 main.cleanAndExit()
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004901 except Exception:
4902 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004903 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004904
Jon Hall935db192016-04-19 00:22:04 -07004905 def transactionalMapGet( self, keyName ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004906 """
4907 CLI command to get the value of a key in a consistent map using
4908 transactions. This a test function and can only get keys from the
4909 test map hard coded into the cli command
4910 Required arguments:
4911 keyName - The name of the key to get
Jon Hall2a5002c2015-08-21 16:49:11 -07004912 returns:
4913 The string value of the key or
4914 None on Error
4915 """
4916 try:
4917 keyName = str( keyName )
4918 cmdStr = "transactional-map-test-get "
Jon Hall2a5002c2015-08-21 16:49:11 -07004919 cmdStr += keyName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004920 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07004921 pattern = "Key-value pair \(" + keyName + ", (?P<value>.+)\) found."
4922 if "Key " + keyName + " not found." in output:
Jon Hall9bfadd22016-05-11 14:48:07 -07004923 main.log.warn( output )
Jon Hall2a5002c2015-08-21 16:49:11 -07004924 return None
4925 else:
4926 match = re.search( pattern, output )
4927 if match:
4928 return match.groupdict()[ 'value' ]
4929 else:
4930 main.log.error( self.name + ": transactionlMapGet did not" +
4931 " match expected output." )
4932 main.log.debug( self.name + " expected: " + pattern )
4933 main.log.debug( self.name + " actual: " + repr( output ) )
4934 return None
4935 except TypeError:
4936 main.log.exception( self.name + ": Object not as expected" )
4937 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004938 except Exception:
4939 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004940 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004941
Jon Hall935db192016-04-19 00:22:04 -07004942 def transactionalMapPut( self, numKeys, value ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004943 """
4944 CLI command to put a value into 'numKeys' number of keys in a
4945 consistent map using transactions. This a test function and can only
4946 put into keys named 'Key#' of the test map hard coded into the cli command
4947 Required arguments:
4948 numKeys - Number of keys to add the value to
4949 value - The string value to put into the keys
Jon Hall2a5002c2015-08-21 16:49:11 -07004950 returns:
4951 A dictionary whose keys are the name of the keys put into the map
4952 and the values of the keys are dictionaries whose key-values are
4953 'value': value put into map and optionaly
4954 'oldValue': Previous value in the key or
4955 None on Error
4956
4957 Example output
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004958 { 'Key1': {'oldValue': 'oldTestValue', 'value': 'Testing'},
4959 'Key2': {'value': 'Testing'} }
Jon Hall2a5002c2015-08-21 16:49:11 -07004960 """
4961 try:
4962 numKeys = str( numKeys )
4963 value = str( value )
4964 cmdStr = "transactional-map-test-put "
Jon Hall2a5002c2015-08-21 16:49:11 -07004965 cmdStr += numKeys + " " + value
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004966 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07004967 newPattern = 'Created Key (?P<key>(\w)+) with value (?P<value>(.)+)\.'
4968 updatedPattern = "Put (?P<value>(.)+) into key (?P<key>(\w)+)\. The old value was (?P<oldValue>(.)+)\."
4969 results = {}
4970 for line in output.splitlines():
4971 new = re.search( newPattern, line )
4972 updated = re.search( updatedPattern, line )
4973 if new:
4974 results[ new.groupdict()[ 'key' ] ] = { 'value': new.groupdict()[ 'value' ] }
4975 elif updated:
4976 results[ updated.groupdict()[ 'key' ] ] = { 'value': updated.groupdict()[ 'value' ],
Jon Hallc6793552016-01-19 14:18:37 -08004977 'oldValue': updated.groupdict()[ 'oldValue' ] }
Jon Hall2a5002c2015-08-21 16:49:11 -07004978 else:
4979 main.log.error( self.name + ": transactionlMapGet did not" +
4980 " match expected output." )
Jon Hallc6793552016-01-19 14:18:37 -08004981 main.log.debug( "{} expected: {!r} or {!r}".format( self.name,
4982 newPattern,
4983 updatedPattern ) )
Jon Hall2a5002c2015-08-21 16:49:11 -07004984 main.log.debug( self.name + " actual: " + repr( output ) )
4985 return results
Jon Hall0e240372018-05-02 11:21:57 -07004986 except ( TypeError, AttributeError ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004987 main.log.exception( self.name + ": Object not as expected" )
4988 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004989 except Exception:
4990 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004991 main.cleanAndExit()
Jon Hallc6793552016-01-19 14:18:37 -08004992
acsmarsdaea66c2015-09-03 11:44:06 -07004993 def maps( self, jsonFormat=True ):
4994 """
4995 Description: Returns result of onos:maps
4996 Optional:
4997 * jsonFormat: enable json formatting of output
4998 """
4999 try:
5000 cmdStr = "maps"
5001 if jsonFormat:
5002 cmdStr += " -j"
5003 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07005004 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005005 assert "Command not found:" not in handle, handle
acsmarsdaea66c2015-09-03 11:44:06 -07005006 return handle
Jon Hallc6793552016-01-19 14:18:37 -08005007 except AssertionError:
5008 main.log.exception( "" )
5009 return None
acsmarsdaea66c2015-09-03 11:44:06 -07005010 except TypeError:
5011 main.log.exception( self.name + ": Object not as expected" )
5012 return None
5013 except pexpect.EOF:
5014 main.log.error( self.name + ": EOF exception found" )
5015 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005016 main.cleanAndExit()
acsmarsdaea66c2015-09-03 11:44:06 -07005017 except Exception:
5018 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005019 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005020
5021 def getSwController( self, uri, jsonFormat=True ):
5022 """
5023 Descrition: Gets the controller information from the device
5024 """
5025 try:
5026 cmd = "device-controllers "
5027 if jsonFormat:
5028 cmd += "-j "
5029 response = self.sendline( cmd + uri )
Jon Halla495f562016-05-16 18:03:26 -07005030 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005031 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005032 return response
Jon Hallc6793552016-01-19 14:18:37 -08005033 except AssertionError:
5034 main.log.exception( "" )
5035 return None
GlennRC050596c2015-11-18 17:06:41 -08005036 except TypeError:
5037 main.log.exception( self.name + ": Object not as expected" )
5038 return None
5039 except pexpect.EOF:
5040 main.log.error( self.name + ": EOF exception found" )
5041 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005042 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005043 except Exception:
5044 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005045 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005046
5047 def setSwController( self, uri, ip, proto="tcp", port="6653", jsonFormat=True ):
5048 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005049 Descrition: sets the controller(s) for the specified device
GlennRC050596c2015-11-18 17:06:41 -08005050
5051 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005052 Required: uri - String: The uri of the device(switch).
GlennRC050596c2015-11-18 17:06:41 -08005053 ip - String or List: The ip address of the controller.
5054 This parameter can be formed in a couple of different ways.
5055 VALID:
5056 10.0.0.1 - just the ip address
5057 tcp:10.0.0.1 - the protocol and the ip address
5058 tcp:10.0.0.1:6653 - the protocol and port can be specified,
5059 so that you can add controllers with different
5060 protocols and ports
5061 INVALID:
5062 10.0.0.1:6653 - this is not supported by ONOS
5063
5064 Optional: proto - The type of connection e.g. tcp, ssl. If a list of ips are given
5065 port - The port number.
5066 jsonFormat - If set ONOS will output in json NOTE: This is currently not supported
5067
5068 Returns: main.TRUE if ONOS returns without any errors, otherwise returns main.FALSE
5069 """
5070 try:
5071 cmd = "device-setcontrollers"
5072
5073 if jsonFormat:
5074 cmd += " -j"
5075 cmd += " " + uri
5076 if isinstance( ip, str ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005077 ip = [ ip ]
GlennRC050596c2015-11-18 17:06:41 -08005078 for item in ip:
5079 if ":" in item:
5080 sitem = item.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005081 if len( sitem ) == 3:
GlennRC050596c2015-11-18 17:06:41 -08005082 cmd += " " + item
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005083 elif "." in sitem[ 1 ]:
5084 cmd += " {}:{}".format( item, port )
GlennRC050596c2015-11-18 17:06:41 -08005085 else:
5086 main.log.error( "Malformed entry: " + item )
5087 raise TypeError
5088 else:
5089 cmd += " {}:{}:{}".format( proto, item, port )
GlennRC050596c2015-11-18 17:06:41 -08005090 response = self.sendline( cmd )
Jon Halla495f562016-05-16 18:03:26 -07005091 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005092 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005093 if "Error" in response:
5094 main.log.error( response )
5095 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005096 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005097 except AssertionError:
5098 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005099 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005100 except TypeError:
5101 main.log.exception( self.name + ": Object not as expected" )
5102 return main.FALSE
5103 except pexpect.EOF:
5104 main.log.error( self.name + ": EOF exception found" )
5105 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005106 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005107 except Exception:
5108 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005109 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005110
5111 def removeDevice( self, device ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005112 '''
GlennRC20fc6522015-12-23 23:26:57 -08005113 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005114 Remove a device from ONOS by passing the uri of the device(s).
GlennRC20fc6522015-12-23 23:26:57 -08005115 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005116 device - (str or list) the id or uri of the device ex. "of:0000000000000001"
GlennRC20fc6522015-12-23 23:26:57 -08005117 Returns:
5118 Returns main.FALSE if an exception is thrown or an error is present
5119 in the response. Otherwise, returns main.TRUE.
5120 NOTE:
5121 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005122 '''
GlennRC20fc6522015-12-23 23:26:57 -08005123 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005124 if isinstance( device, str ):
You Wang823f5022016-08-18 15:24:41 -07005125 deviceStr = device
5126 device = []
5127 device.append( deviceStr )
GlennRC20fc6522015-12-23 23:26:57 -08005128
5129 for d in device:
5130 time.sleep( 1 )
5131 response = self.sendline( "device-remove {}".format( d ) )
Jon Halla495f562016-05-16 18:03:26 -07005132 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005133 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005134 if "Error" in response:
5135 main.log.warn( "Error for device: {}\nResponse: {}".format( d, response ) )
5136 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005137 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005138 except AssertionError:
5139 main.log.exception( "" )
5140 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005141 except TypeError:
5142 main.log.exception( self.name + ": Object not as expected" )
5143 return main.FALSE
5144 except pexpect.EOF:
5145 main.log.error( self.name + ": EOF exception found" )
5146 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005147 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005148 except Exception:
5149 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005150 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005151
5152 def removeHost( self, host ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005153 '''
GlennRC20fc6522015-12-23 23:26:57 -08005154 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005155 Remove a host from ONOS by passing the id of the host(s)
GlennRC20fc6522015-12-23 23:26:57 -08005156 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005157 hostId - (str or list) the id or mac of the host ex. "00:00:00:00:00:01"
GlennRC20fc6522015-12-23 23:26:57 -08005158 Returns:
5159 Returns main.FALSE if an exception is thrown or an error is present
5160 in the response. Otherwise, returns main.TRUE.
5161 NOTE:
5162 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005163 '''
GlennRC20fc6522015-12-23 23:26:57 -08005164 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005165 if isinstance( host, str ):
GlennRC20fc6522015-12-23 23:26:57 -08005166 host = list( host )
5167
5168 for h in host:
5169 time.sleep( 1 )
5170 response = self.sendline( "host-remove {}".format( h ) )
Jon Halla495f562016-05-16 18:03:26 -07005171 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005172 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005173 if "Error" in response:
5174 main.log.warn( "Error for host: {}\nResponse: {}".format( h, response ) )
5175 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005176 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005177 except AssertionError:
5178 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005179 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005180 except TypeError:
5181 main.log.exception( self.name + ": Object not as expected" )
5182 return main.FALSE
5183 except pexpect.EOF:
5184 main.log.error( self.name + ": EOF exception found" )
5185 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005186 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005187 except Exception:
5188 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005189 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005190
YPZhangfebf7302016-05-24 16:45:56 -07005191 def link( self, begin, end, state, timeout=30, showResponse=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005192 '''
GlennRCed771242016-01-13 17:02:47 -08005193 Description:
5194 Bring link down or up in the null-provider.
5195 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005196 begin - (string) One end of a device or switch.
5197 end - (string) the other end of the device or switch
GlennRCed771242016-01-13 17:02:47 -08005198 returns:
5199 main.TRUE if no exceptions were thrown and no Errors are
5200 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005201 '''
GlennRCed771242016-01-13 17:02:47 -08005202 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005203 cmd = "null-link null:{} null:{} {}".format( begin, end, state )
YPZhangfebf7302016-05-24 16:45:56 -07005204 response = self.sendline( cmd, showResponse=showResponse, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07005205 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005206 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08005207 if "Error" in response or "Failure" in response:
5208 main.log.error( response )
5209 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005210 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005211 except AssertionError:
5212 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005213 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005214 except TypeError:
5215 main.log.exception( self.name + ": Object not as expected" )
5216 return main.FALSE
5217 except pexpect.EOF:
5218 main.log.error( self.name + ": EOF exception found" )
5219 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005220 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005221 except Exception:
5222 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005223 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005224
Jon Hall2c8959e2016-12-16 12:17:34 -08005225 def portstate( self, dpid, port, state ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005226 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005227 Description:
5228 Changes the state of port in an OF switch by means of the
5229 PORTSTATUS OF messages.
5230 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005231 dpid - (string) Datapath ID of the device. Ex: 'of:0000000000000102'
5232 port - (string) target port in the device. Ex: '2'
5233 state - (string) target state (enable or disable)
Flavio Castro82ee2f62016-06-07 15:04:12 -07005234 returns:
5235 main.TRUE if no exceptions were thrown and no Errors are
5236 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005237 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005238 try:
Jon Hall2c8959e2016-12-16 12:17:34 -08005239 state = state.lower()
5240 assert state == 'enable' or state == 'disable', "Unknown state"
Jon Halle0f0b342017-04-18 11:43:47 -07005241 cmd = "portstate {} {} {}".format( dpid, port, state )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005242 response = self.sendline( cmd, showResponse=True )
5243 assert response is not None, "Error in sendline"
5244 assert "Command not found:" not in response, response
5245 if "Error" in response or "Failure" in response:
5246 main.log.error( response )
5247 return main.FALSE
5248 return main.TRUE
5249 except AssertionError:
5250 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005251 return main.FALSE
Flavio Castro82ee2f62016-06-07 15:04:12 -07005252 except TypeError:
5253 main.log.exception( self.name + ": Object not as expected" )
5254 return main.FALSE
5255 except pexpect.EOF:
5256 main.log.error( self.name + ": EOF exception found" )
5257 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005258 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005259 except Exception:
5260 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005261 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005262
5263 def logSet( self, level="INFO", app="org.onosproject" ):
5264 """
5265 Set the logging level to lvl for a specific app
5266 returns main.TRUE on success
5267 returns main.FALSE if Error occurred
5268 if noExit is True, TestON will not exit, but clean up
5269 Available level: DEBUG, TRACE, INFO, WARN, ERROR
5270 Level defaults to INFO
5271 """
5272 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005273 self.handle.sendline( "log:set %s %s" % ( level, app ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -08005274 self.handle.expect( self.karafPrompt )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005275
5276 response = self.handle.before
5277 if re.search( "Error", response ):
5278 return main.FALSE
5279 return main.TRUE
5280 except pexpect.TIMEOUT:
5281 main.log.exception( self.name + ": TIMEOUT exception found" )
Devin Lim44075962017-08-11 10:56:37 -07005282 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005283 except pexpect.EOF:
5284 main.log.error( self.name + ": EOF exception found" )
5285 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005286 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005287 except Exception:
5288 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005289 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07005290
5291 def getGraphDict( self, timeout=60, includeHost=False ):
5292 """
5293 Return a dictionary which describes the latest network topology data as a
5294 graph.
5295 An example of the dictionary:
5296 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
5297 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
5298 Each vertex should at least have an 'edges' attribute which describes the
5299 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005300 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07005301 list of attributes.
5302 An example of the edges dictionary:
5303 'edges': { vertex2: { 'port': ..., 'weight': ... },
5304 vertex3: { 'port': ..., 'weight': ... } }
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005305 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07005306 in topology data.
5307 """
5308 graphDict = {}
5309 try:
5310 links = self.links()
5311 links = json.loads( links )
5312 devices = self.devices()
5313 devices = json.loads( devices )
5314 idToDevice = {}
5315 for device in devices:
5316 idToDevice[ device[ 'id' ] ] = device
5317 if includeHost:
5318 hosts = self.hosts()
5319 # FIXME: support 'includeHost' argument
5320 for link in links:
5321 nodeA = link[ 'src' ][ 'device' ]
5322 nodeB = link[ 'dst' ][ 'device' ]
5323 assert idToDevice[ nodeA ][ 'available' ] and idToDevice[ nodeB ][ 'available' ]
Jon Halle0f0b342017-04-18 11:43:47 -07005324 if nodeA not in graphDict.keys():
5325 graphDict[ nodeA ] = { 'edges': {},
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005326 'dpid': idToDevice[ nodeA ][ 'id' ][ 3: ],
Jon Halle0f0b342017-04-18 11:43:47 -07005327 'type': idToDevice[ nodeA ][ 'type' ],
5328 'available': idToDevice[ nodeA ][ 'available' ],
5329 'role': idToDevice[ nodeA ][ 'role' ],
5330 'mfr': idToDevice[ nodeA ][ 'mfr' ],
5331 'hw': idToDevice[ nodeA ][ 'hw' ],
5332 'sw': idToDevice[ nodeA ][ 'sw' ],
5333 'serial': idToDevice[ nodeA ][ 'serial' ],
5334 'chassisId': idToDevice[ nodeA ][ 'chassisId' ],
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005335 'annotations': idToDevice[ nodeA ][ 'annotations' ]}
You Wangdb8cd0a2016-05-26 15:19:45 -07005336 else:
5337 # Assert nodeB is not connected to any current links of nodeA
You Wang7d14d642019-01-23 15:10:08 -08005338 # assert nodeB not in graphDict[ nodeA ][ 'edges' ].keys()
5339 pass
Jon Halle0f0b342017-04-18 11:43:47 -07005340 graphDict[ nodeA ][ 'edges' ][ nodeB ] = { 'port': link[ 'src' ][ 'port' ],
5341 'type': link[ 'type' ],
5342 'state': link[ 'state' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07005343 return graphDict
5344 except ( TypeError, ValueError ):
5345 main.log.exception( self.name + ": Object not as expected" )
5346 return None
5347 except KeyError:
5348 main.log.exception( self.name + ": KeyError exception found" )
5349 return None
5350 except AssertionError:
5351 main.log.exception( self.name + ": AssertionError exception found" )
5352 return None
5353 except pexpect.EOF:
5354 main.log.error( self.name + ": EOF exception found" )
5355 main.log.error( self.name + ": " + self.handle.before )
5356 return None
5357 except Exception:
5358 main.log.exception( self.name + ": Uncaught exception!" )
5359 return None
YPZhangcbc2a062016-07-11 10:55:44 -07005360
5361 def getIntentPerfSummary( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005362 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005363 Send command to check intent-perf summary
5364 Returns: dictionary for intent-perf summary
5365 if something wrong, function will return None
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005366 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005367 cmd = "intent-perf -s"
5368 respDic = {}
5369 resp = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08005370 assert resp is not None, "Error in sendline"
5371 assert "Command not found:" not in resp, resp
YPZhangcbc2a062016-07-11 10:55:44 -07005372 try:
5373 # Generate the dictionary to return
5374 for l in resp.split( "\n" ):
5375 # Delete any white space in line
5376 temp = re.sub( r'\s+', '', l )
5377 temp = temp.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005378 respDic[ temp[ 0 ] ] = temp[ 1 ]
YPZhangcbc2a062016-07-11 10:55:44 -07005379
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005380 except ( TypeError, ValueError ):
YPZhangcbc2a062016-07-11 10:55:44 -07005381 main.log.exception( self.name + ": Object not as expected" )
5382 return None
5383 except KeyError:
5384 main.log.exception( self.name + ": KeyError exception found" )
5385 return None
5386 except AssertionError:
5387 main.log.exception( self.name + ": AssertionError exception found" )
5388 return None
5389 except pexpect.EOF:
5390 main.log.error( self.name + ": EOF exception found" )
5391 main.log.error( self.name + ": " + self.handle.before )
5392 return None
5393 except Exception:
5394 main.log.exception( self.name + ": Uncaught exception!" )
5395 return None
5396 return respDic
5397
Chiyu Chengec63bde2016-11-17 18:11:36 -08005398 def logSearch( self, mode='all', searchTerm='', startLine='', logNum=1 ):
chengchiyu08303a02016-09-08 17:40:26 -07005399 """
5400 Searches the latest ONOS log file for the given search term and
5401 return a list that contains all the lines that have the search term.
YPZhangcbc2a062016-07-11 10:55:44 -07005402
chengchiyu08303a02016-09-08 17:40:26 -07005403 Arguments:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005404 searchTerm:
5405 The string to grep from the ONOS log.
5406 startLine:
5407 The term that decides which line is the start to search the searchTerm in
5408 the karaf log. For now, startTerm only works in 'first' mode.
5409 logNum:
5410 In some extreme cases, one karaf log is not big enough to contain all the
5411 information.Because of this, search mutiply logs is necessary to capture
5412 the right result. logNum is the number of karaf logs that we need to search
5413 the searchTerm.
chengchiyu08303a02016-09-08 17:40:26 -07005414 mode:
5415 all: return all the strings that contain the search term
5416 last: return the last string that contains the search term
5417 first: return the first string that contains the search term
Chiyu Chengec63bde2016-11-17 18:11:36 -08005418 num: return the number of times that the searchTerm appears in the log
5419 total: return how many lines in karaf log
chengchiyu08303a02016-09-08 17:40:26 -07005420 """
5421 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005422 assert isinstance( searchTerm, str )
Jon Halle0f0b342017-04-18 11:43:47 -07005423 # Build the log paths string
Chiyu Chengec63bde2016-11-17 18:11:36 -08005424 logPath = '/opt/onos/log/karaf.log.'
5425 logPaths = '/opt/onos/log/karaf.log'
5426 for i in range( 1, logNum ):
5427 logPaths = logPath + str( i ) + " " + logPaths
5428 cmd = "cat " + logPaths
You Wang6d301d42017-04-21 10:49:33 -07005429 if startLine:
Jon Halla478b852017-12-04 15:00:15 -08005430 # 100000000 is just a extreme large number to make sure this function can
5431 # grep all the lines after startLine
You Wang6d301d42017-04-21 10:49:33 -07005432 cmd = cmd + " | grep -A 100000000 \'" + startLine + "\'"
Chiyu Chengec63bde2016-11-17 18:11:36 -08005433 if mode == 'all':
5434 cmd = cmd + " | grep \'" + searchTerm + "\'"
You Wang6d301d42017-04-21 10:49:33 -07005435 elif mode == 'last':
Chiyu Chengec63bde2016-11-17 18:11:36 -08005436 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | tail -n 1"
You Wang6d301d42017-04-21 10:49:33 -07005437 elif mode == 'first':
5438 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | head -n 1"
5439 elif mode == 'num':
You Wangd91a70f2019-01-03 15:28:10 -08005440 cmd = cmd + " | grep \'" + searchTerm + "\' | wc -l"
5441 num = self.lineCount( cmd )
Chiyu Chengb8c2c842016-10-05 12:40:49 -07005442 return num
You Wang6d301d42017-04-21 10:49:33 -07005443 elif mode == 'total':
Jon Halld5a94fb2018-11-13 14:32:23 -08005444 totalLines = self.lineCount( "cat /opt/onos/log/karaf.log | wc -l" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005445 return int( totalLines )
You Wang6d301d42017-04-21 10:49:33 -07005446 else:
5447 main.log.error( self.name + " unsupported mode" )
5448 return main.ERROR
chengchiyu08303a02016-09-08 17:40:26 -07005449 before = self.sendline( cmd )
5450 before = before.splitlines()
5451 # make sure the returned list only contains the search term
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005452 returnLines = [ line for line in before if searchTerm in line ]
chengchiyu08303a02016-09-08 17:40:26 -07005453 return returnLines
5454 except AssertionError:
5455 main.log.error( self.name + " searchTerm is not string type" )
5456 return None
5457 except pexpect.EOF:
5458 main.log.error( self.name + ": EOF 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 pexpect.TIMEOUT:
5462 main.log.error( self.name + ": TIMEOUT exception found" )
5463 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005464 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005465 except Exception:
5466 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005467 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005468
5469 def vplsShow( self, jsonFormat=True ):
5470 """
5471 Description: Returns result of onos:vpls show, which should list the
5472 configured VPLS networks and the assigned interfaces.
5473 Optional:
5474 * jsonFormat: enable json formatting of output
5475 Returns:
5476 The output of the command or None on error.
5477 """
5478 try:
5479 cmdStr = "vpls show"
5480 if jsonFormat:
5481 raise NotImplementedError
5482 cmdStr += " -j"
5483 handle = self.sendline( cmdStr )
5484 assert handle is not None, "Error in sendline"
5485 assert "Command not found:" not in handle, handle
5486 return handle
5487 except AssertionError:
5488 main.log.exception( "" )
5489 return None
5490 except TypeError:
5491 main.log.exception( self.name + ": Object not as expected" )
5492 return None
5493 except pexpect.EOF:
5494 main.log.error( self.name + ": EOF exception found" )
5495 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005496 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005497 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005498 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005499 return None
5500 except Exception:
5501 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005502 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005503
5504 def parseVplsShow( self ):
5505 """
5506 Parse the cli output of 'vpls show' into json output. This is required
5507 as there is currently no json output available.
5508 """
5509 try:
5510 output = []
5511 raw = self.vplsShow( jsonFormat=False )
5512 namePat = "VPLS name: (?P<name>\w+)"
5513 interfacesPat = "Associated interfaces: \[(?P<interfaces>.*)\]"
5514 encapPat = "Encapsulation: (?P<encap>\w+)"
5515 pattern = "\s+".join( [ namePat, interfacesPat, encapPat ] )
5516 mIter = re.finditer( pattern, raw )
5517 for match in mIter:
5518 item = {}
5519 item[ 'name' ] = match.group( 'name' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005520 ifaces = match.group( 'interfaces' ).split( ', ' )
Jon Hall2c8959e2016-12-16 12:17:34 -08005521 if ifaces == [ "" ]:
5522 ifaces = []
5523 item[ 'interfaces' ] = ifaces
5524 encap = match.group( 'encap' )
5525 if encap != 'NONE':
5526 item[ 'encapsulation' ] = encap.lower()
5527 output.append( item )
5528 return output
5529 except Exception:
5530 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005531 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005532
5533 def vplsList( self, jsonFormat=True ):
5534 """
5535 Description: Returns result of onos:vpls list, which should list the
5536 configured VPLS networks.
5537 Optional:
5538 * jsonFormat: enable json formatting of output
5539 """
5540 try:
5541 cmdStr = "vpls list"
5542 if jsonFormat:
5543 raise NotImplementedError
5544 cmdStr += " -j"
5545 handle = self.sendline( cmdStr )
5546 assert handle is not None, "Error in sendline"
5547 assert "Command not found:" not in handle, handle
5548 return handle
5549 except AssertionError:
5550 main.log.exception( "" )
5551 return None
5552 except TypeError:
5553 main.log.exception( self.name + ": Object not as expected" )
5554 return None
5555 except pexpect.EOF:
5556 main.log.error( self.name + ": EOF exception found" )
5557 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005558 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005559 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005560 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005561 return None
5562 except Exception:
5563 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005564 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005565
5566 def vplsCreate( self, network ):
5567 """
5568 CLI command to create a new VPLS network.
5569 Required arguments:
5570 network - String name of the network to create.
5571 returns:
5572 main.TRUE on success and main.FALSE on failure
5573 """
5574 try:
5575 network = str( network )
5576 cmdStr = "vpls create "
5577 cmdStr += network
5578 output = self.sendline( cmdStr )
5579 assert output is not None, "Error in sendline"
5580 assert "Command not found:" not in output, output
5581 assert "Error executing command" not in output, output
5582 assert "VPLS already exists:" not in output, output
5583 return main.TRUE
5584 except AssertionError:
5585 main.log.exception( "" )
5586 return main.FALSE
5587 except TypeError:
5588 main.log.exception( self.name + ": Object not as expected" )
5589 return main.FALSE
5590 except pexpect.EOF:
5591 main.log.error( self.name + ": EOF exception found" )
5592 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005593 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005594 except Exception:
5595 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005596 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005597
5598 def vplsDelete( self, network ):
5599 """
5600 CLI command to delete a VPLS network.
5601 Required arguments:
5602 network - Name of the network to delete.
5603 returns:
5604 main.TRUE on success and main.FALSE on failure
5605 """
5606 try:
5607 network = str( network )
5608 cmdStr = "vpls delete "
5609 cmdStr += network
5610 output = self.sendline( cmdStr )
5611 assert output is not None, "Error in sendline"
5612 assert "Command not found:" not in output, output
5613 assert "Error executing command" not in output, output
5614 assert " not found" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005615 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005616 return main.TRUE
5617 except AssertionError:
5618 main.log.exception( "" )
5619 return main.FALSE
5620 except TypeError:
5621 main.log.exception( self.name + ": Object not as expected" )
5622 return main.FALSE
5623 except pexpect.EOF:
5624 main.log.error( self.name + ": EOF exception found" )
5625 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005626 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005627 except Exception:
5628 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005629 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005630
5631 def vplsAddIface( self, network, iface ):
5632 """
5633 CLI command to add an interface to a VPLS network.
5634 Required arguments:
5635 network - Name of the network to add the interface to.
5636 iface - The ONOS name for an interface.
5637 returns:
5638 main.TRUE on success and main.FALSE on failure
5639 """
5640 try:
5641 network = str( network )
5642 iface = str( iface )
5643 cmdStr = "vpls add-if "
5644 cmdStr += network + " " + iface
5645 output = self.sendline( cmdStr )
5646 assert output is not None, "Error in sendline"
5647 assert "Command not found:" not in output, output
5648 assert "Error executing command" not in output, output
5649 assert "already associated to network" not in output, output
5650 assert "Interface cannot be added." not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005651 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005652 return main.TRUE
5653 except AssertionError:
5654 main.log.exception( "" )
5655 return main.FALSE
5656 except TypeError:
5657 main.log.exception( self.name + ": Object not as expected" )
5658 return main.FALSE
5659 except pexpect.EOF:
5660 main.log.error( self.name + ": EOF exception found" )
5661 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005662 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005663 except Exception:
5664 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005665 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005666
5667 def vplsRemIface( self, network, iface ):
5668 """
5669 CLI command to remove an interface from a VPLS network.
5670 Required arguments:
5671 network - Name of the network to remove the interface from.
5672 iface - Name of the interface to remove.
5673 returns:
5674 main.TRUE on success and main.FALSE on failure
5675 """
5676 try:
5677 iface = str( iface )
5678 cmdStr = "vpls rem-if "
5679 cmdStr += network + " " + iface
5680 output = self.sendline( cmdStr )
5681 assert output is not None, "Error in sendline"
5682 assert "Command not found:" not in output, output
5683 assert "Error executing command" not in output, output
5684 assert "is not configured" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005685 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005686 return main.TRUE
5687 except AssertionError:
5688 main.log.exception( "" )
5689 return main.FALSE
5690 except TypeError:
5691 main.log.exception( self.name + ": Object not as expected" )
5692 return main.FALSE
5693 except pexpect.EOF:
5694 main.log.error( self.name + ": EOF exception found" )
5695 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005696 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005697 except Exception:
5698 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005699 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005700
5701 def vplsClean( self ):
5702 """
5703 Description: Clears the VPLS app configuration.
5704 Returns: main.TRUE on success and main.FALSE on failure
5705 """
5706 try:
5707 cmdStr = "vpls clean"
5708 handle = self.sendline( cmdStr )
5709 assert handle is not None, "Error in sendline"
5710 assert "Command not found:" not in handle, handle
Jon Hallcf97cf12017-06-06 09:37:51 -07005711 assert "still updating" not in handle, handle
Jon Hall2c8959e2016-12-16 12:17:34 -08005712 return handle
5713 except AssertionError:
5714 main.log.exception( "" )
5715 return main.FALSE
5716 except TypeError:
5717 main.log.exception( self.name + ": Object not as expected" )
5718 return main.FALSE
5719 except pexpect.EOF:
5720 main.log.error( self.name + ": EOF exception found" )
5721 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005722 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005723 except Exception:
5724 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005725 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005726
5727 def vplsSetEncap( self, network, encapType ):
5728 """
5729 CLI command to add an interface to a VPLS network.
5730 Required arguments:
5731 network - Name of the network to create.
5732 encapType - Type of encapsulation.
5733 returns:
5734 main.TRUE on success and main.FALSE on failure
5735 """
5736 try:
5737 network = str( network )
5738 encapType = str( encapType ).upper()
5739 assert encapType in [ "MPLS", "VLAN", "NONE" ], "Incorrect type"
5740 cmdStr = "vpls set-encap "
5741 cmdStr += network + " " + encapType
5742 output = self.sendline( cmdStr )
5743 assert output is not None, "Error in sendline"
5744 assert "Command not found:" not in output, output
5745 assert "Error executing command" not in output, output
5746 assert "already associated to network" not in output, output
5747 assert "Encapsulation type " not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005748 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005749 return main.TRUE
5750 except AssertionError:
5751 main.log.exception( "" )
5752 return main.FALSE
5753 except TypeError:
5754 main.log.exception( self.name + ": Object not as expected" )
5755 return main.FALSE
5756 except pexpect.EOF:
5757 main.log.error( self.name + ": EOF exception found" )
5758 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005759 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005760 except Exception:
5761 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005762 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005763
5764 def interfaces( self, jsonFormat=True ):
5765 """
5766 Description: Returns result of interfaces command.
5767 Optional:
5768 * jsonFormat: enable json formatting of output
5769 Returns:
5770 The output of the command or None on error.
5771 """
5772 try:
5773 cmdStr = "interfaces"
5774 if jsonFormat:
Jon Halle0f0b342017-04-18 11:43:47 -07005775 raise NotImplementedError
Jon Hall2c8959e2016-12-16 12:17:34 -08005776 cmdStr += " -j"
5777 handle = self.sendline( cmdStr )
5778 assert handle is not None, "Error in sendline"
5779 assert "Command not found:" not in handle, handle
5780 return handle
5781 except AssertionError:
5782 main.log.exception( "" )
5783 return None
5784 except TypeError:
5785 main.log.exception( self.name + ": Object not as expected" )
5786 return None
5787 except pexpect.EOF:
5788 main.log.error( self.name + ": EOF exception found" )
5789 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005790 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005791 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005792 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005793 return None
5794 except Exception:
5795 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005796 main.cleanAndExit()
Chiyu Chengec63bde2016-11-17 18:11:36 -08005797
5798 def getTimeStampFromLog( self, mode, searchTerm, splitTerm_before, splitTerm_after, startLine='', logNum=1 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005799 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005800 Get the timestamp of searchTerm from karaf log.
5801
5802 Arguments:
5803 splitTerm_before and splitTerm_after:
5804
5805 The terms that split the string that contains the timeStamp of
5806 searchTerm. For example, if that string is "xxxxxxxcreationTime =
5807 1419510501xxxxxx", then the splitTerm_before is "CreationTime = "
5808 and the splitTerm_after is "x"
5809
5810 others:
Jon Halle0f0b342017-04-18 11:43:47 -07005811 Please look at the "logsearch" Function in onosclidriver.py
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005812 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005813 if logNum < 0:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005814 main.log.error( "Get wrong log number ")
Chiyu Chengec63bde2016-11-17 18:11:36 -08005815 return main.ERROR
5816 lines = self.logSearch( mode=mode, searchTerm=searchTerm, startLine=startLine, logNum=logNum )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005817 if len( lines ) == 0:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005818 main.log.warn( "Captured timestamp string is empty" )
5819 return main.ERROR
5820 lines = lines[ 0 ]
5821 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005822 assert isinstance( lines, str )
Chiyu Chengec63bde2016-11-17 18:11:36 -08005823 # get the target value
5824 line = lines.split( splitTerm_before )
5825 key = line[ 1 ].split( splitTerm_after )
5826 return int( key[ 0 ] )
5827 except IndexError:
5828 main.log.warn( "Index Error!" )
5829 return main.ERROR
5830 except AssertionError:
5831 main.log.warn( "Search Term Not Found " )
5832 return main.ERROR
Jon Halle0f0b342017-04-18 11:43:47 -07005833
5834 def workQueueAdd( self, queueName, value ):
5835 """
5836 CLI command to add a string to the specified Work Queue.
5837 This function uses the distributed primitives test app, which
5838 gives some cli access to distributed primitives for testing
5839 purposes only.
5840
5841 Required arguments:
5842 queueName - The name of the queue to add to
5843 value - The value to add to the queue
5844 returns:
5845 main.TRUE on success, main.FALSE on failure and
5846 main.ERROR on error.
5847 """
5848 try:
5849 queueName = str( queueName )
5850 value = str( value )
5851 prefix = "work-queue-test"
5852 operation = "add"
5853 cmdStr = " ".join( [ prefix, queueName, operation, value ] )
5854 output = self.distPrimitivesSend( cmdStr )
5855 if "Invalid operation name" in output:
5856 main.log.warn( output )
5857 return main.ERROR
5858 elif "Done" in output:
5859 return main.TRUE
5860 except TypeError:
5861 main.log.exception( self.name + ": Object not as expected" )
5862 return main.ERROR
5863 except Exception:
5864 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005865 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005866
5867 def workQueueAddMultiple( self, queueName, value1, value2 ):
5868 """
5869 CLI command to add two strings to the specified Work Queue.
5870 This function uses the distributed primitives test app, which
5871 gives some cli access to distributed primitives for testing
5872 purposes only.
5873
5874 Required arguments:
5875 queueName - The name of the queue to add to
5876 value1 - The first value to add to the queue
5877 value2 - The second value to add to the queue
5878 returns:
5879 main.TRUE on success, main.FALSE on failure and
5880 main.ERROR on error.
5881 """
5882 try:
5883 queueName = str( queueName )
5884 value1 = str( value1 )
5885 value2 = str( value2 )
5886 prefix = "work-queue-test"
5887 operation = "addMultiple"
5888 cmdStr = " ".join( [ prefix, queueName, operation, value1, value2 ] )
5889 output = self.distPrimitivesSend( cmdStr )
5890 if "Invalid operation name" in output:
5891 main.log.warn( output )
5892 return main.ERROR
5893 elif "Done" in output:
5894 return main.TRUE
5895 except TypeError:
5896 main.log.exception( self.name + ": Object not as expected" )
5897 return main.ERROR
5898 except Exception:
5899 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005900 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005901
5902 def workQueueTakeAndComplete( self, queueName, number=1 ):
5903 """
5904 CLI command to take a value from the specified Work Queue and compelte it.
5905 This function uses the distributed primitives test app, which
5906 gives some cli access to distributed primitives for testing
5907 purposes only.
5908
5909 Required arguments:
5910 queueName - The name of the queue to add to
5911 number - The number of items to take and complete
5912 returns:
5913 main.TRUE on success, main.FALSE on failure and
5914 main.ERROR on error.
5915 """
5916 try:
5917 queueName = str( queueName )
5918 number = str( int( number ) )
5919 prefix = "work-queue-test"
5920 operation = "takeAndComplete"
5921 cmdStr = " ".join( [ prefix, queueName, operation, number ] )
5922 output = self.distPrimitivesSend( cmdStr )
5923 if "Invalid operation name" in output:
5924 main.log.warn( output )
5925 return main.ERROR
5926 elif "Done" in output:
5927 return main.TRUE
5928 except TypeError:
5929 main.log.exception( self.name + ": Object not as expected" )
5930 return main.ERROR
5931 except Exception:
5932 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005933 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005934
5935 def workQueueDestroy( self, queueName ):
5936 """
5937 CLI command to destroy the specified Work Queue.
5938 This function uses the distributed primitives test app, which
5939 gives some cli access to distributed primitives for testing
5940 purposes only.
5941
5942 Required arguments:
5943 queueName - The name of the queue to add to
5944 returns:
5945 main.TRUE on success, main.FALSE on failure and
5946 main.ERROR on error.
5947 """
5948 try:
5949 queueName = str( queueName )
5950 prefix = "work-queue-test"
5951 operation = "destroy"
5952 cmdStr = " ".join( [ prefix, queueName, operation ] )
5953 output = self.distPrimitivesSend( cmdStr )
5954 if "Invalid operation name" in output:
5955 main.log.warn( output )
5956 return main.ERROR
5957 return main.TRUE
5958 except TypeError:
5959 main.log.exception( self.name + ": Object not as expected" )
5960 return main.ERROR
5961 except Exception:
5962 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005963 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005964
5965 def workQueueTotalPending( self, queueName ):
5966 """
5967 CLI command to get the Total Pending items of the specified Work Queue.
5968 This function uses the distributed primitives test app, which
5969 gives some cli access to distributed primitives for testing
5970 purposes only.
5971
5972 Required arguments:
5973 queueName - The name of the queue to add to
5974 returns:
5975 The number of Pending items in the specified work queue or
5976 None on error
5977 """
5978 try:
5979 queueName = str( queueName )
5980 prefix = "work-queue-test"
5981 operation = "totalPending"
5982 cmdStr = " ".join( [ prefix, queueName, operation ] )
5983 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08005984 main.log.debug( self.name + ": work queue unparsed: " + output )
5985 output = output.split( "\r\n" )[ -1 ]
5986 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07005987 pattern = r'\d+'
5988 if "Invalid operation name" in output:
5989 main.log.warn( output )
5990 return None
5991 else:
5992 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005993 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07005994 except ( AttributeError, TypeError ):
5995 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
5996 return None
5997 except Exception:
5998 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005999 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006000
6001 def workQueueTotalCompleted( self, queueName ):
6002 """
6003 CLI command to get the Total Completed items of the specified Work Queue.
6004 This function uses the distributed primitives test app, which
6005 gives some cli access to distributed primitives for testing
6006 purposes only.
6007
6008 Required arguments:
6009 queueName - The name of the queue to add to
6010 returns:
6011 The number of complete items in the specified work queue or
6012 None on error
6013 """
6014 try:
6015 queueName = str( queueName )
6016 prefix = "work-queue-test"
6017 operation = "totalCompleted"
6018 cmdStr = " ".join( [ prefix, queueName, operation ] )
6019 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006020 main.log.debug( self.name + ": work queue unparsed: " + output )
6021 output = output.split( "\r\n" )[ -1 ]
6022 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006023 pattern = r'\d+'
6024 if "Invalid operation name" in output:
6025 main.log.warn( output )
6026 return None
6027 else:
6028 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006029 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006030 except ( AttributeError, TypeError ):
6031 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6032 return None
6033 except Exception:
6034 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006035 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006036
6037 def workQueueTotalInProgress( self, queueName ):
6038 """
6039 CLI command to get the Total In Progress items of the specified Work Queue.
6040 This function uses the distributed primitives test app, which
6041 gives some cli access to distributed primitives for testing
6042 purposes only.
6043
6044 Required arguments:
6045 queueName - The name of the queue to add to
6046 returns:
6047 The number of In Progress items in the specified work queue or
6048 None on error
6049 """
6050 try:
6051 queueName = str( queueName )
6052 prefix = "work-queue-test"
6053 operation = "totalInProgress"
6054 cmdStr = " ".join( [ prefix, queueName, operation ] )
6055 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006056 main.log.debug( self.name + ": work queue unparsed: " + output )
6057 output = output.split( "\r\n" )[ -1 ]
6058 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006059 pattern = r'\d+'
6060 if "Invalid operation name" in output:
6061 main.log.warn( output )
6062 return None
6063 else:
6064 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006065 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006066 except ( AttributeError, TypeError ):
6067 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6068 return None
6069 except Exception:
6070 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006071 main.cleanAndExit()
Jeremy Ronquillo818bc7c2017-08-09 17:14:53 +00006072
6073 def events( self, args='-a' ):
6074 """
6075 Description: Returns events -a command output
6076 Optional:
6077 add other arguments
6078 """
6079 try:
6080 cmdStr = "events"
6081 if args:
6082 cmdStr += " " + args
6083 handle = self.sendline( cmdStr )
6084 assert handle is not None, "Error in sendline"
6085 assert "Command not found:" not in handle, handle
6086 return handle
6087 except AssertionError:
6088 main.log.exception( "" )
6089 return None
6090 except TypeError:
6091 main.log.exception( self.name + ": Object not as expected" )
6092 return None
6093 except pexpect.EOF:
6094 main.log.error( self.name + ": EOF exception found" )
6095 main.log.error( self.name + ": " + self.handle.before )
6096 main.cleanAndExit()
6097 except Exception:
6098 main.log.exception( self.name + ": Uncaught exception!" )
6099 main.cleanAndExit()
6100
6101 def getMaster( self, deviceID ):
6102 """
6103 Description: Obtains current master using "roles" command for a specific deviceID
6104 """
6105 try:
6106 return str( self.getRole( deviceID )[ 'master' ] )
6107 except AssertionError:
6108 main.log.exception( "" )
6109 return None
6110 except TypeError:
6111 main.log.exception( self.name + ": Object not as expected" )
6112 return None
6113 except pexpect.EOF:
6114 main.log.error( self.name + ": EOF exception found" )
6115 main.log.error( self.name + ": " + self.handle.before )
6116 main.cleanAndExit()
6117 except Exception:
6118 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lime6fe3c42017-10-18 16:28:40 -07006119 main.cleanAndExit()
Jon Halla478b852017-12-04 15:00:15 -08006120
6121 def issu( self ):
6122 """
6123 Short summary of In-Service Software Upgrade status
6124
6125 Returns the output of the cli command or None on Error
6126 """
6127 try:
6128 cmdStr = "issu"
6129 handle = self.sendline( cmdStr )
6130 assert handle is not None, "Error in sendline"
6131 assert "Command not found:" not in handle, handle
6132 assert "Unsupported command:" not in handle, handle
6133 return handle
6134 except AssertionError:
6135 main.log.exception( "" )
6136 return None
6137 except TypeError:
6138 main.log.exception( self.name + ": Object not as expected" )
6139 return None
6140 except pexpect.EOF:
6141 main.log.error( self.name + ": EOF exception found" )
6142 main.log.error( self.name + ": " + self.handle.before )
6143 main.cleanAndExit()
6144 except Exception:
6145 main.log.exception( self.name + ": Uncaught exception!" )
6146 main.cleanAndExit()
6147
6148 def issuInit( self ):
6149 """
6150 Initiates an In-Service Software Upgrade
6151
6152 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6153 """
6154 try:
6155 cmdStr = "issu init"
6156 handle = self.sendline( cmdStr )
6157 assert handle is not None, "Error in sendline"
6158 assert "Command not found:" not in handle, handle
6159 assert "Unsupported command:" not in handle, handle
6160 if "Initialized" in handle:
6161 return main.TRUE
6162 else:
6163 return main.FALSE
6164 except AssertionError:
6165 main.log.exception( "" )
6166 return main.ERROR
6167 except TypeError:
6168 main.log.exception( self.name + ": Object not as expected" )
6169 return main.ERROR
6170 except pexpect.EOF:
6171 main.log.error( self.name + ": EOF exception found" )
6172 main.log.error( self.name + ": " + self.handle.before )
6173 main.cleanAndExit()
6174 except Exception:
6175 main.log.exception( self.name + ": Uncaught exception!" )
6176 main.cleanAndExit()
6177
6178 def issuUpgrade( self ):
6179 """
6180 Transitions stores to upgraded nodes
6181
6182 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6183 """
6184 try:
6185 cmdStr = "issu upgrade"
6186 handle = self.sendline( cmdStr )
6187 assert handle is not None, "Error in sendline"
6188 assert "Command not found:" not in handle, handle
6189 assert "Unsupported command:" not in handle, handle
6190 if "Upgraded" in handle:
6191 return main.TRUE
6192 else:
6193 return main.FALSE
6194 except AssertionError:
6195 main.log.exception( "" )
6196 return main.ERROR
6197 except TypeError:
6198 main.log.exception( self.name + ": Object not as expected" )
6199 return main.ERROR
6200 except pexpect.EOF:
6201 main.log.error( self.name + ": EOF exception found" )
6202 main.log.error( self.name + ": " + self.handle.before )
6203 main.cleanAndExit()
6204 except Exception:
6205 main.log.exception( self.name + ": Uncaught exception!" )
6206 main.cleanAndExit()
6207
6208 def issuCommit( self ):
6209 """
6210 Finalizes an In-Service Software Upgrade
6211
6212 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6213 """
6214 try:
6215 cmdStr = "issu commit"
6216 handle = self.sendline( cmdStr )
6217 assert handle is not None, "Error in sendline"
6218 assert "Command not found:" not in handle, handle
6219 assert "Unsupported command:" not in handle, handle
6220 # TODO: Check the version returned by this command
6221 if "Committed version" in handle:
6222 return main.TRUE
6223 else:
6224 return main.FALSE
6225 except AssertionError:
6226 main.log.exception( "" )
6227 return main.ERROR
6228 except TypeError:
6229 main.log.exception( self.name + ": Object not as expected" )
6230 return main.ERROR
6231 except pexpect.EOF:
6232 main.log.error( self.name + ": EOF exception found" )
6233 main.log.error( self.name + ": " + self.handle.before )
6234 main.cleanAndExit()
6235 except Exception:
6236 main.log.exception( self.name + ": Uncaught exception!" )
6237 main.cleanAndExit()
6238
6239 def issuRollback( self ):
6240 """
6241 Rolls back an In-Service Software Upgrade
6242
6243 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6244 """
6245 try:
6246 cmdStr = "issu rollback"
6247 handle = self.sendline( cmdStr )
6248 assert handle is not None, "Error in sendline"
6249 assert "Command not found:" not in handle, handle
6250 assert "Unsupported command:" not in handle, handle
6251 # TODO: Check the version returned by this command
6252 if "Rolled back to version" in handle:
6253 return main.TRUE
6254 else:
6255 return main.FALSE
6256 except AssertionError:
6257 main.log.exception( "" )
6258 return main.ERROR
6259 except TypeError:
6260 main.log.exception( self.name + ": Object not as expected" )
6261 return main.ERROR
6262 except pexpect.EOF:
6263 main.log.error( self.name + ": EOF exception found" )
6264 main.log.error( self.name + ": " + self.handle.before )
6265 main.cleanAndExit()
6266 except Exception:
6267 main.log.exception( self.name + ": Uncaught exception!" )
6268 main.cleanAndExit()
6269
6270 def issuReset( self ):
6271 """
6272 Resets the In-Service Software Upgrade status after a rollback
6273
6274 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6275 """
6276 try:
6277 cmdStr = "issu reset"
6278 handle = self.sendline( cmdStr )
6279 assert handle is not None, "Error in sendline"
6280 assert "Command not found:" not in handle, handle
6281 assert "Unsupported command:" not in handle, handle
6282 # TODO: Check the version returned by this command
6283 if "Reset version" in handle:
6284 return main.TRUE
6285 else:
6286 return main.FALSE
6287 except AssertionError:
6288 main.log.exception( "" )
6289 return main.ERROR
6290 except TypeError:
6291 main.log.exception( self.name + ": Object not as expected" )
6292 return main.ERROR
6293 except pexpect.EOF:
6294 main.log.error( self.name + ": EOF exception found" )
6295 main.log.error( self.name + ": " + self.handle.before )
6296 main.cleanAndExit()
6297 except Exception:
6298 main.log.exception( self.name + ": Uncaught exception!" )
6299 main.cleanAndExit()
6300
6301 def issuStatus( self ):
6302 """
6303 Status of an In-Service Software Upgrade
6304
6305 Returns the output of the cli command or None on Error
6306 """
6307 try:
6308 cmdStr = "issu status"
6309 handle = self.sendline( cmdStr )
6310 assert handle is not None, "Error in sendline"
6311 assert "Command not found:" not in handle, handle
6312 assert "Unsupported command:" not in handle, handle
6313 return handle
6314 except AssertionError:
6315 main.log.exception( "" )
6316 return None
6317 except TypeError:
6318 main.log.exception( self.name + ": Object not as expected" )
6319 return None
6320 except pexpect.EOF:
6321 main.log.error( self.name + ": EOF exception found" )
6322 main.log.error( self.name + ": " + self.handle.before )
6323 main.cleanAndExit()
6324 except Exception:
6325 main.log.exception( self.name + ": Uncaught exception!" )
6326 main.cleanAndExit()
6327
6328 def issuVersion( self ):
6329 """
6330 Get the version of an In-Service Software Upgrade
6331
6332 Returns the output of the cli command or None on Error
6333 """
6334 try:
6335 cmdStr = "issu version"
6336 handle = self.sendline( cmdStr )
6337 assert handle is not None, "Error in sendline"
6338 assert "Command not found:" not in handle, handle
6339 assert "Unsupported command:" not in handle, handle
6340 return handle
6341 except AssertionError:
6342 main.log.exception( "" )
6343 return None
6344 except TypeError:
6345 main.log.exception( self.name + ": Object not as expected" )
6346 return None
6347 except pexpect.EOF:
6348 main.log.error( self.name + ": EOF exception found" )
6349 main.log.error( self.name + ": " + self.handle.before )
6350 main.cleanAndExit()
6351 except Exception:
6352 main.log.exception( self.name + ": Uncaught exception!" )
6353 main.cleanAndExit()
You Wange24d6272018-03-27 21:18:50 -07006354
6355 def mcastJoin( self, sIP, groupIP, sPort, dPorts ):
6356 """
6357 Create a multicast route by calling 'mcast-join' command
6358 sIP: source IP of the multicast route
6359 groupIP: group IP of the multicast route
6360 sPort: source port (e.g. of:0000000000000001/3 ) of the multicast route
6361 dPorts: a list of destination ports of the multicast route
6362 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6363 """
6364 try:
6365 cmdStr = "mcast-join"
6366 cmdStr += " " + str( sIP )
6367 cmdStr += " " + str( groupIP )
6368 cmdStr += " " + str( sPort )
6369 assert isinstance( dPorts, list )
6370 for dPort in dPorts:
6371 cmdStr += " " + str( dPort )
6372 handle = self.sendline( cmdStr )
6373 assert handle is not None, "Error in sendline"
6374 assert "Command not found:" not in handle, handle
6375 assert "Unsupported command:" not in handle, handle
6376 assert "Error executing command" not in handle, handle
6377 if "Added the mcast route" in handle:
6378 return main.TRUE
6379 else:
6380 return main.FALSE
6381 except AssertionError:
6382 main.log.exception( "" )
6383 return None
6384 except TypeError:
6385 main.log.exception( self.name + ": Object not as expected" )
6386 return None
6387 except pexpect.EOF:
6388 main.log.error( self.name + ": EOF exception found" )
6389 main.log.error( self.name + ": " + self.handle.before )
6390 main.cleanAndExit()
6391 except Exception:
6392 main.log.exception( self.name + ": Uncaught exception!" )
6393 main.cleanAndExit()
6394
6395 def mcastDelete( self, sIP, groupIP, dPorts ):
6396 """
6397 Delete a multicast route by calling 'mcast-delete' command
6398 sIP: source IP of the multicast route
6399 groupIP: group IP of the multicast route
6400 dPorts: a list of destination ports of the multicast route
6401 Returns main.TRUE if mcast route is deleted; Otherwise main.FALSE
6402 """
6403 try:
6404 cmdStr = "mcast-delete"
6405 cmdStr += " " + str( sIP )
6406 cmdStr += " " + str( groupIP )
6407 assert isinstance( dPorts, list )
6408 for dPort in dPorts:
6409 cmdStr += " " + str( dPort )
6410 handle = self.sendline( cmdStr )
6411 assert handle is not None, "Error in sendline"
6412 assert "Command not found:" not in handle, handle
6413 assert "Unsupported command:" not in handle, handle
6414 assert "Error executing command" not in handle, handle
6415 if "Updated the mcast route" in handle:
6416 return main.TRUE
6417 else:
6418 return main.FALSE
6419 except AssertionError:
6420 main.log.exception( "" )
6421 return None
6422 except TypeError:
6423 main.log.exception( self.name + ": Object not as expected" )
6424 return None
6425 except pexpect.EOF:
6426 main.log.error( self.name + ": EOF exception found" )
6427 main.log.error( self.name + ": " + self.handle.before )
6428 main.cleanAndExit()
6429 except Exception:
6430 main.log.exception( self.name + ": Uncaught exception!" )
6431 main.cleanAndExit()
6432
6433 def mcastHostJoin( self, sAddr, gAddr, srcs, sinks ):
6434 """
6435 Create a multicast route by calling 'mcast-host-join' command
6436 sAddr: we can provide * for ASM or a specific address for SSM
6437 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006438 srcs: a list of HostId of the sources e.g. ["00:AA:00:00:00:01/None"]
You Wange24d6272018-03-27 21:18:50 -07006439 sinks: a list of HostId of the sinks e.g. ["00:AA:00:00:01:05/40"]
6440 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6441 """
6442 try:
6443 cmdStr = "mcast-host-join"
6444 cmdStr += " -sAddr " + str( sAddr )
6445 cmdStr += " -gAddr " + str( gAddr )
6446 assert isinstance( srcs, list )
6447 for src in srcs:
6448 cmdStr += " -srcs " + str( src )
6449 assert isinstance( sinks, list )
6450 for sink in sinks:
6451 cmdStr += " -sinks " + str( sink )
6452 handle = self.sendline( cmdStr )
6453 assert handle is not None, "Error in sendline"
6454 assert "Command not found:" not in handle, handle
6455 assert "Unsupported command:" not in handle, handle
6456 assert "Error executing command" not in handle, handle
6457 if "Added the mcast route" in handle:
6458 return main.TRUE
6459 else:
6460 return main.FALSE
6461 except AssertionError:
6462 main.log.exception( "" )
6463 return None
6464 except TypeError:
6465 main.log.exception( self.name + ": Object not as expected" )
6466 return None
6467 except pexpect.EOF:
6468 main.log.error( self.name + ": EOF exception found" )
6469 main.log.error( self.name + ": " + self.handle.before )
6470 main.cleanAndExit()
6471 except Exception:
6472 main.log.exception( self.name + ": Uncaught exception!" )
6473 main.cleanAndExit()
6474
6475 def mcastHostDelete( self, sAddr, gAddr, host=None ):
6476 """
6477 Delete multicast sink(s) by calling 'mcast-host-delete' command
6478 sAddr: we can provide * for ASM or a specific address for SSM
6479 gAddr: specifies multicast group address
You Wangc02d8352018-04-17 16:42:10 -07006480 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
You Wange24d6272018-03-27 21:18:50 -07006481 will delete the route if not specified
6482 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6483 """
6484 try:
6485 cmdStr = "mcast-host-delete"
6486 cmdStr += " -sAddr " + str( sAddr )
6487 cmdStr += " -gAddr " + str( gAddr )
6488 if host:
6489 cmdStr += " -h " + str( host )
6490 handle = self.sendline( cmdStr )
6491 assert handle is not None, "Error in sendline"
6492 assert "Command not found:" not in handle, handle
6493 assert "Unsupported command:" not in handle, handle
6494 assert "Error executing command" not in handle, handle
6495 if "Updated the mcast route" in handle:
6496 return main.TRUE
6497 elif "Deleted the mcast route" in handle:
6498 return main.TRUE
6499 else:
6500 return main.FALSE
6501 except AssertionError:
6502 main.log.exception( "" )
6503 return None
6504 except TypeError:
6505 main.log.exception( self.name + ": Object not as expected" )
6506 return None
6507 except pexpect.EOF:
6508 main.log.error( self.name + ": EOF exception found" )
6509 main.log.error( self.name + ": " + self.handle.before )
6510 main.cleanAndExit()
6511 except Exception:
6512 main.log.exception( self.name + ": Uncaught exception!" )
6513 main.cleanAndExit()
6514
You Wang547893e2018-05-08 13:34:59 -07006515 def mcastSinkDelete( self, sAddr, gAddr, sink=None ):
6516 """
6517 Delete multicast sink(s) by calling 'mcast-sink-delete' command
6518 sAddr: we can provide * for ASM or a specific address for SSM
6519 gAddr: specifies multicast group address
6520 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
6521 will delete the route if not specified
6522 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6523 """
6524 try:
6525 cmdStr = "mcast-sink-delete"
6526 cmdStr += " -sAddr " + str( sAddr )
6527 cmdStr += " -gAddr " + str( gAddr )
6528 if sink:
6529 cmdStr += " -s " + str( sink )
6530 handle = self.sendline( cmdStr )
6531 assert handle is not None, "Error in sendline"
6532 assert "Command not found:" not in handle, handle
6533 assert "Unsupported command:" not in handle, handle
6534 assert "Error executing command" not in handle, handle
6535 if "Updated the mcast route" in handle:
6536 return main.TRUE
6537 elif "Deleted the mcast route" in handle:
6538 return main.TRUE
6539 else:
6540 return main.FALSE
6541 except AssertionError:
6542 main.log.exception( "" )
6543 return None
6544 except TypeError:
6545 main.log.exception( self.name + ": Object not as expected" )
6546 return None
6547 except pexpect.EOF:
6548 main.log.error( self.name + ": EOF exception found" )
6549 main.log.error( self.name + ": " + self.handle.before )
6550 main.cleanAndExit()
6551 except Exception:
6552 main.log.exception( self.name + ": Uncaught exception!" )
6553 main.cleanAndExit()
6554
You Wange24d6272018-03-27 21:18:50 -07006555 def mcastSourceDelete( self, sAddr, gAddr, srcs=None ):
6556 """
6557 Delete multicast src(s) by calling 'mcast-source-delete' command
6558 sAddr: we can provide * for ASM or a specific address for SSM
6559 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006560 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 -07006561 will delete the route if not specified
6562 Returns main.TRUE if mcast sink is deleted; Otherwise main.FALSE
6563 """
6564 try:
6565 cmdStr = "mcast-source-delete"
6566 cmdStr += " -sAddr " + str( sAddr )
6567 cmdStr += " -gAddr " + str( gAddr )
6568 if srcs:
6569 assert isinstance( srcs, list )
6570 for src in srcs:
6571 cmdStr += " -src " + str( src )
6572 handle = self.sendline( cmdStr )
6573 assert handle is not None, "Error in sendline"
6574 assert "Command not found:" not in handle, handle
6575 assert "Unsupported command:" not in handle, handle
6576 assert "Error executing command" not in handle, handle
6577 if "Updated the mcast route" in handle:
6578 return main.TRUE
6579 elif "Deleted the mcast route" in handle:
6580 return main.TRUE
6581 else:
6582 return main.FALSE
6583 except AssertionError:
6584 main.log.exception( "" )
6585 return None
6586 except TypeError:
6587 main.log.exception( self.name + ": Object not as expected" )
6588 return None
6589 except pexpect.EOF:
6590 main.log.error( self.name + ": EOF exception found" )
6591 main.log.error( self.name + ": " + self.handle.before )
6592 main.cleanAndExit()
6593 except Exception:
6594 main.log.exception( self.name + ": Uncaught exception!" )
6595 main.cleanAndExit()
You Wang5da39c82018-04-26 22:55:08 -07006596
6597 def netcfg( self, jsonFormat=True, args="" ):
6598 """
6599 Run netcfg cli command with given args
6600 """
6601 try:
6602 cmdStr = "netcfg"
6603 if jsonFormat:
6604 cmdStr = cmdStr + " -j"
6605 if args:
6606 cmdStr = cmdStr + " " + str( args )
6607 handle = self.sendline( cmdStr )
6608 assert handle is not None, "Error in sendline"
6609 assert "Command not found:" not in handle, handle
6610 assert "Unsupported command:" not in handle, handle
6611 assert "Error executing command" not in handle, handle
6612 return handle
6613 except AssertionError:
6614 main.log.exception( "" )
6615 return None
6616 except TypeError:
6617 main.log.exception( self.name + ": Object not as expected" )
6618 return None
6619 except pexpect.EOF:
6620 main.log.error( self.name + ": EOF exception found" )
6621 main.log.error( self.name + ": " + self.handle.before )
6622 main.cleanAndExit()
6623 except Exception:
6624 main.log.exception( self.name + ": Uncaught exception!" )
6625 main.cleanAndExit()
6626
You Wang0fa76e72018-05-18 11:33:25 -07006627 def composeT3Command( self, sAddr, dAddr, ipv6=False, verbose=True, simple=False ):
You Wang5da39c82018-04-26 22:55:08 -07006628 """
You Wang54b1d672018-06-11 16:44:13 -07006629 Compose and return a list of t3-troubleshoot cli commands for given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006630 Options:
6631 sAddr: IP address of the source host
6632 dAddr: IP address of the destination host
You Wang0fa76e72018-05-18 11:33:25 -07006633 ipv6: True if hosts are IPv6
6634 verbose: return verbose t3 output if True
6635 simple: compose command for t3-troubleshoot-simple if True
You Wang5da39c82018-04-26 22:55:08 -07006636 """
6637 try:
6638 # Collect information of both hosts from onos
6639 hosts = self.hosts()
6640 hosts = json.loads( hosts )
6641 sHost = None
6642 dHost = None
6643 for host in hosts:
6644 if sAddr in host[ "ipAddresses" ]:
6645 sHost = host
6646 elif dAddr in host[ "ipAddresses" ]:
6647 dHost = host
6648 if sHost and dHost:
6649 break
6650 assert sHost, "Not able to find host with IP {}".format( sAddr )
You Wang54b1d672018-06-11 16:44:13 -07006651 cmdList = []
You Wang5d9527b2018-05-29 17:08:54 -07006652 if simple:
6653 assert dHost, "Not able to find host with IP {}".format( dAddr )
You Wang54b1d672018-06-11 16:44:13 -07006654 cmdStr = "t3-troubleshoot-simple"
6655 if verbose:
6656 cmdStr += " -vv"
6657 if ipv6:
6658 cmdStr += " -et ipv6"
You Wang0fa76e72018-05-18 11:33:25 -07006659 cmdStr += " {}/{} {}/{}".format( sHost[ "mac" ], sHost[ "vlan" ], dHost[ "mac" ], dHost[ "vlan" ] )
You Wang54b1d672018-06-11 16:44:13 -07006660 cmdList.append( cmdStr )
You Wang0fa76e72018-05-18 11:33:25 -07006661 else:
You Wang54b1d672018-06-11 16:44:13 -07006662 for location in sHost[ "locations" ]:
6663 cmdStr = "t3-troubleshoot"
6664 if verbose:
6665 cmdStr += " -vv"
6666 if ipv6:
6667 cmdStr += " -et ipv6"
6668 cmdStr += " -s " + str( sAddr )
6669 cmdStr += " -sp " + str( location[ "elementId" ] ) + "/" + str( location[ "port" ] )
6670 cmdStr += " -sm " + str( sHost[ "mac" ] )
6671 if sHost[ "vlan" ] != "None":
6672 cmdStr += " -vid " + sHost[ "vlan" ]
6673 cmdStr += " -d " + str( dAddr )
6674 netcfg = self.netcfg( args="devices {}".format( location[ "elementId" ] ) )
6675 netcfg = json.loads( netcfg )
6676 assert netcfg, "Failed to get netcfg"
6677 cmdStr += " -dm " + str( netcfg[ "segmentrouting" ][ "routerMac" ] )
6678 cmdList.append( cmdStr )
6679 return cmdList
You Wang5da39c82018-04-26 22:55:08 -07006680 except AssertionError:
6681 main.log.exception( "" )
6682 return None
6683 except ( KeyError, TypeError ):
6684 main.log.exception( self.name + ": Object not as expected" )
6685 return None
6686 except Exception:
6687 main.log.exception( self.name + ": Uncaught exception!" )
6688 main.cleanAndExit()
6689
6690 def t3( self, sAddr, dAddr, ipv6=False ):
6691 """
You Wang54b1d672018-06-11 16:44:13 -07006692 Run t3-troubleshoot cli commands for all posible routes given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006693 Options:
6694 sAddr: IP address of the source host
6695 dAddr: IP address of the destination host
6696 """
6697 try:
You Wang54b1d672018-06-11 16:44:13 -07006698 cmdList = self.composeT3Command( sAddr, dAddr, ipv6 )
6699 assert cmdList is not None, "composeT3Command returned None"
6700 t3Output = ""
6701 for cmdStr in cmdList:
6702 handle = self.sendline( cmdStr )
6703 assert handle is not None, "Error in sendline"
6704 assert "Command not found:" not in handle, handle
6705 assert "Unsupported command:" not in handle, handle
6706 assert "Error executing command" not in handle, handle
6707 assert "Tracing packet" in handle
6708 t3Output += handle
6709 return t3Output
You Wang5da39c82018-04-26 22:55:08 -07006710 except AssertionError:
6711 main.log.exception( "" )
6712 return None
6713 except pexpect.EOF:
6714 main.log.error( self.name + ": EOF exception found" )
6715 main.log.error( self.name + ": " + self.handle.before )
6716 main.cleanAndExit()
6717 except Exception:
6718 main.log.exception( self.name + ": Uncaught exception!" )
6719 main.cleanAndExit()