blob: 80e024680e81e295b7ac9a6cdf455e6eaad4b6ba [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
Jon Hall6c9e2da2018-11-06 12:01:23 -080061 self.karafPrompt = "sdn@root >" # FIXME: make configurable
You Wangdb8cd0a2016-05-26 15:19:45 -070062 self.graph = Graph()
Devin Limdc78e202017-06-09 18:30:07 -070063 super( OnosCliDriver, self ).__init__()
kelvin8ec71442015-01-15 16:57:00 -080064
Jeremy Ronquillo82705492017-10-18 14:19:55 -070065 def checkOptions( self, var, defaultVar ):
Devin Limdc78e202017-06-09 18:30:07 -070066 if var is None or var == "":
67 return defaultVar
68 return var
Jeremy Ronquillo82705492017-10-18 14:19:55 -070069
kelvin8ec71442015-01-15 16:57:00 -080070 def connect( self, **connectargs ):
71 """
andrewonlab95ce8322014-10-13 14:12:04 -040072 Creates ssh handle for ONOS cli.
kelvin8ec71442015-01-15 16:57:00 -080073 """
andrewonlab95ce8322014-10-13 14:12:04 -040074 try:
75 for key in connectargs:
kelvin8ec71442015-01-15 16:57:00 -080076 vars( self )[ key ] = connectargs[ key ]
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 ]
85
Jeremy Ronquillo82705492017-10-18 14:19:55 -070086 self.home = self.checkOptions( self.home, "~/onos" )
87 self.karafUser = self.checkOptions( self.karafUser, self.user_name )
88 self.karafPass = self.checkOptions( self.karafPass, self.pwd )
andrewonlab95ce8322014-10-13 14:12:04 -040089
kelvin-onlaba4074292015-07-09 15:19:49 -070090 for key in self.options:
91 if key == 'onosIp':
92 self.onosIp = self.options[ 'onosIp' ]
93 break
94
kelvin8ec71442015-01-15 16:57:00 -080095 self.name = self.options[ 'name' ]
kelvin-onlaba4074292015-07-09 15:19:49 -070096
97 try:
Jon Hallc6793552016-01-19 14:18:37 -080098 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -070099 self.ip_address = os.getenv( str( self.ip_address ) )
100 else:
101 main.log.info( self.name +
102 ": Trying to connect to " +
103 self.ip_address )
104
105 except KeyError:
106 main.log.info( "Invalid host name," +
107 " connecting to local host instead" )
108 self.ip_address = 'localhost'
109 except Exception as inst:
110 main.log.error( "Uncaught exception: " + str( inst ) )
111
kelvin8ec71442015-01-15 16:57:00 -0800112 self.handle = super( OnosCliDriver, self ).connect(
kelvin-onlab08679eb2015-01-21 16:11:48 -0800113 user_name=self.user_name,
114 ip_address=self.ip_address,
kelvin-onlab898a6c62015-01-16 14:13:53 -0800115 port=self.port,
116 pwd=self.pwd,
117 home=self.home )
andrewonlab95ce8322014-10-13 14:12:04 -0400118
kelvin8ec71442015-01-15 16:57:00 -0800119 self.handle.sendline( "cd " + self.home )
Devin Limdc78e202017-06-09 18:30:07 -0700120 self.handle.expect( self.prompt )
andrewonlab95ce8322014-10-13 14:12:04 -0400121 if self.handle:
122 return self.handle
kelvin8ec71442015-01-15 16:57:00 -0800123 else:
124 main.log.info( "NO ONOS HANDLE" )
andrewonlab95ce8322014-10-13 14:12:04 -0400125 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -0800126 except TypeError:
127 main.log.exception( self.name + ": Object not as expected" )
128 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400129 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800130 main.log.error( self.name + ": EOF exception found" )
131 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700132 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800133 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800134 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700135 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400136
kelvin8ec71442015-01-15 16:57:00 -0800137 def disconnect( self ):
138 """
andrewonlab95ce8322014-10-13 14:12:04 -0400139 Called when Test is complete to disconnect the ONOS handle.
kelvin8ec71442015-01-15 16:57:00 -0800140 """
Jon Halld61331b2015-02-17 16:35:47 -0800141 response = main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -0400142 try:
Jon Hall61282e32015-03-19 11:34:11 -0700143 if self.handle:
144 i = self.logout()
145 if i == main.TRUE:
146 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -0700147 self.handle.expect( self.prompt )
Jon Hall61282e32015-03-19 11:34:11 -0700148 self.handle.sendline( "exit" )
149 self.handle.expect( "closed" )
Jon Halld4d4b372015-01-28 16:02:41 -0800150 except TypeError:
151 main.log.exception( self.name + ": Object not as expected" )
Jon Halld61331b2015-02-17 16:35:47 -0800152 response = main.FALSE
andrewonlab95ce8322014-10-13 14:12:04 -0400153 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800154 main.log.error( self.name + ": EOF exception found" )
155 main.log.error( self.name + ": " + self.handle.before )
Jon Hall61282e32015-03-19 11:34:11 -0700156 except ValueError:
Jon Hall1a77a1e2015-04-06 10:41:13 -0700157 main.log.exception( "Exception in disconnect of " + self.name )
Jon Hall61282e32015-03-19 11:34:11 -0700158 response = main.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -0800159 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800160 main.log.exception( self.name + ": Connection failed to the host" )
andrewonlab95ce8322014-10-13 14:12:04 -0400161 response = main.FALSE
162 return response
163
kelvin8ec71442015-01-15 16:57:00 -0800164 def logout( self ):
165 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500166 Sends 'logout' command to ONOS cli
Jon Hall61282e32015-03-19 11:34:11 -0700167 Returns main.TRUE if exited CLI and
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000168 main.FALSE on timeout (not guranteed you are disconnected)
Jon Hall61282e32015-03-19 11:34:11 -0700169 None on TypeError
170 Exits test on unknown error or pexpect exits unexpectedly
kelvin8ec71442015-01-15 16:57:00 -0800171 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500172 try:
Jon Hall61282e32015-03-19 11:34:11 -0700173 if self.handle:
174 self.handle.sendline( "" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800175 i = self.handle.expect( [ self.karafPrompt, self.prompt, pexpect.TIMEOUT ],
Jon Hall61282e32015-03-19 11:34:11 -0700176 timeout=10 )
177 if i == 0: # In ONOS CLI
178 self.handle.sendline( "logout" )
Devin Limdc78e202017-06-09 18:30:07 -0700179 j = self.handle.expect( [ self.prompt,
Jon Hallbfe00002016-04-05 10:23:54 -0700180 "Command not found:",
181 pexpect.TIMEOUT ] )
182 if j == 0: # Successfully logged out
183 return main.TRUE
184 elif j == 1 or j == 2:
185 # ONOS didn't fully load, and logout command isn't working
186 # or the command timed out
187 self.handle.send( "\x04" ) # send ctrl-d
Jon Hall64ab3bd2016-05-13 11:29:44 -0700188 try:
Devin Limdc78e202017-06-09 18:30:07 -0700189 self.handle.expect( self.prompt )
Jon Hall64ab3bd2016-05-13 11:29:44 -0700190 except pexpect.TIMEOUT:
191 main.log.error( "ONOS did not respond to 'logout' or CTRL-d" )
Jon Hallbfe00002016-04-05 10:23:54 -0700192 return main.TRUE
Jon Halle0f0b342017-04-18 11:43:47 -0700193 else: # some other output
Jon Hallbfe00002016-04-05 10:23:54 -0700194 main.log.warn( "Unknown repsonse to logout command: '{}'",
195 repr( self.handle.before ) )
196 return main.FALSE
Jon Hall61282e32015-03-19 11:34:11 -0700197 elif i == 1: # not in CLI
198 return main.TRUE
steven30801e42f1fb2019-01-17 11:31:45 +0800199 elif i == 2: # Timeout
Jon Hall61282e32015-03-19 11:34:11 -0700200 return main.FALSE
201 else:
andrewonlab9627f432014-11-14 12:45:10 -0500202 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800203 except TypeError:
204 main.log.exception( self.name + ": Object not as expected" )
205 return None
andrewonlab38d2b4a2014-11-13 16:28:47 -0500206 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800207 main.log.error( self.name + ": eof exception found" )
Jon Hall61282e32015-03-19 11:34:11 -0700208 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700209 main.cleanAndExit()
Jon Hall61282e32015-03-19 11:34:11 -0700210 except ValueError:
Jon Hall5aa168b2015-03-23 14:23:09 -0700211 main.log.error( self.name +
212 "ValueError exception in logout method" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800213 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800214 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700215 main.cleanAndExit()
andrewonlab38d2b4a2014-11-13 16:28:47 -0500216
kelvin-onlabd3b64892015-01-20 13:26:24 -0800217 def setCell( self, cellname ):
kelvin8ec71442015-01-15 16:57:00 -0800218 """
andrewonlab95ce8322014-10-13 14:12:04 -0400219 Calls 'cell <name>' to set the environment variables on ONOSbench
kelvin8ec71442015-01-15 16:57:00 -0800220
andrewonlab95ce8322014-10-13 14:12:04 -0400221 Before issuing any cli commands, set the environment variable first.
kelvin8ec71442015-01-15 16:57:00 -0800222 """
andrewonlab95ce8322014-10-13 14:12:04 -0400223 try:
224 if not cellname:
kelvin8ec71442015-01-15 16:57:00 -0800225 main.log.error( "Must define cellname" )
Devin Lim44075962017-08-11 10:56:37 -0700226 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400227 else:
kelvin8ec71442015-01-15 16:57:00 -0800228 self.handle.sendline( "cell " + str( cellname ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800229 # Expect the cellname in the ONOSCELL variable.
kelvin8ec71442015-01-15 16:57:00 -0800230 # Note that this variable name is subject to change
andrewonlab95ce8322014-10-13 14:12:04 -0400231 # and that this driver will have to change accordingly
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700232 self.handle.expect( str( cellname ) )
andrew@onlab.usc400b112015-01-21 15:33:19 -0800233 handleBefore = self.handle.before
234 handleAfter = self.handle.after
kelvin8ec71442015-01-15 16:57:00 -0800235 # Get the rest of the handle
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700236 self.handle.sendline( "" )
237 self.handle.expect( self.prompt )
andrew@onlab.usc400b112015-01-21 15:33:19 -0800238 handleMore = self.handle.before
andrewonlab95ce8322014-10-13 14:12:04 -0400239
kelvin-onlabd3b64892015-01-20 13:26:24 -0800240 main.log.info( "Cell call returned: " + handleBefore +
241 handleAfter + handleMore )
andrewonlab95ce8322014-10-13 14:12:04 -0400242
243 return main.TRUE
244
Jon Halld4d4b372015-01-28 16:02:41 -0800245 except TypeError:
246 main.log.exception( self.name + ": Object not as expected" )
247 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400248 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800249 main.log.error( self.name + ": eof exception found" )
250 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700251 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800252 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800253 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700254 main.cleanAndExit()
kelvin8ec71442015-01-15 16:57:00 -0800255
pingping-lin57a56ce2015-05-20 16:43:48 -0700256 def startOnosCli( self, ONOSIp, karafTimeout="",
Chiyu Chengef109502016-11-21 15:51:38 -0800257 commandlineTimeout=10, onosStartTimeout=60, waitForStart=False ):
kelvin8ec71442015-01-15 16:57:00 -0800258 """
Jon Hallefbd9792015-03-05 16:11:36 -0800259 karafTimeout is an optional argument. karafTimeout value passed
kelvin-onlabd3b64892015-01-20 13:26:24 -0800260 by user would be used to set the current karaf shell idle timeout.
261 Note that when ever this property is modified the shell will exit and
Hari Krishnad7b9c202015-01-05 10:38:14 -0800262 the subsequent login would reflect new idle timeout.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800263 Below is an example to start a session with 60 seconds idle timeout
264 ( input value is in milliseconds ):
kelvin8ec71442015-01-15 16:57:00 -0800265
Hari Krishna25d42f72015-01-05 15:08:28 -0800266 tValue = "60000"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800267 main.ONOScli1.startOnosCli( ONOSIp, karafTimeout=tValue )
kelvin8ec71442015-01-15 16:57:00 -0800268
kelvin-onlabd3b64892015-01-20 13:26:24 -0800269 Note: karafTimeout is left as str so that this could be read
270 and passed to startOnosCli from PARAMS file as str.
kelvin8ec71442015-01-15 16:57:00 -0800271 """
You Wangf69ab392016-01-26 16:34:38 -0800272 self.onosIp = ONOSIp
andrewonlab95ce8322014-10-13 14:12:04 -0400273 try:
Jon Hall67253832016-12-05 09:47:13 -0800274 # Check if we are already in the cli
kelvin8ec71442015-01-15 16:57:00 -0800275 self.handle.sendline( "" )
276 x = self.handle.expect( [
Jon Hall6c9e2da2018-11-06 12:01:23 -0800277 self.prompt, self.karafPrompt ], commandlineTimeout )
andrewonlab48829f62014-11-17 13:49:01 -0500278 if x == 1:
kelvin8ec71442015-01-15 16:57:00 -0800279 main.log.info( "ONOS cli is already running" )
andrewonlab48829f62014-11-17 13:49:01 -0500280 return main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -0400281
Jon Hall67253832016-12-05 09:47:13 -0800282 # Not in CLI so login
Chiyu Chengef109502016-11-21 15:51:38 -0800283 if waitForStart:
Jeremy Ronquilloec916a42018-02-02 13:05:57 -0800284 # Wait for onos start ( onos-wait-for-start ) and enter onos cli
285 startCliCommand = "onos-wait-for-start "
Chiyu Chengef109502016-11-21 15:51:38 -0800286 else:
287 startCliCommand = "onos "
288 self.handle.sendline( startCliCommand + str( ONOSIp ) )
kelvin8ec71442015-01-15 16:57:00 -0800289 i = self.handle.expect( [
Jon Hall6c9e2da2018-11-06 12:01:23 -0800290 self.karafPrompt,
pingping-lin57a56ce2015-05-20 16:43:48 -0700291 pexpect.TIMEOUT ], onosStartTimeout )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400292
293 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800294 main.log.info( str( ONOSIp ) + " CLI Started successfully" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800295 if karafTimeout: # FIXME: This doesn't look right
kelvin8ec71442015-01-15 16:57:00 -0800296 self.handle.sendline(
Hari Krishnaac4e1782015-01-26 12:09:12 -0800297 "config:property-set -p org.apache.karaf.shell\
298 sshIdleTimeout " +
kelvin8ec71442015-01-15 16:57:00 -0800299 karafTimeout )
Devin Limdc78e202017-06-09 18:30:07 -0700300 self.handle.expect( self.prompt )
Chiyu Chengef109502016-11-21 15:51:38 -0800301 self.handle.sendline( startCliCommand + str( ONOSIp ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800302 self.handle.expect( self.karafPrompt )
303 main.log.debug( self.handle.before )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400304 return main.TRUE
305 else:
kelvin8ec71442015-01-15 16:57:00 -0800306 # If failed, send ctrl+c to process and try again
307 main.log.info( "Starting CLI failed. Retrying..." )
308 self.handle.send( "\x03" )
Chiyu Chengef109502016-11-21 15:51:38 -0800309 self.handle.sendline( startCliCommand + str( ONOSIp ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800310 i = self.handle.expect( [ self.karafPrompt, pexpect.TIMEOUT ],
kelvin8ec71442015-01-15 16:57:00 -0800311 timeout=30 )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400312 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800313 main.log.info( str( ONOSIp ) + " CLI Started " +
kelvin8ec71442015-01-15 16:57:00 -0800314 "successfully after retry attempt" )
Hari Krishnae36ef212015-01-04 14:09:13 -0800315 if karafTimeout:
kelvin8ec71442015-01-15 16:57:00 -0800316 self.handle.sendline(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800317 "config:property-set -p org.apache.karaf.shell\
318 sshIdleTimeout " +
kelvin8ec71442015-01-15 16:57:00 -0800319 karafTimeout )
Devin Limdc78e202017-06-09 18:30:07 -0700320 self.handle.expect( self.prompt )
Chiyu Chengef109502016-11-21 15:51:38 -0800321 self.handle.sendline( startCliCommand + str( ONOSIp ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800322 self.handle.expect( self.karafPrompt )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400323 return main.TRUE
324 else:
kelvin8ec71442015-01-15 16:57:00 -0800325 main.log.error( "Connection to CLI " +
kelvin-onlabd3b64892015-01-20 13:26:24 -0800326 str( ONOSIp ) + " timeout" )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400327 return main.FALSE
andrewonlab95ce8322014-10-13 14:12:04 -0400328
Jon Halld4d4b372015-01-28 16:02:41 -0800329 except TypeError:
330 main.log.exception( self.name + ": Object not as expected" )
331 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400332 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800333 main.log.error( self.name + ": EOF exception found" )
334 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700335 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800336 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800337 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700338 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400339
suibin zhang116647a2016-05-06 16:30:09 -0700340 def startCellCli( self, karafTimeout="",
341 commandlineTimeout=10, onosStartTimeout=60 ):
342 """
343 Start CLI on onos ecll handle.
344
345 karafTimeout is an optional argument. karafTimeout value passed
346 by user would be used to set the current karaf shell idle timeout.
347 Note that when ever this property is modified the shell will exit and
348 the subsequent login would reflect new idle timeout.
349 Below is an example to start a session with 60 seconds idle timeout
350 ( input value is in milliseconds ):
351
352 tValue = "60000"
353
354 Note: karafTimeout is left as str so that this could be read
355 and passed to startOnosCli from PARAMS file as str.
356 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000357
suibin zhang116647a2016-05-06 16:30:09 -0700358 try:
359 self.handle.sendline( "" )
360 x = self.handle.expect( [
Jon Hall6c9e2da2018-11-06 12:01:23 -0800361 self.prompt, self.karafPrompt ], commandlineTimeout )
suibin zhang116647a2016-05-06 16:30:09 -0700362
363 if x == 1:
364 main.log.info( "ONOS cli is already running" )
365 return main.TRUE
366
Jeremy Ronquilloec916a42018-02-02 13:05:57 -0800367 # Wait for onos start ( onos-wait-for-start ) and enter onos cli
suibin zhang116647a2016-05-06 16:30:09 -0700368 self.handle.sendline( "/opt/onos/bin/onos" )
369 i = self.handle.expect( [
Jon Hall6c9e2da2018-11-06 12:01:23 -0800370 self.karafPrompt,
suibin zhang116647a2016-05-06 16:30:09 -0700371 pexpect.TIMEOUT ], onosStartTimeout )
372
373 if i == 0:
374 main.log.info( self.name + " CLI Started successfully" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800375 if karafTimeout: # FIXME: This doesn't look right
suibin zhang116647a2016-05-06 16:30:09 -0700376 self.handle.sendline(
377 "config:property-set -p org.apache.karaf.shell\
378 sshIdleTimeout " +
379 karafTimeout )
Devin Limdc78e202017-06-09 18:30:07 -0700380 self.handle.expect( self.prompt )
suibin zhang116647a2016-05-06 16:30:09 -0700381 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800382 self.handle.expect( self.karafPrompt )
383 main.log.debug( self.handle.before )
suibin zhang116647a2016-05-06 16:30:09 -0700384 return main.TRUE
385 else:
386 # If failed, send ctrl+c to process and try again
387 main.log.info( "Starting CLI failed. Retrying..." )
388 self.handle.send( "\x03" )
389 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800390 i = self.handle.expect( [ self.karafPrompt, pexpect.TIMEOUT ],
suibin zhang116647a2016-05-06 16:30:09 -0700391 timeout=30 )
392 if i == 0:
393 main.log.info( self.name + " CLI Started " +
394 "successfully after retry attempt" )
395 if karafTimeout:
396 self.handle.sendline(
397 "config:property-set -p org.apache.karaf.shell\
398 sshIdleTimeout " +
399 karafTimeout )
Devin Limdc78e202017-06-09 18:30:07 -0700400 self.handle.expect( self.prompt )
suibin zhang116647a2016-05-06 16:30:09 -0700401 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800402 self.handle.expect( self.karafPrompt )
suibin zhang116647a2016-05-06 16:30:09 -0700403 return main.TRUE
404 else:
405 main.log.error( "Connection to CLI " +
406 self.name + " timeout" )
407 return main.FALSE
408
409 except TypeError:
410 main.log.exception( self.name + ": Object not as expected" )
411 return None
412 except pexpect.EOF:
413 main.log.error( self.name + ": EOF exception found" )
414 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700415 main.cleanAndExit()
suibin zhang116647a2016-05-06 16:30:09 -0700416 except Exception:
417 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700418 main.cleanAndExit()
suibin zhang116647a2016-05-06 16:30:09 -0700419
Pratik Parab3b2ab5a2017-02-14 13:15:14 -0800420 def log( self, cmdStr, level="", noExit=False ):
kelvin-onlab9f541032015-02-04 16:19:53 -0800421 """
422 log the commands in the onos CLI.
kelvin-onlab338f5512015-02-06 10:53:16 -0800423 returns main.TRUE on success
Jon Hallefbd9792015-03-05 16:11:36 -0800424 returns main.FALSE if Error occurred
YPZhangebf9eb52016-05-12 15:20:24 -0700425 if noExit is True, TestON will not exit, but clean up
kelvin-onlab338f5512015-02-06 10:53:16 -0800426 Available level: DEBUG, TRACE, INFO, WARN, ERROR
427 Level defaults to INFO
Pratik Parab3b2ab5a2017-02-14 13:15:14 -0800428 if cmdStr has spaces then put quotes in the passed string
kelvin-onlab9f541032015-02-04 16:19:53 -0800429 """
430 try:
kelvin-onlab338f5512015-02-06 10:53:16 -0800431 lvlStr = ""
432 if level:
433 lvlStr = "--level=" + level
434
kelvin-onlab338f5512015-02-06 10:53:16 -0800435 self.handle.sendline( "log:log " + lvlStr + " " + cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -0700436 self.handle.expect( "log:log" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800437 self.handle.expect( self.karafPrompt )
kelvin-onlabfb521662015-02-27 09:52:40 -0800438
kelvin-onlab9f541032015-02-04 16:19:53 -0800439 response = self.handle.before
440 if re.search( "Error", response ):
441 return main.FALSE
442 return main.TRUE
Jon Hall80daded2015-05-27 16:07:00 -0700443 except pexpect.TIMEOUT:
444 main.log.exception( self.name + ": TIMEOUT exception found" )
YPZhangebf9eb52016-05-12 15:20:24 -0700445 if noExit:
446 main.cleanup()
447 return None
448 else:
Devin Lim44075962017-08-11 10:56:37 -0700449 main.cleanAndExit()
kelvin-onlab9f541032015-02-04 16:19:53 -0800450 except pexpect.EOF:
451 main.log.error( self.name + ": EOF exception found" )
452 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700453 if noExit:
454 main.cleanup()
455 return None
456 else:
Devin Lim44075962017-08-11 10:56:37 -0700457 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800458 except Exception:
kelvin-onlabfb521662015-02-27 09:52:40 -0800459 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700460 if noExit:
461 main.cleanup()
462 return None
463 else:
Devin Lim44075962017-08-11 10:56:37 -0700464 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400465
Jon Hall0e240372018-05-02 11:21:57 -0700466 def clearBuffer( self, debug=False, timeout=10, noExit=False ):
kelvin8ec71442015-01-15 16:57:00 -0800467 """
Jon Hall0e240372018-05-02 11:21:57 -0700468 Test cli connection and clear any left over output in the buffer
469 Optional Arguments:
470 debug - Defaults to False. If True, will enable debug logging.
471 timeout - Defaults to 10. Amount of time in seconds for a command to return
472 before a timeout.
473 noExit - Defaults to False. If True, will not exit TestON in the event of a
kelvin8ec71442015-01-15 16:57:00 -0800474 """
andrewonlaba18f6bf2014-10-13 19:31:54 -0400475 try:
Jon Halla495f562016-05-16 18:03:26 -0700476 # Try to reconnect if disconnected from cli
477 self.handle.sendline( "" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800478 i = self.handle.expect( [ self.karafPrompt, self.prompt, pexpect.TIMEOUT ] )
Jon Hall0e240372018-05-02 11:21:57 -0700479 response = self.handle.before
Jon Halla495f562016-05-16 18:03:26 -0700480 if i == 1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700481 main.log.error( self.name + ": onos cli session closed. " )
Jon Halla495f562016-05-16 18:03:26 -0700482 if self.onosIp:
483 main.log.warn( "Trying to reconnect " + self.onosIp )
484 reconnectResult = self.startOnosCli( self.onosIp )
485 if reconnectResult:
486 main.log.info( self.name + ": onos cli session reconnected." )
487 else:
488 main.log.error( self.name + ": reconnection failed." )
YPZhang14a4aa92016-07-15 13:37:15 -0700489 if noExit:
490 return None
491 else:
Devin Lim44075962017-08-11 10:56:37 -0700492 main.cleanAndExit()
Jon Halla495f562016-05-16 18:03:26 -0700493 else:
Devin Lim44075962017-08-11 10:56:37 -0700494 main.cleanAndExit()
Jon Halla495f562016-05-16 18:03:26 -0700495 if i == 2:
Jon Hall7a6ebfd2017-03-13 10:58:58 -0700496 main.log.warn( "Timeout when testing cli responsiveness" )
497 main.log.debug( self.handle.before )
498 self.handle.send( "\x03" ) # Send ctrl-c to clear previous output
Jon Hall6c9e2da2018-11-06 12:01:23 -0800499 self.handle.expect( self.karafPrompt )
Jon Halla495f562016-05-16 18:03:26 -0700500
Jon Hall0e240372018-05-02 11:21:57 -0700501 response += self.handle.before
Jon Hall14a03b52016-05-11 12:07:30 -0700502 if debug:
Jon Hall0e240372018-05-02 11:21:57 -0700503 main.log.debug( self.name + ": Raw output from sending ''" )
504 main.log.debug( self.name + ": " + repr( response ) )
505 except pexpect.TIMEOUT:
506 main.log.error( self.name + ": ONOS timeout" )
507 main.log.debug( self.handle.before )
You Wang141b43b2018-06-26 16:50:18 -0700508 self.handle.send( "\x03" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800509 self.handle.expect( self.karafPrompt )
Jon Hall0e240372018-05-02 11:21:57 -0700510 return None
511 except pexpect.EOF:
512 main.log.error( self.name + ": EOF exception found" )
513 main.log.error( self.name + ": " + self.handle.before )
514 if noExit:
515 return None
516 else:
517 main.cleanAndExit()
518 except Exception:
519 main.log.exception( self.name + ": Uncaught exception!" )
520 if noExit:
521 return None
522 else:
523 main.cleanAndExit()
524
Jon Hall22e94ce2019-01-15 14:52:17 -0800525 def sendline( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False, relaxedRegex=True, expectJson=False ):
Jon Hall0e240372018-05-02 11:21:57 -0700526 """
527 A wrapper around pexpect's sendline/expect. Will return all the output from a given command
528
529 Required Arguments:
530 cmdStr - String to send to the pexpect session
531
532 Optional Arguments:
533 showResponse - Defaults to False. If True will log the response.
534 debug - Defaults to False. If True, will enable debug logging.
535 timeout - Defaults to 10. Amount of time in seconds for a command to return
536 before a timeout.
537 noExit - Defaults to False. If True, will not exit TestON in the event of a
538 closed channel, but instead return None
Jon Hall6c9e2da2018-11-06 12:01:23 -0800539 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 -0700540
541 Warning: There are no sanity checking to commands sent using this method.
542
543 """
544 try:
545 # Try to reconnect if disconnected from cli
546 self.clearBuffer( debug=debug, timeout=timeout, noExit=noExit )
547 if debug:
548 # NOTE: This adds an average of .4 seconds per call
Jon Hall14a03b52016-05-11 12:07:30 -0700549 logStr = "\"Sending CLI command: '" + cmdStr + "'\""
Jon Halle0f0b342017-04-18 11:43:47 -0700550 self.log( logStr, noExit=noExit )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800551 self.handle.sendline( cmdStr )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800552 self.handle.expect( self.karafPrompt, timeout )
Jon Hall63604932015-02-26 17:09:50 -0800553 response = self.handle.before
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000554 main.log.info( "Command '" + str( cmdStr ) + "' sent to "
Jon Hallc6793552016-01-19 14:18:37 -0800555 + self.name + "." )
Jon Hallc6358dd2015-04-10 12:44:28 -0700556 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700557 main.log.debug( self.name + ": Raw output" )
558 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700559
Jon Hall6c9e2da2018-11-06 12:01:23 -0800560 # Remove control codes from karaf 4.2.1
Jon Hallcf31d0f2018-12-13 11:18:48 -0800561 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 -0800562 response = karafEscape.sub( '', response )
563 if debug:
564 main.log.debug( self.name + ": karafEscape output" )
565 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700566 # Remove ANSI color control strings from output
Jon Hall6c9e2da2018-11-06 12:01:23 -0800567 ansiEscape = re.compile( r'((\x9b|\x1b\[)[0-?]*[ -/]*[@-~])' )
Jon Hall63604932015-02-26 17:09:50 -0800568 response = ansiEscape.sub( '', response )
Jon Hallc6358dd2015-04-10 12:44:28 -0700569 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700570 main.log.debug( self.name + ": ansiEscape output" )
571 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700572
Jon Hall6c9e2da2018-11-06 12:01:23 -0800573 # Remove ANSI color control strings from output
Jon Hallcf31d0f2018-12-13 11:18:48 -0800574 # NOTE: karaf is sometimes adding a single character then two
575 # backspaces and sometimes adding 2 characters with 2 backspaces??
Jon Hall6c9e2da2018-11-06 12:01:23 -0800576 backspaceEscape = re.compile( r'((..\x08\x08)|(.|\s)\x08)' )
577 response = backspaceEscape.sub( '', response )
578 if debug:
579 main.log.debug( self.name + ": backspaceEscape output" )
580 main.log.debug( self.name + ": " + repr( response ) )
581
kelvin-onlabfb521662015-02-27 09:52:40 -0800582 # Remove extra return chars that get added
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000583 response = re.sub( r"\s\r", "", response )
Jon Hallc6358dd2015-04-10 12:44:28 -0700584 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700585 main.log.debug( self.name + ": Removed extra returns " +
586 "from output" )
587 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700588
589 # Strip excess whitespace
Jon Hall63604932015-02-26 17:09:50 -0800590 response = response.strip()
Jon Hallc6358dd2015-04-10 12:44:28 -0700591 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700592 main.log.debug( self.name + ": parsed and stripped output" )
593 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700594
Jon Hall63604932015-02-26 17:09:50 -0800595 # parse for just the output, remove the cmd from response
Jon Hallce0d70b2018-12-11 11:01:32 -0800596 cmdPattern = cmdStr.strip()
597 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
598 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800599 if relaxedRegex:
Jon Hallce0d70b2018-12-11 11:01:32 -0800600 cmdPattern = cmdPattern.split( '|' )[ -1 ].strip()
601 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
602 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800603 # This was added because karaf 4.2 is stripping some characters from the command echo
Jon Hallce0d70b2018-12-11 11:01:32 -0800604 output = response.split( cmdPattern, 1 )
Jon Hall22e94ce2019-01-15 14:52:17 -0800605 if expectJson:
606 main.log.warn( "Relaxed Regex: Searching for a json string amongst the output" )
607 jsonPattern = r'\{.*\}'
608 match = re.search( jsonPattern, output[ 0 ] )
609 if match:
610 output = [ '' , match.group( 0 ) ] # We expect a list with the second element to be the output
Jon Hall39e3ffe2018-12-05 11:40:29 -0800611 if len( output ) < 2:
612 main.log.warn( "Relaxing regex match to last 5 characters of the sent command" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800613 cmdPattern = cmdPattern[ -5: ]
614 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
615 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
616 output = response.split( cmdPattern, 1 )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800617 else:
Jon Hallce0d70b2018-12-11 11:01:32 -0800618 output = response.split( cmdPattern, 1 )
619 if len( output ) < 2: # TODO: Should we do this without the relaxedRegex flag?
Jon Hall8c9dd1c2018-11-14 15:40:39 -0800620 main.log.warn( "Relaxing regex match to last 5 characters of the sent command" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800621 output = response.split( cmdPattern[ -5: ], 1 )
Jon Hall0e240372018-05-02 11:21:57 -0700622 if output:
623 if debug:
624 main.log.debug( self.name + ": split output" )
625 for r in output:
626 main.log.debug( self.name + ": " + repr( r ) )
Jon Hallce0d70b2018-12-11 11:01:32 -0800627 if len( output ) == 1:
628 main.log.error( "Could not remove sent command echo from output" )
629 return output
Jon Hall0e240372018-05-02 11:21:57 -0700630 output = output[ 1 ].strip()
GlennRC85870432015-11-23 11:45:51 -0800631 if showResponse:
GlennRCed771242016-01-13 17:02:47 -0800632 main.log.info( "Response from ONOS: {}".format( output ) )
Jon Hall0e240372018-05-02 11:21:57 -0700633 self.clearBuffer( debug=debug, timeout=timeout, noExit=noExit )
GlennRC85870432015-11-23 11:45:51 -0800634 return output
GlennRCed771242016-01-13 17:02:47 -0800635 except pexpect.TIMEOUT:
Jon Hall0e240372018-05-02 11:21:57 -0700636 main.log.error( self.name + ": ONOS timeout" )
GlennRCed771242016-01-13 17:02:47 -0800637 if debug:
638 main.log.debug( self.handle.before )
You Wang141b43b2018-06-26 16:50:18 -0700639 self.handle.send( "\x03" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800640 self.handle.expect( self.karafPrompt )
GlennRCed771242016-01-13 17:02:47 -0800641 return None
Jon Hallc6358dd2015-04-10 12:44:28 -0700642 except IndexError:
643 main.log.exception( self.name + ": Object not as expected" )
Jon Halla495f562016-05-16 18:03:26 -0700644 main.log.debug( "response: {}".format( repr( response ) ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700645 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800646 except TypeError:
647 main.log.exception( self.name + ": Object not as expected" )
648 return None
andrewonlaba18f6bf2014-10-13 19:31:54 -0400649 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800650 main.log.error( self.name + ": EOF exception found" )
651 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700652 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700653 return None
654 else:
Devin Lim44075962017-08-11 10:56:37 -0700655 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800656 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800657 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700658 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700659 return None
660 else:
Devin Lim44075962017-08-11 10:56:37 -0700661 main.cleanAndExit()
andrewonlaba18f6bf2014-10-13 19:31:54 -0400662
Jon Halld5a94fb2018-11-13 14:32:23 -0800663 def lineCount( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False, relaxedRegex=True ):
664 """
665 A wrapper around sendline(). Will return the number of lines returned or None on error
666
667 Required Arguments:
668 cmdStr - String to send to the pexpect session
669
670 Optional Arguments:
671 showResponse - Defaults to False. If True will log the response.
672 debug - Defaults to False. If True, will enable debug logging.
673 timeout - Defaults to 10. Amount of time in seconds for a command to return
674 before a timeout.
675 noExit - Defaults to False. If True, will not exit TestON in the event of a
676 closed channel, but instead return None
677 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.
678
679 Warning: There are no sanity checking to commands sent using this method.
680
681 """
682 try:
683 numLines = self.sendline( cmdStr, showResponse, debug, timeout, noExit, relaxedRegex )
Jon Hall8c9dd1c2018-11-14 15:40:39 -0800684 parsed = re.search( "(\d+)\s+(\d+)", numLines )
685 if not parsed:
686 main.log.error( "Warning, output of karaf's wc may have changed" )
687 return None
688 return parsed.group( 1 )
Jon Halld5a94fb2018-11-13 14:32:23 -0800689 except IndexError:
690 main.log.exception( self.name + ": Object not as expected" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800691 main.log.debug( "response: {}".format( repr( numLines ) ) )
Jon Halld5a94fb2018-11-13 14:32:23 -0800692 return None
693 except TypeError:
694 main.log.exception( self.name + ": Object not as expected" )
695 return None
696 except Exception:
697 main.log.exception( self.name + ": Uncaught exception!" )
698 if noExit:
699 return None
700 else:
701 main.cleanAndExit()
702
kelvin8ec71442015-01-15 16:57:00 -0800703 # IMPORTANT NOTE:
704 # For all cli commands, naming convention should match
kelvin-onlabd3b64892015-01-20 13:26:24 -0800705 # the cli command changing 'a:b' with 'aB'.
706 # Ex ) onos:topology > onosTopology
707 # onos:links > onosLinks
708 # feature:list > featureList
Jon Halle3f39ff2015-01-13 11:50:53 -0800709
kelvin-onlabd3b64892015-01-20 13:26:24 -0800710 def addNode( self, nodeId, ONOSIp, tcpPort="" ):
kelvin8ec71442015-01-15 16:57:00 -0800711 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400712 Adds a new cluster node by ID and address information.
713 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800714 * nodeId
715 * ONOSIp
andrewonlabc2d05aa2014-10-13 16:51:10 -0400716 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800717 * tcpPort
kelvin8ec71442015-01-15 16:57:00 -0800718 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400719 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800720 cmdStr = "add-node " + str( nodeId ) + " " +\
721 str( ONOSIp ) + " " + str( tcpPort )
722 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700723 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800724 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -0800725 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700726 main.log.error( self.name + ": Error in adding node" )
kelvin8ec71442015-01-15 16:57:00 -0800727 main.log.error( handle )
Jon Halle3f39ff2015-01-13 11:50:53 -0800728 return main.FALSE
andrewonlabc2d05aa2014-10-13 16:51:10 -0400729 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800730 main.log.info( "Node " + str( ONOSIp ) + " added" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400731 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800732 except AssertionError:
733 main.log.exception( "" )
734 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800735 except TypeError:
736 main.log.exception( self.name + ": Object not as expected" )
737 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400738 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800739 main.log.error( self.name + ": EOF exception found" )
740 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700741 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800742 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800743 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700744 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400745
kelvin-onlabd3b64892015-01-20 13:26:24 -0800746 def removeNode( self, nodeId ):
kelvin8ec71442015-01-15 16:57:00 -0800747 """
andrewonlab86dc3082014-10-13 18:18:38 -0400748 Removes a cluster by ID
749 Issues command: 'remove-node [<node-id>]'
750 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800751 * nodeId
kelvin8ec71442015-01-15 16:57:00 -0800752 """
andrewonlab86dc3082014-10-13 18:18:38 -0400753 try:
andrewonlab86dc3082014-10-13 18:18:38 -0400754
kelvin-onlabd3b64892015-01-20 13:26:24 -0800755 cmdStr = "remove-node " + str( nodeId )
Jon Hall08f61bc2015-04-13 16:00:30 -0700756 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700757 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800758 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700759 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700760 main.log.error( self.name + ": Error in removing node" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700761 main.log.error( handle )
762 return main.FALSE
763 else:
764 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800765 except AssertionError:
766 main.log.exception( "" )
767 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800768 except TypeError:
769 main.log.exception( self.name + ": Object not as expected" )
770 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400771 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800772 main.log.error( self.name + ": EOF exception found" )
773 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700774 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800775 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800776 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700777 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400778
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700779 def nodes( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800780 """
andrewonlab7c211572014-10-15 16:45:20 -0400781 List the nodes currently visible
782 Issues command: 'nodes'
Jon Hall61282e32015-03-19 11:34:11 -0700783 Optional argument:
784 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800785 """
andrewonlab7c211572014-10-15 16:45:20 -0400786 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700787 cmdStr = "nodes"
Jon Hall61282e32015-03-19 11:34:11 -0700788 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700789 cmdStr += " -j"
790 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700791 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800792 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -0700793 return output
Jon Hallc6793552016-01-19 14:18:37 -0800794 except AssertionError:
795 main.log.exception( "" )
796 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800797 except TypeError:
798 main.log.exception( self.name + ": Object not as expected" )
799 return None
andrewonlab7c211572014-10-15 16:45:20 -0400800 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800801 main.log.error( self.name + ": EOF exception found" )
802 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700803 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800804 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800805 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700806 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400807
kelvin8ec71442015-01-15 16:57:00 -0800808 def topology( self ):
809 """
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700810 Definition:
Jon Hall390696c2015-05-05 17:13:41 -0700811 Returns the output of topology command.
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700812 Return:
813 topology = current ONOS topology
kelvin8ec71442015-01-15 16:57:00 -0800814 """
andrewonlab95ce8322014-10-13 14:12:04 -0400815 try:
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700816 cmdStr = "topology -j"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800817 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800818 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800819 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700820 main.log.info( cmdStr + " returned: " + str( handle ) )
andrewonlab95ce8322014-10-13 14:12:04 -0400821 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800822 except AssertionError:
823 main.log.exception( "" )
Jon Halld4d4b372015-01-28 16:02:41 -0800824 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800825 except TypeError:
826 main.log.exception( self.name + ": Object not as expected" )
827 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400828 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800829 main.log.error( self.name + ": EOF exception found" )
830 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700831 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800832 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800833 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700834 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -0800835
jenkins7ead5a82015-03-13 10:28:21 -0700836 def deviceRemove( self, deviceId ):
837 """
838 Removes particular device from storage
839
840 TODO: refactor this function
841 """
842 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700843 cmdStr = "device-remove " + str( deviceId )
844 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800845 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800846 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700847 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700848 main.log.error( self.name + ": Error in removing device" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700849 main.log.error( handle )
850 return main.FALSE
851 else:
852 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800853 except AssertionError:
854 main.log.exception( "" )
855 return None
jenkins7ead5a82015-03-13 10:28:21 -0700856 except TypeError:
857 main.log.exception( self.name + ": Object not as expected" )
858 return None
859 except pexpect.EOF:
860 main.log.error( self.name + ": EOF exception found" )
861 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700862 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700863 except Exception:
864 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700865 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700866
You Wang3b9689a2018-08-30 12:24:00 -0700867 def devices( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -0800868 """
Jon Hall7b02d952014-10-17 20:14:54 -0400869 Lists all infrastructure devices or switches
andrewonlab86dc3082014-10-13 18:18:38 -0400870 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800871 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800872 """
andrewonlab86dc3082014-10-13 18:18:38 -0400873 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700874 cmdStr = "devices"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800875 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700876 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -0700877 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -0800878 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800879 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700880 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800881 except AssertionError:
882 main.log.exception( "" )
883 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800884 except TypeError:
885 main.log.exception( self.name + ": Object not as expected" )
886 return None
andrewonlab7c211572014-10-15 16:45:20 -0400887 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800888 main.log.error( self.name + ": EOF exception found" )
889 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700890 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800891 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800892 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700893 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400894
kelvin-onlabd3b64892015-01-20 13:26:24 -0800895 def balanceMasters( self ):
kelvin8ec71442015-01-15 16:57:00 -0800896 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800897 This balances the devices across all controllers
898 by issuing command: 'onos> onos:balance-masters'
899 If required this could be extended to return devices balanced output.
kelvin8ec71442015-01-15 16:57:00 -0800900 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800901 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800902 cmdStr = "onos:balance-masters"
Jon Hallc6358dd2015-04-10 12:44:28 -0700903 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800904 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800905 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700906 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700907 main.log.error( self.name + ": Error in balancing masters" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700908 main.log.error( handle )
909 return main.FALSE
910 else:
911 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800912 except AssertionError:
913 main.log.exception( "" )
914 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800915 except TypeError:
916 main.log.exception( self.name + ": Object not as expected" )
917 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800918 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800919 main.log.error( self.name + ": EOF exception found" )
920 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700921 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800922 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800923 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700924 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800925
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000926 def checkMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700927 """
928 Returns the output of the masters command.
929 Optional argument:
930 * jsonFormat - boolean indicating if you want output in json
931 """
932 try:
933 cmdStr = "onos:masters"
934 if jsonFormat:
935 cmdStr += " -j"
936 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700937 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800938 assert "Command not found:" not in output, output
acsmars24950022015-07-30 18:00:43 -0700939 return output
Jon Hallc6793552016-01-19 14:18:37 -0800940 except AssertionError:
941 main.log.exception( "" )
942 return None
acsmars24950022015-07-30 18:00:43 -0700943 except TypeError:
944 main.log.exception( self.name + ": Object not as expected" )
945 return None
946 except pexpect.EOF:
947 main.log.error( self.name + ": EOF exception found" )
948 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700949 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700950 except Exception:
951 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700952 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700953
Jon Hallc6793552016-01-19 14:18:37 -0800954 def checkBalanceMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700955 """
956 Uses the master command to check that the devices' leadership
957 is evenly divided
958
959 Dependencies: checkMasters() and summary()
960
Jon Hall6509dbf2016-06-21 17:01:17 -0700961 Returns main.TRUE if the devices are balanced
962 Returns main.FALSE if the devices are unbalanced
acsmars24950022015-07-30 18:00:43 -0700963 Exits on Exception
964 Returns None on TypeError
965 """
966 try:
Jon Hallc6793552016-01-19 14:18:37 -0800967 summaryOutput = self.summary()
968 totalDevices = json.loads( summaryOutput )[ "devices" ]
969 except ( TypeError, ValueError ):
970 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summaryOutput ) )
971 return None
972 try:
acsmars24950022015-07-30 18:00:43 -0700973 totalOwnedDevices = 0
Jon Hallc6793552016-01-19 14:18:37 -0800974 mastersOutput = self.checkMasters()
975 masters = json.loads( mastersOutput )
acsmars24950022015-07-30 18:00:43 -0700976 first = masters[ 0 ][ "size" ]
977 for master in masters:
978 totalOwnedDevices += master[ "size" ]
979 if master[ "size" ] > first + 1 or master[ "size" ] < first - 1:
980 main.log.error( "Mastership not balanced" )
981 main.log.info( "\n" + self.checkMasters( False ) )
982 return main.FALSE
Jon Halle0f0b342017-04-18 11:43:47 -0700983 main.log.info( "Mastership balanced between " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700984 str( len( masters ) ) + " masters" )
acsmars24950022015-07-30 18:00:43 -0700985 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800986 except ( TypeError, ValueError ):
987 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, mastersOutput ) )
acsmars24950022015-07-30 18:00:43 -0700988 return None
989 except pexpect.EOF:
990 main.log.error( self.name + ": EOF exception found" )
991 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700992 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700993 except Exception:
994 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700995 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700996
YPZhangfebf7302016-05-24 16:45:56 -0700997 def links( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -0800998 """
Jon Halle8217482014-10-17 13:49:14 -0400999 Lists all core links
1000 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001001 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001002 """
Jon Halle8217482014-10-17 13:49:14 -04001003 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001004 cmdStr = "links"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001005 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001006 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07001007 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001008 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001009 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001010 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001011 except AssertionError:
1012 main.log.exception( "" )
1013 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001014 except TypeError:
1015 main.log.exception( self.name + ": Object not as expected" )
1016 return None
Jon Halle8217482014-10-17 13:49:14 -04001017 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001018 main.log.error( self.name + ": EOF exception found" )
1019 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001020 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001021 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001022 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001023 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001024
You Wang3b9689a2018-08-30 12:24:00 -07001025 def ports( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -08001026 """
Jon Halle8217482014-10-17 13:49:14 -04001027 Lists all ports
1028 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001029 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001030 """
Jon Halle8217482014-10-17 13:49:14 -04001031 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001032 cmdStr = "ports"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001033 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001034 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -07001035 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001036 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001037 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001038 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001039 except AssertionError:
1040 main.log.exception( "" )
1041 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001042 except TypeError:
1043 main.log.exception( self.name + ": Object not as expected" )
1044 return None
Jon Halle8217482014-10-17 13:49:14 -04001045 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001046 main.log.error( self.name + ": EOF exception found" )
1047 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001048 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001049 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001050 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001051 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001052
kelvin-onlabd3b64892015-01-20 13:26:24 -08001053 def roles( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001054 """
Jon Hall983a1702014-10-28 18:44:22 -04001055 Lists all devices and the controllers with roles assigned to them
1056 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001057 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001058 """
andrewonlab7c211572014-10-15 16:45:20 -04001059 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001060 cmdStr = "roles"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001061 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001062 cmdStr += " -j"
1063 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001064 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001065 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001066 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001067 except AssertionError:
1068 main.log.exception( "" )
1069 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001070 except TypeError:
1071 main.log.exception( self.name + ": Object not as expected" )
1072 return None
Jon Hall983a1702014-10-28 18:44:22 -04001073 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001074 main.log.error( self.name + ": EOF exception found" )
1075 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001076 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001077 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001078 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001079 main.cleanAndExit()
Jon Hall983a1702014-10-28 18:44:22 -04001080
kelvin-onlabd3b64892015-01-20 13:26:24 -08001081 def getRole( self, deviceId ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001082 """
Jon Halle3f39ff2015-01-13 11:50:53 -08001083 Given the a string containing the json representation of the "roles"
1084 cli command and a partial or whole device id, returns a json object
1085 containing the roles output for the first device whose id contains
1086 "device_id"
Jon Hall983a1702014-10-28 18:44:22 -04001087
1088 Returns:
Jon Halle3f39ff2015-01-13 11:50:53 -08001089 A dict of the role assignments for the given device or
1090 None if no match
kelvin8ec71442015-01-15 16:57:00 -08001091 """
Jon Hall983a1702014-10-28 18:44:22 -04001092 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001093 if deviceId is None:
Jon Hall983a1702014-10-28 18:44:22 -04001094 return None
1095 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001096 rawRoles = self.roles()
1097 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001098 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001099 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001100 # print device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001101 if str( deviceId ) in device[ 'id' ]:
Jon Hall983a1702014-10-28 18:44:22 -04001102 return device
1103 return None
Jon Hallc6793552016-01-19 14:18:37 -08001104 except ( TypeError, ValueError ):
1105 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001106 return None
andrewonlab86dc3082014-10-13 18:18:38 -04001107 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001108 main.log.error( self.name + ": EOF exception found" )
1109 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001110 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001111 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001112 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001113 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001114
kelvin-onlabd3b64892015-01-20 13:26:24 -08001115 def rolesNotNull( self ):
kelvin8ec71442015-01-15 16:57:00 -08001116 """
Jon Hall94fd0472014-12-08 11:52:42 -08001117 Iterates through each device and checks if there is a master assigned
1118 Returns: main.TRUE if each device has a master
1119 main.FALSE any device has no master
kelvin8ec71442015-01-15 16:57:00 -08001120 """
Jon Hall94fd0472014-12-08 11:52:42 -08001121 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001122 rawRoles = self.roles()
1123 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001124 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001125 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001126 # print device
1127 if device[ 'master' ] == "none":
1128 main.log.warn( "Device has no master: " + str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08001129 return main.FALSE
1130 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08001131 except ( TypeError, ValueError ):
1132 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001133 return None
Jon Hall94fd0472014-12-08 11:52:42 -08001134 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001135 main.log.error( self.name + ": EOF exception found" )
1136 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001137 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001138 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001139 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001140 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001141
kelvin-onlabd3b64892015-01-20 13:26:24 -08001142 def paths( self, srcId, dstId ):
kelvin8ec71442015-01-15 16:57:00 -08001143 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001144 Returns string of paths, and the cost.
1145 Issues command: onos:paths <src> <dst>
kelvin8ec71442015-01-15 16:57:00 -08001146 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001147 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001148 cmdStr = "onos:paths " + str( srcId ) + " " + str( dstId )
1149 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001150 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001151 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08001152 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001153 main.log.error( self.name + ": Error in getting paths" )
kelvin8ec71442015-01-15 16:57:00 -08001154 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001155 else:
kelvin8ec71442015-01-15 16:57:00 -08001156 path = handle.split( ";" )[ 0 ]
1157 cost = handle.split( ";" )[ 1 ]
1158 return ( path, cost )
Jon Hallc6793552016-01-19 14:18:37 -08001159 except AssertionError:
1160 main.log.exception( "" )
1161 return ( handle, "Error" )
Jon Halld4d4b372015-01-28 16:02:41 -08001162 except TypeError:
1163 main.log.exception( self.name + ": Object not as expected" )
1164 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001165 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001166 main.log.error( self.name + ": EOF exception found" )
1167 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001168 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001169 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001170 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001171 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -08001172
kelvin-onlabd3b64892015-01-20 13:26:24 -08001173 def hosts( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001174 """
Jon Hallffb386d2014-11-21 13:43:38 -08001175 Lists all discovered hosts
Jon Hall42db6dc2014-10-24 19:03:48 -04001176 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001177 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001178 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001179 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001180 cmdStr = "hosts"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001181 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001182 cmdStr += " -j"
1183 handle = self.sendline( cmdStr )
Jeremyd9e4eb12016-04-13 12:09:06 -07001184 if handle:
1185 assert "Command not found:" not in handle, handle
Jon Hallbaf53162015-12-17 17:04:34 -08001186 # TODO: Maybe make this less hardcoded
1187 # ConsistentMap Exceptions
1188 assert "org.onosproject.store.service" not in handle
1189 # Node not leader
1190 assert "java.lang.IllegalStateException" not in handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001191 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001192 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07001193 main.log.exception( self.name + ": Error in processing '" + cmdStr + "' " +
Jeremy Songster6949cea2016-04-19 18:13:18 -07001194 "command: " + str( handle ) )
Jon Hallc6793552016-01-19 14:18:37 -08001195 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001196 except TypeError:
1197 main.log.exception( self.name + ": Object not as expected" )
1198 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001199 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001200 main.log.error( self.name + ": EOF exception found" )
1201 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001202 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001203 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001204 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001205 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001206
kelvin-onlabd3b64892015-01-20 13:26:24 -08001207 def getHost( self, mac ):
kelvin8ec71442015-01-15 16:57:00 -08001208 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001209 Return the first host from the hosts api whose 'id' contains 'mac'
Jon Halle3f39ff2015-01-13 11:50:53 -08001210
Jon Hallefbd9792015-03-05 16:11:36 -08001211 Note: mac must be a colon separated mac address, but could be a
Jon Halle3f39ff2015-01-13 11:50:53 -08001212 partial mac address
1213
Jon Hall42db6dc2014-10-24 19:03:48 -04001214 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08001215 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001216 try:
kelvin8ec71442015-01-15 16:57:00 -08001217 if mac is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04001218 return None
1219 else:
1220 mac = mac
kelvin-onlabd3b64892015-01-20 13:26:24 -08001221 rawHosts = self.hosts()
1222 hostsJson = json.loads( rawHosts )
kelvin8ec71442015-01-15 16:57:00 -08001223 # search json for the host with mac then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001224 for host in hostsJson:
kelvin8ec71442015-01-15 16:57:00 -08001225 # print "%s in %s?" % ( mac, host[ 'id' ] )
Jon Halld4d4b372015-01-28 16:02:41 -08001226 if not host:
1227 pass
1228 elif mac in host[ 'id' ]:
Jon Hall42db6dc2014-10-24 19:03:48 -04001229 return host
1230 return None
Jon Hallc6793552016-01-19 14:18:37 -08001231 except ( TypeError, ValueError ):
1232 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawHosts ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001233 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001234 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001235 main.log.error( self.name + ": EOF exception found" )
1236 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001237 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001238 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001239 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001240 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001241
kelvin-onlabd3b64892015-01-20 13:26:24 -08001242 def getHostsId( self, hostList ):
kelvin8ec71442015-01-15 16:57:00 -08001243 """
1244 Obtain list of hosts
andrewonlab3f0a4af2014-10-17 12:25:14 -04001245 Issues command: 'onos> hosts'
kelvin8ec71442015-01-15 16:57:00 -08001246
andrewonlab3f0a4af2014-10-17 12:25:14 -04001247 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001248 * hostList: List of hosts obtained by Mininet
andrewonlab3f0a4af2014-10-17 12:25:14 -04001249 IMPORTANT:
1250 This function assumes that you started your
kelvin8ec71442015-01-15 16:57:00 -08001251 topology with the option '--mac'.
andrewonlab3f0a4af2014-10-17 12:25:14 -04001252 Furthermore, it assumes that value of VLAN is '-1'
1253 Description:
kelvin8ec71442015-01-15 16:57:00 -08001254 Converts mininet hosts ( h1, h2, h3... ) into
1255 ONOS format ( 00:00:00:00:00:01/-1 , ... )
1256 """
andrewonlab3f0a4af2014-10-17 12:25:14 -04001257 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001258 onosHostList = []
andrewonlab3f0a4af2014-10-17 12:25:14 -04001259
kelvin-onlabd3b64892015-01-20 13:26:24 -08001260 for host in hostList:
kelvin8ec71442015-01-15 16:57:00 -08001261 host = host.replace( "h", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001262 hostHex = hex( int( host ) ).zfill( 12 )
1263 hostHex = str( hostHex ).replace( 'x', '0' )
1264 i = iter( str( hostHex ) )
1265 hostHex = ":".join( a + b for a, b in zip( i, i ) )
1266 hostHex = hostHex + "/-1"
1267 onosHostList.append( hostHex )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001268
kelvin-onlabd3b64892015-01-20 13:26:24 -08001269 return onosHostList
andrewonlab3f0a4af2014-10-17 12:25:14 -04001270
Jon Halld4d4b372015-01-28 16:02:41 -08001271 except TypeError:
1272 main.log.exception( self.name + ": Object not as expected" )
1273 return None
andrewonlab3f0a4af2014-10-17 12:25:14 -04001274 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001275 main.log.error( self.name + ": EOF exception found" )
1276 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001277 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001278 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001279 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001280 main.cleanAndExit()
andrewonlab3e15ead2014-10-15 14:21:34 -04001281
You Wangbc898b82018-05-03 16:22:34 -07001282 def verifyHostLocation( self, hostIp, location ):
1283 """
1284 Description:
1285 Verify the host given is discovered in all locations expected
1286 Required:
1287 hostIp: IP address of the host
1288 location: expected location(s) of the given host. ex. "of:0000000000000005/8"
1289 Could be a string or list
1290 Returns:
1291 main.TRUE if host is discovered on all locations provided
1292 main.FALSE otherwise
1293 """
1294 import json
1295 locations = [ location ] if isinstance( location, str ) else location
1296 assert isinstance( locations, list ), "Wrong type of location: {}".format( type( location ) )
1297 try:
1298 hosts = self.hosts()
1299 hosts = json.loads( hosts )
1300 targetHost = None
1301 for host in hosts:
1302 if hostIp in host[ "ipAddresses" ]:
1303 targetHost = host
You Wangfd80ab42018-05-10 17:21:53 -07001304 assert targetHost, "Not able to find host with IP {}".format( hostIp )
You Wangbc898b82018-05-03 16:22:34 -07001305 result = main.TRUE
1306 locationsDiscovered = [ loc[ "elementId" ] + "/" + loc[ "port" ] for loc in targetHost[ "locations" ] ]
1307 for loc in locations:
1308 discovered = False
1309 for locDiscovered in locationsDiscovered:
You Wang547893e2018-05-08 13:34:59 -07001310 locToMatch = locDiscovered if "/" in loc else locDiscovered.split( "/" )[0]
1311 if loc == locToMatch:
You Wangbc898b82018-05-03 16:22:34 -07001312 main.log.debug( "Host {} discovered with location {}".format( hostIp, loc ) )
You Wang547893e2018-05-08 13:34:59 -07001313 discovered = True
You Wangbc898b82018-05-03 16:22:34 -07001314 break
1315 if discovered:
1316 locationsDiscovered.remove( locDiscovered )
1317 else:
1318 main.log.warn( "Host {} not discovered with location {}".format( hostIp, loc ) )
1319 result = main.FALSE
1320 if locationsDiscovered:
1321 main.log.warn( "Host {} is also discovered with location {}".format( hostIp, locationsDiscovered ) )
1322 result = main.FALSE
1323 return result
1324 except KeyError:
1325 main.log.exception( self.name + ": host data not as expected: " + hosts )
1326 return None
1327 except pexpect.EOF:
1328 main.log.error( self.name + ": EOF exception found" )
1329 main.log.error( self.name + ": " + self.handle.before )
1330 main.cleanAndExit()
1331 except Exception:
1332 main.log.exception( self.name + ": Uncaught exception" )
1333 return None
1334
You Wang53dba1e2018-02-02 17:45:44 -08001335 def verifyHostIp( self, hostList=[], prefix="" ):
1336 """
1337 Description:
1338 Verify that all hosts have IP address assigned to them
1339 Optional:
1340 hostList: If specified, verifications only happen to the hosts
1341 in hostList
1342 prefix: at least one of the ip address assigned to the host
1343 needs to have the specified prefix
1344 Returns:
1345 main.TRUE if all hosts have specific IP address assigned;
1346 main.FALSE otherwise
1347 """
1348 import json
1349 try:
1350 hosts = self.hosts()
1351 hosts = json.loads( hosts )
1352 if not hostList:
1353 hostList = [ host[ "id" ] for host in hosts ]
1354 for host in hosts:
1355 hostId = host[ "id" ]
1356 if hostId not in hostList:
1357 continue
1358 ipList = host[ "ipAddresses" ]
1359 main.log.debug( self.name + ": IP list on host " + str( hostId ) + ": " + str( ipList ) )
1360 if not ipList:
1361 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostId ) )
1362 else:
1363 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
1364 main.log.warn( self.name + ": None of the IPs on host " + str( hostId ) + " has prefix " + str( prefix ) )
1365 else:
1366 main.log.debug( self.name + ": Found matching IP on host " + str( hostId ) )
1367 hostList.remove( hostId )
1368 if hostList:
1369 main.log.warn( self.name + ": failed to verify IP on following hosts: " + str( hostList) )
1370 return main.FALSE
1371 else:
1372 return main.TRUE
1373 except KeyError:
1374 main.log.exception( self.name + ": host data not as expected: " + hosts )
1375 return None
1376 except pexpect.EOF:
1377 main.log.error( self.name + ": EOF exception found" )
1378 main.log.error( self.name + ": " + self.handle.before )
1379 main.cleanAndExit()
1380 except Exception:
1381 main.log.exception( self.name + ": Uncaught exception" )
1382 return None
1383
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001384 def addHostIntent( self, hostIdOne, hostIdTwo, vlanId="", setVlan="", encap="", bandwidth="" ):
kelvin8ec71442015-01-15 16:57:00 -08001385 """
andrewonlabe6745342014-10-17 14:29:13 -04001386 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001387 * hostIdOne: ONOS host id for host1
1388 * hostIdTwo: ONOS host id for host2
Jeremy Songster832f9e92016-05-05 14:30:49 -07001389 Optional:
1390 * vlanId: specify a VLAN id for the intent
Jeremy Songsterff553672016-05-12 17:06:23 -07001391 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001392 * encap: specify an encapsulation type
andrewonlabe6745342014-10-17 14:29:13 -04001393 Description:
Jon Hallefbd9792015-03-05 16:11:36 -08001394 Adds a host-to-host intent ( bidirectional ) by
Jon Hallb1290e82014-11-18 16:17:48 -05001395 specifying the two hosts.
kelvin-onlabfb521662015-02-27 09:52:40 -08001396 Returns:
1397 A string of the intent id or None on Error
kelvin8ec71442015-01-15 16:57:00 -08001398 """
andrewonlabe6745342014-10-17 14:29:13 -04001399 try:
Jeremy Songster832f9e92016-05-05 14:30:49 -07001400 cmdStr = "add-host-intent "
1401 if vlanId:
1402 cmdStr += "-v " + str( vlanId ) + " "
Jeremy Songsterff553672016-05-12 17:06:23 -07001403 if setVlan:
1404 cmdStr += "--setVlan " + str( vlanId ) + " "
Jeremy Songsterc032f162016-08-04 17:14:49 -07001405 if encap:
1406 cmdStr += "--encapsulation " + str( encap ) + " "
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001407 if bandwidth:
1408 cmdStr += "-b " + str( bandwidth ) + " "
Jeremy Songster832f9e92016-05-05 14:30:49 -07001409 cmdStr += str( hostIdOne ) + " " + str( hostIdTwo )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001410 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001411 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001412 assert "Command not found:" not in handle, handle
Hari Krishnaac4e1782015-01-26 12:09:12 -08001413 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001414 main.log.error( self.name + ": Error in adding Host intent" )
Jon Hall61282e32015-03-19 11:34:11 -07001415 main.log.debug( "Response from ONOS was: " + repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001416 return None
Hari Krishnaac4e1782015-01-26 12:09:12 -08001417 else:
1418 main.log.info( "Host intent installed between " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001419 str( hostIdOne ) + " and " + str( hostIdTwo ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001420 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001421 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001422 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001423 else:
1424 main.log.error( "Error, intent ID not found" )
Jon Hall61282e32015-03-19 11:34:11 -07001425 main.log.debug( "Response from ONOS was: " +
1426 repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001427 return None
Jon Hallc6793552016-01-19 14:18:37 -08001428 except AssertionError:
1429 main.log.exception( "" )
1430 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001431 except TypeError:
1432 main.log.exception( self.name + ": Object not as expected" )
1433 return None
andrewonlabe6745342014-10-17 14:29:13 -04001434 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001435 main.log.error( self.name + ": EOF exception found" )
1436 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001437 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001438 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001439 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001440 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04001441
kelvin-onlabd3b64892015-01-20 13:26:24 -08001442 def addOpticalIntent( self, ingressDevice, egressDevice ):
kelvin8ec71442015-01-15 16:57:00 -08001443 """
andrewonlab7b31d232014-10-24 13:31:47 -04001444 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001445 * ingressDevice: device id of ingress device
1446 * egressDevice: device id of egress device
andrewonlab7b31d232014-10-24 13:31:47 -04001447 Optional:
1448 TODO: Still needs to be implemented via dev side
kelvin-onlabfb521662015-02-27 09:52:40 -08001449 Description:
1450 Adds an optical intent by specifying an ingress and egress device
1451 Returns:
1452 A string of the intent id or None on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08001453 """
andrewonlab7b31d232014-10-24 13:31:47 -04001454 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001455 cmdStr = "add-optical-intent " + str( ingressDevice ) +\
1456 " " + str( egressDevice )
1457 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001458 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001459 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08001460 # If error, return error message
Jon Halle3f39ff2015-01-13 11:50:53 -08001461 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001462 main.log.error( self.name + ": Error in adding Optical intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001463 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001464 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001465 main.log.info( "Optical intent installed between " +
1466 str( ingressDevice ) + " and " +
1467 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001468 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001469 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001470 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001471 else:
1472 main.log.error( "Error, intent ID not found" )
1473 return None
Jon Hallc6793552016-01-19 14:18:37 -08001474 except AssertionError:
1475 main.log.exception( "" )
1476 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001477 except TypeError:
1478 main.log.exception( self.name + ": Object not as expected" )
1479 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001480 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001481 main.log.error( self.name + ": EOF exception found" )
1482 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001483 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001484 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001485 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001486 main.cleanAndExit()
andrewonlab7b31d232014-10-24 13:31:47 -04001487
kelvin-onlabd3b64892015-01-20 13:26:24 -08001488 def addPointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001489 self,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001490 ingressDevice,
1491 egressDevice,
1492 portIngress="",
1493 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001494 ethType="",
1495 ethSrc="",
1496 ethDst="",
1497 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001498 lambdaAlloc=False,
alisonda157272016-12-22 01:13:21 -08001499 protected=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001500 ipProto="",
1501 ipSrc="",
1502 ipDst="",
1503 tcpSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001504 tcpDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001505 vlanId="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001506 setVlan="",
1507 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001508 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001509 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001510 * ingressDevice: device id of ingress device
1511 * egressDevice: device id of egress device
andrewonlab289e4b72014-10-21 21:24:18 -04001512 Optional:
1513 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001514 * ethSrc: specify ethSrc ( i.e. src mac addr )
1515 * ethDst: specify ethDst ( i.e. dst mac addr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001516 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001517 * lambdaAlloc: if True, intent will allocate lambda
andrewonlab40ccd8b2014-11-06 16:23:34 -05001518 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001519 * ipProto: specify ip protocol
andrewonlabf77e0cb2014-11-11 17:17:59 -05001520 * ipSrc: specify ip source address
1521 * ipDst: specify ip destination address
1522 * tcpSrc: specify tcp source port
1523 * tcpDst: specify tcp destination port
Jeremy Songster832f9e92016-05-05 14:30:49 -07001524 * vlanId: specify vlan ID
Jeremy Songsterff553672016-05-12 17:06:23 -07001525 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001526 * encap: specify an Encapsulation type to use
andrewonlab4dbb4d82014-10-17 18:22:31 -04001527 Description:
kelvin8ec71442015-01-15 16:57:00 -08001528 Adds a point-to-point intent ( uni-directional ) by
andrewonlab289e4b72014-10-21 21:24:18 -04001529 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001530 Returns:
1531 A string of the intent id or None on error
andrewonlab289e4b72014-10-21 21:24:18 -04001532
Jon Halle3f39ff2015-01-13 11:50:53 -08001533 NOTE: This function may change depending on the
andrewonlab4dbb4d82014-10-17 18:22:31 -04001534 options developers provide for point-to-point
1535 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001536 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001537 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001538 cmd = "add-point-intent"
andrewonlab36af3822014-11-18 17:48:18 -05001539
Jeremy Songsterff553672016-05-12 17:06:23 -07001540 if ethType:
1541 cmd += " --ethType " + str( ethType )
1542 if ethSrc:
1543 cmd += " --ethSrc " + str( ethSrc )
1544 if ethDst:
1545 cmd += " --ethDst " + str( ethDst )
1546 if bandwidth:
1547 cmd += " --bandwidth " + str( bandwidth )
1548 if lambdaAlloc:
1549 cmd += " --lambda "
1550 if ipProto:
1551 cmd += " --ipProto " + str( ipProto )
1552 if ipSrc:
1553 cmd += " --ipSrc " + str( ipSrc )
1554 if ipDst:
1555 cmd += " --ipDst " + str( ipDst )
1556 if tcpSrc:
1557 cmd += " --tcpSrc " + str( tcpSrc )
1558 if tcpDst:
1559 cmd += " --tcpDst " + str( tcpDst )
1560 if vlanId:
1561 cmd += " -v " + str( vlanId )
1562 if setVlan:
1563 cmd += " --setVlan " + str( setVlan )
Jeremy Songsterc032f162016-08-04 17:14:49 -07001564 if encap:
1565 cmd += " --encapsulation " + str( encap )
alisonda157272016-12-22 01:13:21 -08001566 if protected:
1567 cmd += " --protect "
andrewonlab289e4b72014-10-21 21:24:18 -04001568
kelvin8ec71442015-01-15 16:57:00 -08001569 # Check whether the user appended the port
1570 # or provided it as an input
kelvin-onlabd3b64892015-01-20 13:26:24 -08001571 if "/" in ingressDevice:
1572 cmd += " " + str( ingressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001573 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001574 if not portIngress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001575 main.log.error( "You must specify the ingress port" )
kelvin8ec71442015-01-15 16:57:00 -08001576 # TODO: perhaps more meaningful return
kelvin-onlabfb521662015-02-27 09:52:40 -08001577 # Would it make sense to throw an exception and exit
1578 # the test?
1579 return None
andrewonlab36af3822014-11-18 17:48:18 -05001580
kelvin8ec71442015-01-15 16:57:00 -08001581 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001582 str( ingressDevice ) + "/" +\
1583 str( portIngress ) + " "
andrewonlab36af3822014-11-18 17:48:18 -05001584
kelvin-onlabd3b64892015-01-20 13:26:24 -08001585 if "/" in egressDevice:
1586 cmd += " " + str( egressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001587 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001588 if not portEgress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001589 main.log.error( "You must specify the egress port" )
1590 return None
Jon Halle3f39ff2015-01-13 11:50:53 -08001591
kelvin8ec71442015-01-15 16:57:00 -08001592 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001593 str( egressDevice ) + "/" +\
1594 str( portEgress )
kelvin8ec71442015-01-15 16:57:00 -08001595
kelvin-onlab898a6c62015-01-16 14:13:53 -08001596 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001597 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001598 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001599 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001600 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001601 main.log.error( self.name + ": Error in adding point-to-point intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001602 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001603 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001604 # TODO: print out all the options in this message?
1605 main.log.info( "Point-to-point intent installed between " +
1606 str( ingressDevice ) + " and " +
1607 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001608 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001609 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001610 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001611 else:
1612 main.log.error( "Error, intent ID not found" )
1613 return None
Jon Hallc6793552016-01-19 14:18:37 -08001614 except AssertionError:
1615 main.log.exception( "" )
1616 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001617 except TypeError:
1618 main.log.exception( self.name + ": Object not as expected" )
1619 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001620 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001621 main.log.error( self.name + ": EOF exception found" )
1622 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001623 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001624 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001625 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001626 main.cleanAndExit()
andrewonlab4dbb4d82014-10-17 18:22:31 -04001627
kelvin-onlabd3b64892015-01-20 13:26:24 -08001628 def addMultipointToSinglepointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001629 self,
shahshreyac2f97072015-03-19 17:04:29 -07001630 ingressDeviceList,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001631 egressDevice,
shahshreyac2f97072015-03-19 17:04:29 -07001632 portIngressList=None,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001633 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001634 ethType="",
1635 ethSrc="",
1636 ethDst="",
1637 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001638 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001639 ipProto="",
1640 ipSrc="",
1641 ipDst="",
1642 tcpSrc="",
1643 tcpDst="",
1644 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001645 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001646 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001647 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001648 partial=False,
1649 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001650 """
shahshreyad0c80432014-12-04 16:56:05 -08001651 Note:
shahshreya70622b12015-03-19 17:19:00 -07001652 This function assumes the format of all ingress devices
Jon Hallbe379602015-03-24 13:39:32 -07001653 is same. That is, all ingress devices include port numbers
1654 with a "/" or all ingress devices could specify device
1655 ids and port numbers seperately.
shahshreyad0c80432014-12-04 16:56:05 -08001656 Required:
Jon Hallbe379602015-03-24 13:39:32 -07001657 * ingressDeviceList: List of device ids of ingress device
shahshreyac2f97072015-03-19 17:04:29 -07001658 ( Atleast 2 ingress devices required in the list )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001659 * egressDevice: device id of egress device
shahshreyad0c80432014-12-04 16:56:05 -08001660 Optional:
1661 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001662 * ethSrc: specify ethSrc ( i.e. src mac addr )
1663 * ethDst: specify ethDst ( i.e. dst mac addr )
shahshreyad0c80432014-12-04 16:56:05 -08001664 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001665 * lambdaAlloc: if True, intent will allocate lambda
shahshreyad0c80432014-12-04 16:56:05 -08001666 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001667 * ipProto: specify ip protocol
shahshreyad0c80432014-12-04 16:56:05 -08001668 * ipSrc: specify ip source address
1669 * ipDst: specify ip destination address
1670 * tcpSrc: specify tcp source port
1671 * tcpDst: specify tcp destination port
1672 * setEthSrc: action to Rewrite Source MAC Address
1673 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001674 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001675 * setVlan: specify VLAN Id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001676 * encap: specify a type of encapsulation
shahshreyad0c80432014-12-04 16:56:05 -08001677 Description:
kelvin8ec71442015-01-15 16:57:00 -08001678 Adds a multipoint-to-singlepoint intent ( uni-directional ) by
shahshreyad0c80432014-12-04 16:56:05 -08001679 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001680 Returns:
1681 A string of the intent id or None on error
shahshreyad0c80432014-12-04 16:56:05 -08001682
Jon Halle3f39ff2015-01-13 11:50:53 -08001683 NOTE: This function may change depending on the
Jon Hallefbd9792015-03-05 16:11:36 -08001684 options developers provide for multipoint-to-singlepoint
shahshreyad0c80432014-12-04 16:56:05 -08001685 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001686 """
shahshreyad0c80432014-12-04 16:56:05 -08001687 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001688 cmd = "add-multi-to-single-intent"
shahshreyad0c80432014-12-04 16:56:05 -08001689
Jeremy Songsterff553672016-05-12 17:06:23 -07001690 if ethType:
1691 cmd += " --ethType " + str( ethType )
1692 if ethSrc:
1693 cmd += " --ethSrc " + str( ethSrc )
1694 if ethDst:
1695 cmd += " --ethDst " + str( ethDst )
1696 if bandwidth:
1697 cmd += " --bandwidth " + str( bandwidth )
1698 if lambdaAlloc:
1699 cmd += " --lambda "
1700 if ipProto:
1701 cmd += " --ipProto " + str( ipProto )
1702 if ipSrc:
1703 cmd += " --ipSrc " + str( ipSrc )
1704 if ipDst:
1705 cmd += " --ipDst " + str( ipDst )
1706 if tcpSrc:
1707 cmd += " --tcpSrc " + str( tcpSrc )
1708 if tcpDst:
1709 cmd += " --tcpDst " + str( tcpDst )
1710 if setEthSrc:
1711 cmd += " --setEthSrc " + str( setEthSrc )
1712 if setEthDst:
1713 cmd += " --setEthDst " + str( setEthDst )
1714 if vlanId:
1715 cmd += " -v " + str( vlanId )
1716 if setVlan:
1717 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001718 if partial:
1719 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001720 if encap:
1721 cmd += " --encapsulation " + str( encap )
shahshreyad0c80432014-12-04 16:56:05 -08001722
kelvin8ec71442015-01-15 16:57:00 -08001723 # Check whether the user appended the port
1724 # or provided it as an input
shahshreyac2f97072015-03-19 17:04:29 -07001725
1726 if portIngressList is None:
1727 for ingressDevice in ingressDeviceList:
1728 if "/" in ingressDevice:
1729 cmd += " " + str( ingressDevice )
1730 else:
1731 main.log.error( "You must specify " +
Jon Hallbe379602015-03-24 13:39:32 -07001732 "the ingress port" )
shahshreyac2f97072015-03-19 17:04:29 -07001733 # TODO: perhaps more meaningful return
1734 return main.FALSE
shahshreyad0c80432014-12-04 16:56:05 -08001735 else:
Jon Hall71ce4e72015-03-23 14:05:58 -07001736 if len( ingressDeviceList ) == len( portIngressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001737 for ingressDevice, portIngress in zip( ingressDeviceList,
1738 portIngressList ):
shahshreya70622b12015-03-19 17:19:00 -07001739 cmd += " " + \
1740 str( ingressDevice ) + "/" +\
1741 str( portIngress ) + " "
kelvin-onlab38143812015-04-01 15:03:01 -07001742 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001743 main.log.error( "Device list and port list does not " +
1744 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001745 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001746 if "/" in egressDevice:
1747 cmd += " " + str( egressDevice )
shahshreyad0c80432014-12-04 16:56:05 -08001748 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001749 if not portEgress:
kelvin8ec71442015-01-15 16:57:00 -08001750 main.log.error( "You must specify " +
1751 "the egress port" )
shahshreyad0c80432014-12-04 16:56:05 -08001752 return main.FALSE
Jon Halle3f39ff2015-01-13 11:50:53 -08001753
kelvin8ec71442015-01-15 16:57:00 -08001754 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001755 str( egressDevice ) + "/" +\
1756 str( portEgress )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001757 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001758 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001759 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001760 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001761 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001762 main.log.error( self.name + ": Error in adding multipoint-to-singlepoint " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001763 "intent" )
1764 return None
shahshreyad0c80432014-12-04 16:56:05 -08001765 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001766 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001767 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001768 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001769 else:
1770 main.log.error( "Error, intent ID not found" )
1771 return None
Jon Hallc6793552016-01-19 14:18:37 -08001772 except AssertionError:
1773 main.log.exception( "" )
1774 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001775 except TypeError:
1776 main.log.exception( self.name + ": Object not as expected" )
1777 return None
1778 except pexpect.EOF:
1779 main.log.error( self.name + ": EOF exception found" )
1780 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001781 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001782 except Exception:
1783 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001784 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001785
1786 def addSinglepointToMultipointIntent(
1787 self,
1788 ingressDevice,
1789 egressDeviceList,
1790 portIngress="",
1791 portEgressList=None,
1792 ethType="",
1793 ethSrc="",
1794 ethDst="",
1795 bandwidth="",
1796 lambdaAlloc=False,
1797 ipProto="",
1798 ipSrc="",
1799 ipDst="",
1800 tcpSrc="",
1801 tcpDst="",
1802 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001803 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001804 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001805 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001806 partial=False,
1807 encap="" ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001808 """
1809 Note:
1810 This function assumes the format of all egress devices
1811 is same. That is, all egress devices include port numbers
1812 with a "/" or all egress devices could specify device
1813 ids and port numbers seperately.
1814 Required:
1815 * EgressDeviceList: List of device ids of egress device
1816 ( Atleast 2 eress devices required in the list )
1817 * ingressDevice: device id of ingress device
1818 Optional:
1819 * ethType: specify ethType
1820 * ethSrc: specify ethSrc ( i.e. src mac addr )
1821 * ethDst: specify ethDst ( i.e. dst mac addr )
1822 * bandwidth: specify bandwidth capacity of link
1823 * lambdaAlloc: if True, intent will allocate lambda
1824 for the specified intent
1825 * ipProto: specify ip protocol
1826 * ipSrc: specify ip source address
1827 * ipDst: specify ip destination address
1828 * tcpSrc: specify tcp source port
1829 * tcpDst: specify tcp destination port
1830 * setEthSrc: action to Rewrite Source MAC Address
1831 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001832 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001833 * setVlan: specify VLAN ID treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001834 * encap: specify an encapsulation type
kelvin-onlabb9408212015-04-01 13:34:04 -07001835 Description:
1836 Adds a singlepoint-to-multipoint intent ( uni-directional ) by
1837 specifying device id's and optional fields
1838 Returns:
1839 A string of the intent id or None on error
1840
1841 NOTE: This function may change depending on the
1842 options developers provide for singlepoint-to-multipoint
1843 intent via cli
1844 """
1845 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001846 cmd = "add-single-to-multi-intent"
kelvin-onlabb9408212015-04-01 13:34:04 -07001847
Jeremy Songsterff553672016-05-12 17:06:23 -07001848 if ethType:
1849 cmd += " --ethType " + str( ethType )
1850 if ethSrc:
1851 cmd += " --ethSrc " + str( ethSrc )
1852 if ethDst:
1853 cmd += " --ethDst " + str( ethDst )
1854 if bandwidth:
1855 cmd += " --bandwidth " + str( bandwidth )
1856 if lambdaAlloc:
1857 cmd += " --lambda "
1858 if ipProto:
1859 cmd += " --ipProto " + str( ipProto )
1860 if ipSrc:
1861 cmd += " --ipSrc " + str( ipSrc )
1862 if ipDst:
1863 cmd += " --ipDst " + str( ipDst )
1864 if tcpSrc:
1865 cmd += " --tcpSrc " + str( tcpSrc )
1866 if tcpDst:
1867 cmd += " --tcpDst " + str( tcpDst )
1868 if setEthSrc:
1869 cmd += " --setEthSrc " + str( setEthSrc )
1870 if setEthDst:
1871 cmd += " --setEthDst " + str( setEthDst )
1872 if vlanId:
1873 cmd += " -v " + str( vlanId )
1874 if setVlan:
1875 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001876 if partial:
1877 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001878 if encap:
1879 cmd += " --encapsulation " + str( encap )
kelvin-onlabb9408212015-04-01 13:34:04 -07001880
1881 # Check whether the user appended the port
1882 # or provided it as an input
Jon Hall08f61bc2015-04-13 16:00:30 -07001883
kelvin-onlabb9408212015-04-01 13:34:04 -07001884 if "/" in ingressDevice:
1885 cmd += " " + str( ingressDevice )
1886 else:
1887 if not portIngress:
1888 main.log.error( "You must specify " +
1889 "the Ingress port" )
1890 return main.FALSE
1891
1892 cmd += " " +\
1893 str( ingressDevice ) + "/" +\
1894 str( portIngress )
1895
1896 if portEgressList is None:
1897 for egressDevice in egressDeviceList:
1898 if "/" in egressDevice:
1899 cmd += " " + str( egressDevice )
1900 else:
1901 main.log.error( "You must specify " +
1902 "the egress port" )
1903 # TODO: perhaps more meaningful return
1904 return main.FALSE
1905 else:
1906 if len( egressDeviceList ) == len( portEgressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001907 for egressDevice, portEgress in zip( egressDeviceList,
1908 portEgressList ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001909 cmd += " " + \
1910 str( egressDevice ) + "/" +\
1911 str( portEgress )
kelvin-onlab38143812015-04-01 15:03:01 -07001912 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001913 main.log.error( "Device list and port list does not " +
1914 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001915 return main.FALSE
kelvin-onlabb9408212015-04-01 13:34:04 -07001916 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001917 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001918 assert "Command not found:" not in handle, handle
kelvin-onlabb9408212015-04-01 13:34:04 -07001919 # If error, return error message
1920 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001921 main.log.error( self.name + ": Error in adding singlepoint-to-multipoint " +
kelvin-onlabb9408212015-04-01 13:34:04 -07001922 "intent" )
shahshreyac2f97072015-03-19 17:04:29 -07001923 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001924 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001925 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001926 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001927 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001928 else:
1929 main.log.error( "Error, intent ID not found" )
1930 return None
Jon Hallc6793552016-01-19 14:18:37 -08001931 except AssertionError:
1932 main.log.exception( "" )
1933 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001934 except TypeError:
1935 main.log.exception( self.name + ": Object not as expected" )
1936 return None
shahshreyad0c80432014-12-04 16:56:05 -08001937 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001938 main.log.error( self.name + ": EOF exception found" )
1939 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001940 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001941 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001942 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001943 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001944
Hari Krishna9e232602015-04-13 17:29:08 -07001945 def addMplsIntent(
1946 self,
1947 ingressDevice,
1948 egressDevice,
Hari Krishna87a17f12015-04-13 17:42:23 -07001949 ingressPort="",
1950 egressPort="",
Hari Krishna9e232602015-04-13 17:29:08 -07001951 ethType="",
1952 ethSrc="",
1953 ethDst="",
1954 bandwidth="",
1955 lambdaAlloc=False,
1956 ipProto="",
1957 ipSrc="",
1958 ipDst="",
1959 tcpSrc="",
1960 tcpDst="",
Hari Krishna87a17f12015-04-13 17:42:23 -07001961 ingressLabel="",
Hari Krishnadfff6672015-04-13 17:53:27 -07001962 egressLabel="",
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001963 priority="" ):
Hari Krishna9e232602015-04-13 17:29:08 -07001964 """
1965 Required:
1966 * ingressDevice: device id of ingress device
1967 * egressDevice: device id of egress device
1968 Optional:
1969 * ethType: specify ethType
1970 * ethSrc: specify ethSrc ( i.e. src mac addr )
1971 * ethDst: specify ethDst ( i.e. dst mac addr )
1972 * bandwidth: specify bandwidth capacity of link
1973 * lambdaAlloc: if True, intent will allocate lambda
1974 for the specified intent
1975 * ipProto: specify ip protocol
1976 * ipSrc: specify ip source address
1977 * ipDst: specify ip destination address
1978 * tcpSrc: specify tcp source port
1979 * tcpDst: specify tcp destination port
1980 * ingressLabel: Ingress MPLS label
1981 * egressLabel: Egress MPLS label
1982 Description:
1983 Adds MPLS intent by
1984 specifying device id's and optional fields
1985 Returns:
1986 A string of the intent id or None on error
1987
1988 NOTE: This function may change depending on the
1989 options developers provide for MPLS
1990 intent via cli
1991 """
1992 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001993 cmd = "add-mpls-intent"
Hari Krishna9e232602015-04-13 17:29:08 -07001994
Jeremy Songsterff553672016-05-12 17:06:23 -07001995 if ethType:
1996 cmd += " --ethType " + str( ethType )
1997 if ethSrc:
1998 cmd += " --ethSrc " + str( ethSrc )
1999 if ethDst:
2000 cmd += " --ethDst " + str( ethDst )
2001 if bandwidth:
2002 cmd += " --bandwidth " + str( bandwidth )
2003 if lambdaAlloc:
2004 cmd += " --lambda "
2005 if ipProto:
2006 cmd += " --ipProto " + str( ipProto )
2007 if ipSrc:
2008 cmd += " --ipSrc " + str( ipSrc )
2009 if ipDst:
2010 cmd += " --ipDst " + str( ipDst )
2011 if tcpSrc:
2012 cmd += " --tcpSrc " + str( tcpSrc )
2013 if tcpDst:
2014 cmd += " --tcpDst " + str( tcpDst )
2015 if ingressLabel:
2016 cmd += " --ingressLabel " + str( ingressLabel )
2017 if egressLabel:
2018 cmd += " --egressLabel " + str( egressLabel )
2019 if priority:
2020 cmd += " --priority " + str( priority )
Hari Krishna9e232602015-04-13 17:29:08 -07002021
2022 # Check whether the user appended the port
2023 # or provided it as an input
2024 if "/" in ingressDevice:
2025 cmd += " " + str( ingressDevice )
2026 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002027 if not ingressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002028 main.log.error( "You must specify the ingress port" )
2029 return None
2030
2031 cmd += " " + \
2032 str( ingressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002033 str( ingressPort ) + " "
Hari Krishna9e232602015-04-13 17:29:08 -07002034
2035 if "/" in egressDevice:
2036 cmd += " " + str( egressDevice )
2037 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002038 if not egressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002039 main.log.error( "You must specify the egress port" )
2040 return None
2041
2042 cmd += " " +\
2043 str( egressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002044 str( egressPort )
Hari Krishna9e232602015-04-13 17:29:08 -07002045
2046 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08002047 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002048 assert "Command not found:" not in handle, handle
Hari Krishna9e232602015-04-13 17:29:08 -07002049 # If error, return error message
2050 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002051 main.log.error( self.name + ": Error in adding mpls intent" )
Hari Krishna9e232602015-04-13 17:29:08 -07002052 return None
2053 else:
2054 # TODO: print out all the options in this message?
2055 main.log.info( "MPLS intent installed between " +
2056 str( ingressDevice ) + " and " +
2057 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002058 match = re.search( 'id=0x([\da-f]+),', handle )
Hari Krishna9e232602015-04-13 17:29:08 -07002059 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002060 return match.group()[ 3:-1 ]
Hari Krishna9e232602015-04-13 17:29:08 -07002061 else:
2062 main.log.error( "Error, intent ID not found" )
2063 return None
Jon Hallc6793552016-01-19 14:18:37 -08002064 except AssertionError:
2065 main.log.exception( "" )
2066 return None
Hari Krishna9e232602015-04-13 17:29:08 -07002067 except TypeError:
2068 main.log.exception( self.name + ": Object not as expected" )
2069 return None
2070 except pexpect.EOF:
2071 main.log.error( self.name + ": EOF exception found" )
2072 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002073 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002074 except Exception:
2075 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002076 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002077
Jon Hallefbd9792015-03-05 16:11:36 -08002078 def removeIntent( self, intentId, app='org.onosproject.cli',
2079 purge=False, sync=False ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002080 """
shahshreya1c818fc2015-02-26 13:44:08 -08002081 Remove intent for specified application id and intent id
Jon Hall61282e32015-03-19 11:34:11 -07002082 Optional args:-
shahshreya1c818fc2015-02-26 13:44:08 -08002083 -s or --sync: Waits for the removal before returning
Jon Hall61282e32015-03-19 11:34:11 -07002084 -p or --purge: Purge the intent from the store after removal
2085
Jon Halle3f39ff2015-01-13 11:50:53 -08002086 Returns:
Jon Hall6509dbf2016-06-21 17:01:17 -07002087 main.FALSE on error and
Jon Halle3f39ff2015-01-13 11:50:53 -08002088 cli output otherwise
kelvin-onlab898a6c62015-01-16 14:13:53 -08002089 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002090 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002091 cmdStr = "remove-intent"
shahshreya1c818fc2015-02-26 13:44:08 -08002092 if purge:
2093 cmdStr += " -p"
2094 if sync:
2095 cmdStr += " -s"
2096
2097 cmdStr += " " + app + " " + str( intentId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002098 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002099 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002100 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08002101 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002102 main.log.error( self.name + ": Error in removing intent" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002103 return main.FALSE
andrewonlab9a50dfe2014-10-17 17:22:31 -04002104 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002105 # TODO: Should this be main.TRUE
2106 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002107 except AssertionError:
2108 main.log.exception( "" )
2109 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002110 except TypeError:
2111 main.log.exception( self.name + ": Object not as expected" )
2112 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002113 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002114 main.log.error( self.name + ": EOF exception found" )
2115 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002116 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002117 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002118 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002119 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04002120
YPZhangfebf7302016-05-24 16:45:56 -07002121 def removeAllIntents( self, purge=False, sync=False, app='org.onosproject.cli', timeout=30 ):
Jeremy42df2e72016-02-23 16:37:46 -08002122 """
2123 Description:
2124 Remove all the intents
2125 Optional args:-
2126 -s or --sync: Waits for the removal before returning
2127 -p or --purge: Purge the intent from the store after removal
2128 Returns:
2129 Returns main.TRUE if all intents are removed, otherwise returns
2130 main.FALSE; Returns None for exception
2131 """
2132 try:
2133 cmdStr = "remove-intent"
2134 if purge:
2135 cmdStr += " -p"
2136 if sync:
2137 cmdStr += " -s"
2138
2139 cmdStr += " " + app
YPZhangfebf7302016-05-24 16:45:56 -07002140 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08002141 assert handle is not None, "Error in sendline"
Jeremy42df2e72016-02-23 16:37:46 -08002142 assert "Command not found:" not in handle, handle
2143 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002144 main.log.error( self.name + ": Error in removing intent" )
Jeremy42df2e72016-02-23 16:37:46 -08002145 return main.FALSE
2146 else:
2147 return main.TRUE
2148 except AssertionError:
2149 main.log.exception( "" )
2150 return None
2151 except TypeError:
2152 main.log.exception( self.name + ": Object not as expected" )
2153 return None
2154 except pexpect.EOF:
2155 main.log.error( self.name + ": EOF exception found" )
2156 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002157 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002158 except Exception:
2159 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002160 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002161
Hari Krishnaacabd5a2015-07-01 17:10:19 -07002162 def purgeWithdrawnIntents( self ):
Hari Krishna0ce0e152015-06-23 09:55:29 -07002163 """
2164 Purges all WITHDRAWN Intents
2165 """
2166 try:
2167 cmdStr = "purge-intents"
2168 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002169 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002170 assert "Command not found:" not in handle, handle
Hari Krishna0ce0e152015-06-23 09:55:29 -07002171 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002172 main.log.error( self.name + ": Error in purging intents" )
Hari Krishna0ce0e152015-06-23 09:55:29 -07002173 return main.FALSE
2174 else:
2175 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002176 except AssertionError:
2177 main.log.exception( "" )
2178 return None
Hari Krishna0ce0e152015-06-23 09:55:29 -07002179 except TypeError:
2180 main.log.exception( self.name + ": Object not as expected" )
2181 return None
2182 except pexpect.EOF:
2183 main.log.error( self.name + ": EOF exception found" )
2184 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002185 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002186 except Exception:
2187 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002188 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002189
Devin Lime6fe3c42017-10-18 16:28:40 -07002190 def wipeout( self ):
2191 """
2192 Wipe out the flows,intents,links,devices,hosts, and groups from the ONOS.
2193 """
2194 try:
2195 cmdStr = "wipe-out please"
2196 handle = self.sendline( cmdStr, timeout=60 )
2197 assert handle is not None, "Error in sendline"
2198 assert "Command not found:" not in handle, handle
2199 return main.TRUE
2200 except AssertionError:
2201 main.log.exception( "" )
2202 return None
2203 except TypeError:
2204 main.log.exception( self.name + ": Object not as expected" )
2205 return None
2206 except pexpect.EOF:
2207 main.log.error( self.name + ": EOF exception found" )
2208 main.log.error( self.name + ": " + self.handle.before )
2209 main.cleanAndExit()
2210 except Exception:
2211 main.log.exception( self.name + ": Uncaught exception!" )
2212 main.cleanAndExit()
2213
kelvin-onlabd3b64892015-01-20 13:26:24 -08002214 def routes( self, jsonFormat=False ):
kelvin8ec71442015-01-15 16:57:00 -08002215 """
kelvin-onlab898a6c62015-01-16 14:13:53 -08002216 NOTE: This method should be used after installing application:
2217 onos-app-sdnip
pingping-lin8b306ac2014-11-17 18:13:51 -08002218 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002219 * jsonFormat: enable output formatting in json
pingping-lin8b306ac2014-11-17 18:13:51 -08002220 Description:
2221 Obtain all routes in the system
kelvin8ec71442015-01-15 16:57:00 -08002222 """
pingping-lin8b306ac2014-11-17 18:13:51 -08002223 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002224 cmdStr = "routes"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002225 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002226 cmdStr += " -j"
2227 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002228 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002229 assert "Command not found:" not in handle, handle
pingping-lin8b306ac2014-11-17 18:13:51 -08002230 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002231 except AssertionError:
2232 main.log.exception( "" )
2233 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002234 except TypeError:
2235 main.log.exception( self.name + ": Object not as expected" )
2236 return None
pingping-lin8b306ac2014-11-17 18:13:51 -08002237 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002238 main.log.error( self.name + ": EOF exception found" )
2239 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002240 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002241 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002242 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002243 main.cleanAndExit()
pingping-lin8b306ac2014-11-17 18:13:51 -08002244
pingping-lin54b03372015-08-13 14:43:10 -07002245 def ipv4RouteNumber( self ):
2246 """
2247 NOTE: This method should be used after installing application:
2248 onos-app-sdnip
2249 Description:
2250 Obtain the total IPv4 routes number in the system
2251 """
2252 try:
Pratik Parab57963572017-05-09 11:37:54 -07002253 cmdStr = "routes -j"
pingping-lin54b03372015-08-13 14:43:10 -07002254 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002255 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002256 assert "Command not found:" not in handle, handle
pingping-lin54b03372015-08-13 14:43:10 -07002257 jsonResult = json.loads( handle )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002258 return len( jsonResult[ 'routes4' ] )
Jon Hallc6793552016-01-19 14:18:37 -08002259 except AssertionError:
2260 main.log.exception( "" )
2261 return None
2262 except ( TypeError, ValueError ):
2263 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002264 return None
2265 except pexpect.EOF:
2266 main.log.error( self.name + ": EOF exception found" )
2267 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002268 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002269 except Exception:
2270 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002271 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002272
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002273 # =============Function to check Bandwidth allocation========
Jon Hall0e240372018-05-02 11:21:57 -07002274 def allocations( self, jsonFormat = True ):
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002275 """
2276 Description:
2277 Obtain Bandwidth Allocation Information from ONOS cli.
2278 """
2279 try:
2280 cmdStr = "allocations"
2281 if jsonFormat:
2282 cmdStr += " -j"
Jon Hall0e240372018-05-02 11:21:57 -07002283 handle = self.sendline( cmdStr, timeout=300 )
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002284 assert handle is not None, "Error in sendline"
2285 assert "Command not found:" not in handle, handle
2286 return handle
2287 except AssertionError:
2288 main.log.exception( "" )
2289 return None
2290 except ( TypeError, ValueError ):
2291 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
2292 return None
2293 except pexpect.EOF:
2294 main.log.error( self.name + ": EOF exception found" )
2295 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002296 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002297 except Exception:
2298 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002299 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002300
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002301 def intents( self, jsonFormat = True, summary = False, **intentargs ):
kelvin8ec71442015-01-15 16:57:00 -08002302 """
andrewonlabe6745342014-10-17 14:29:13 -04002303 Description:
Jon Hallff566d52016-01-15 14:45:36 -08002304 Obtain intents from the ONOS cli.
2305 Optional:
2306 * jsonFormat: Enable output formatting in json, default to True
2307 * summary: Whether only output the intent summary, defaults to False
2308 * type: Only output a certain type of intent. This options is valid
2309 only when jsonFormat is True and summary is True.
kelvin-onlab898a6c62015-01-16 14:13:53 -08002310 """
andrewonlabe6745342014-10-17 14:29:13 -04002311 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002312 cmdStr = "intents"
pingping-lin8244a3b2015-09-16 13:36:56 -07002313 if summary:
2314 cmdStr += " -s"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002315 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002316 cmdStr += " -j"
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002317 handle = self.sendline( cmdStr, timeout=300 )
You Wangb5a55f72017-03-03 12:51:05 -08002318 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002319 assert "Command not found:" not in handle, handle
pingping-lin8244a3b2015-09-16 13:36:56 -07002320 args = utilities.parse_args( [ "TYPE" ], **intentargs )
acsmars5b5fbaf2015-09-18 10:38:20 -07002321 if "TYPE" in args.keys():
Jon Hallff566d52016-01-15 14:45:36 -08002322 intentType = args[ "TYPE" ]
acsmars5b5fbaf2015-09-18 10:38:20 -07002323 else:
Jon Hallff566d52016-01-15 14:45:36 -08002324 intentType = ""
2325 # IF we want the summary of a specific intent type
2326 if jsonFormat and summary and ( intentType != "" ):
pingping-lin8244a3b2015-09-16 13:36:56 -07002327 jsonResult = json.loads( handle )
Jon Hallff566d52016-01-15 14:45:36 -08002328 if intentType in jsonResult.keys():
2329 return jsonResult[ intentType ]
pingping-lin8244a3b2015-09-16 13:36:56 -07002330 else:
Jon Hallff566d52016-01-15 14:45:36 -08002331 main.log.error( "unknown TYPE, returning all types of intents" )
pingping-lin8244a3b2015-09-16 13:36:56 -07002332 return handle
2333 else:
2334 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002335 except AssertionError:
2336 main.log.exception( "" )
2337 return None
2338 except ( TypeError, ValueError ):
2339 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002340 return None
2341 except pexpect.EOF:
2342 main.log.error( self.name + ": EOF exception found" )
2343 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002344 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002345 except Exception:
2346 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002347 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002348
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002349 def getIntentState( self, intentsId, intentsJson=None ):
kelvin-onlab54400a92015-02-26 18:05:51 -08002350 """
You Wangfdcbfc42016-05-16 12:16:53 -07002351 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002352 Gets intent state. Accepts a single intent ID (string type) or a
You Wangfdcbfc42016-05-16 12:16:53 -07002353 list of intent IDs.
2354 Parameters:
2355 intentsId: intent ID, both string type and list type are acceptable
kelvin-onlab54400a92015-02-26 18:05:51 -08002356 intentsJson: parsed json object from the onos:intents api
You Wangfdcbfc42016-05-16 12:16:53 -07002357 Returns:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002358 Returns the state (string type) of the ID if a single intent ID is
You Wangfdcbfc42016-05-16 12:16:53 -07002359 accepted.
2360 Returns a list of dictionaries if a list of intent IDs is accepted,
2361 and each dictionary maps 'id' to the Intent ID and 'state' to
2362 corresponding intent state.
kelvin-onlab54400a92015-02-26 18:05:51 -08002363 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002364
kelvin-onlab54400a92015-02-26 18:05:51 -08002365 try:
2366 state = "State is Undefined"
2367 if not intentsJson:
Jon Hallc6793552016-01-19 14:18:37 -08002368 rawJson = self.intents()
kelvin-onlab54400a92015-02-26 18:05:51 -08002369 else:
Jon Hallc6793552016-01-19 14:18:37 -08002370 rawJson = intentsJson
2371 parsedIntentsJson = json.loads( rawJson )
Jon Hallefbd9792015-03-05 16:11:36 -08002372 if isinstance( intentsId, types.StringType ):
Jon Hallc6793552016-01-19 14:18:37 -08002373 for intent in parsedIntentsJson:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002374 if intentsId == intent[ 'id' ]:
2375 state = intent[ 'state' ]
kelvin-onlab54400a92015-02-26 18:05:51 -08002376 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002377 main.log.info( "Cannot find intent ID" + str( intentsId ) +
Jon Hall53158082017-05-18 11:17:00 -07002378 " in the list" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002379 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002380 elif isinstance( intentsId, types.ListType ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002381 dictList = []
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002382 for i in xrange( len( intentsId ) ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002383 stateDict = {}
Jon Hall53158082017-05-18 11:17:00 -07002384 for intent in parsedIntentsJson:
2385 if intentsId[ i ] == intent[ 'id' ]:
2386 stateDict[ 'state' ] = intent[ 'state' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002387 stateDict[ 'id' ] = intentsId[ i ]
Jon Hallefbd9792015-03-05 16:11:36 -08002388 dictList.append( stateDict )
kelvin-onlab54400a92015-02-26 18:05:51 -08002389 break
Jon Hallefbd9792015-03-05 16:11:36 -08002390 if len( intentsId ) != len( dictList ):
Jon Hall53158082017-05-18 11:17:00 -07002391 main.log.warn( "Could not find all intents in ONOS output" )
2392 main.log.debug( "expected ids: {} \n ONOS intents: {}".format( intentsId, parsedIntentsJson ) )
kelvin-onlab07dbd012015-03-04 16:29:39 -08002393 return dictList
kelvin-onlab54400a92015-02-26 18:05:51 -08002394 else:
Jon Hall53158082017-05-18 11:17:00 -07002395 main.log.info( "Invalid type for intentsId argument" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002396 return None
Jon Hallc6793552016-01-19 14:18:37 -08002397 except ( TypeError, ValueError ):
2398 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
kelvin-onlab54400a92015-02-26 18:05:51 -08002399 return None
2400 except pexpect.EOF:
2401 main.log.error( self.name + ": EOF exception found" )
2402 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002403 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002404 except Exception:
kelvin-onlab54400a92015-02-26 18:05:51 -08002405 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002406 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07002407
Jon Hallf539eb92017-05-22 17:18:42 -07002408 def checkIntentState( self, intentsId, expectedState='INSTALLED' ):
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002409 """
2410 Description:
2411 Check intents state
2412 Required:
2413 intentsId - List of intents ID to be checked
2414 Optional:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002415 expectedState - Check the expected state(s) of each intents
kelvin-onlabf512e942015-06-08 19:42:59 -07002416 state in the list.
2417 *NOTE: You can pass in a list of expected state,
2418 Eg: expectedState = [ 'INSTALLED' , 'INSTALLING' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002419 Return:
Jon Hall53158082017-05-18 11:17:00 -07002420 Returns main.TRUE only if all intent are the same as expected states,
2421 otherwise returns main.FALSE.
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002422 """
2423 try:
kelvin-onlabf512e942015-06-08 19:42:59 -07002424 returnValue = main.TRUE
Jon Hallf539eb92017-05-22 17:18:42 -07002425 # Generating a dictionary: intent id as a key and state as value
Devin Lim752dd7b2017-06-27 14:40:03 -07002426
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002427 # intentsDict = self.getIntentState( intentsId )
Devin Lim752dd7b2017-06-27 14:40:03 -07002428 intentsDict = []
2429 for intent in json.loads( self.intents() ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002430 if isinstance( intentsId, types.StringType ) \
2431 and intent.get( 'id' ) == intentsId:
2432 intentsDict.append( intent )
2433 elif isinstance( intentsId, types.ListType ) \
Devin Lim752dd7b2017-06-27 14:40:03 -07002434 and any( intent.get( 'id' ) == ids for ids in intentsId ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002435 intentsDict.append( intent )
Devin Lim752dd7b2017-06-27 14:40:03 -07002436
2437 if not intentsDict:
Jon Hallae04e622016-01-27 10:38:05 -08002438 main.log.info( self.name + ": There is something wrong " +
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002439 "getting intents state" )
2440 return main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002441
2442 if isinstance( expectedState, types.StringType ):
2443 for intents in intentsDict:
2444 if intents.get( 'state' ) != expectedState:
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002445 main.log.debug( self.name + " : Intent ID - " +
2446 intents.get( 'id' ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002447 " actual state = " +
2448 intents.get( 'state' )
2449 + " does not equal expected state = "
2450 + expectedState )
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002451 returnValue = main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002452 elif isinstance( expectedState, types.ListType ):
2453 for intents in intentsDict:
2454 if not any( state == intents.get( 'state' ) for state in
2455 expectedState ):
2456 main.log.debug( self.name + " : Intent ID - " +
2457 intents.get( 'id' ) +
2458 " actual state = " +
2459 intents.get( 'state' ) +
2460 " does not equal expected states = "
2461 + str( expectedState ) )
2462 returnValue = main.FALSE
2463
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002464 if returnValue == main.TRUE:
2465 main.log.info( self.name + ": All " +
2466 str( len( intentsDict ) ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002467 " intents are in " + str( expectedState ) +
2468 " state" )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002469 return returnValue
2470 except TypeError:
2471 main.log.exception( self.name + ": Object not as expected" )
2472 return None
2473 except pexpect.EOF:
2474 main.log.error( self.name + ": EOF exception found" )
2475 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002476 main.cleanAndExit()
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002477 except Exception:
2478 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002479 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04002480
Jon Hallf539eb92017-05-22 17:18:42 -07002481 def compareBandwidthAllocations( self, expectedAllocations ):
2482 """
2483 Description:
2484 Compare the allocated bandwidth with the given allocations
2485 Required:
2486 expectedAllocations - The expected ONOS output of the allocations command
2487 Return:
2488 Returns main.TRUE only if all intent are the same as expected states,
2489 otherwise returns main.FALSE.
2490 """
2491 # FIXME: Convert these string comparisons to object comparisons
2492 try:
2493 returnValue = main.TRUE
2494 bandwidthFailed = False
2495 rawAlloc = self.allocations()
2496 expectedFormat = StringIO( expectedAllocations )
2497 ONOSOutput = StringIO( rawAlloc )
2498 main.log.debug( "ONOSOutput: {}\nexpected output: {}".format( str( ONOSOutput ),
2499 str( expectedFormat ) ) )
2500
2501 for actual, expected in izip( ONOSOutput, expectedFormat ):
2502 actual = actual.rstrip()
2503 expected = expected.rstrip()
2504 main.log.debug( "Expect: {}\nactual: {}".format( expected, actual ) )
2505 if actual != expected and 'allocated' in actual and 'allocated' in expected:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002506 marker1 = actual.find( 'allocated' )
2507 m1 = actual[ :marker1 ]
2508 marker2 = expected.find( 'allocated' )
2509 m2 = expected[ :marker2 ]
Jon Hallf539eb92017-05-22 17:18:42 -07002510 if m1 != m2:
2511 bandwidthFailed = True
2512 elif actual != expected and 'allocated' not in actual and 'allocated' not in expected:
2513 bandwidthFailed = True
2514 expectedFormat.close()
2515 ONOSOutput.close()
2516
2517 if bandwidthFailed:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002518 main.log.error( "Bandwidth not allocated correctly using Intents!!" )
Jon Hallf539eb92017-05-22 17:18:42 -07002519 returnValue = main.FALSE
2520 return returnValue
2521 except TypeError:
2522 main.log.exception( self.name + ": Object not as expected" )
2523 return None
2524 except pexpect.EOF:
2525 main.log.error( self.name + ": EOF exception found" )
2526 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002527 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002528 except Exception:
2529 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002530 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002531
You Wang66518af2016-05-16 15:32:59 -07002532 def compareIntent( self, intentDict ):
2533 """
2534 Description:
2535 Compare the intent ids and states provided in the argument with all intents in ONOS
2536 Return:
2537 Returns main.TRUE if the two sets of intents match exactly, otherwise main.FALSE
2538 Arguments:
2539 intentDict: a dictionary which maps intent ids to intent states
2540 """
2541 try:
2542 intentsRaw = self.intents()
2543 intentsJson = json.loads( intentsRaw )
2544 intentDictONOS = {}
2545 for intent in intentsJson:
2546 intentDictONOS[ intent[ 'id' ] ] = intent[ 'state' ]
You Wang58d04452016-09-21 15:13:05 -07002547 returnValue = main.TRUE
You Wang66518af2016-05-16 15:32:59 -07002548 if len( intentDict ) != len( intentDictONOS ):
You Wang58d04452016-09-21 15:13:05 -07002549 main.log.warn( self.name + ": expected intent count does not match that in ONOS, " +
You Wang66518af2016-05-16 15:32:59 -07002550 str( len( intentDict ) ) + " expected and " +
2551 str( len( intentDictONOS ) ) + " actual" )
You Wang58d04452016-09-21 15:13:05 -07002552 returnValue = main.FALSE
You Wang66518af2016-05-16 15:32:59 -07002553 for intentID in intentDict.keys():
Jon Halle0f0b342017-04-18 11:43:47 -07002554 if intentID not in intentDictONOS.keys():
You Wang66518af2016-05-16 15:32:59 -07002555 main.log.debug( self.name + ": intent ID - " + intentID + " is not in ONOS" )
2556 returnValue = main.FALSE
You Wang58d04452016-09-21 15:13:05 -07002557 else:
2558 if intentDict[ intentID ] != intentDictONOS[ intentID ]:
2559 main.log.debug( self.name + ": intent ID - " + intentID +
2560 " expected state is " + intentDict[ intentID ] +
2561 " but actual state is " + intentDictONOS[ intentID ] )
2562 returnValue = main.FALSE
2563 intentDictONOS.pop( intentID )
2564 if len( intentDictONOS ) > 0:
2565 returnValue = main.FALSE
2566 for intentID in intentDictONOS.keys():
2567 main.log.debug( self.name + ": find extra intent in ONOS: intent ID " + intentID )
You Wang66518af2016-05-16 15:32:59 -07002568 if returnValue == main.TRUE:
2569 main.log.info( self.name + ": all intent IDs and states match that in ONOS" )
2570 return returnValue
You Wang1be9a512016-05-26 16:54:17 -07002571 except KeyError:
2572 main.log.exception( self.name + ": KeyError exception found" )
2573 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002574 except ( TypeError, ValueError ):
2575 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intentsRaw ) )
You Wang85560372016-05-18 10:44:33 -07002576 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002577 except pexpect.EOF:
2578 main.log.error( self.name + ": EOF exception found" )
2579 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002580 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002581 except Exception:
2582 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002583 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002584
YPZhang14a4aa92016-07-15 13:37:15 -07002585 def checkIntentSummary( self, timeout=60, noExit=True ):
GlennRCed771242016-01-13 17:02:47 -08002586 """
2587 Description:
2588 Check the number of installed intents.
2589 Optional:
2590 timeout - the timeout for pexcept
YPZhang14a4aa92016-07-15 13:37:15 -07002591 noExit - If noExit, TestON will not exit if any except.
GlennRCed771242016-01-13 17:02:47 -08002592 Return:
2593 Returns main.TRUE only if the number of all installed intents are the same as total intents number
2594 , otherwise, returns main.FALSE.
2595 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002596
GlennRCed771242016-01-13 17:02:47 -08002597 try:
2598 cmd = "intents -s -j"
2599
2600 # Check response if something wrong
YPZhang14a4aa92016-07-15 13:37:15 -07002601 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002602 if response is None:
YPZhang0584d432016-06-21 15:20:13 -07002603 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002604 response = json.loads( response )
2605
2606 # get total and installed number, see if they are match
2607 allState = response.get( 'all' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002608 if allState.get( 'total' ) == allState.get( 'installed' ):
Jon Halla478b852017-12-04 15:00:15 -08002609 main.log.info( 'Total Intents: {} Installed Intents: {}'.format(
2610 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002611 return main.TRUE
Jon Halla478b852017-12-04 15:00:15 -08002612 main.log.info( 'Verified Intents failed Expected intents: {} installed intents: {}'.format(
2613 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002614 return main.FALSE
2615
Jon Hallc6793552016-01-19 14:18:37 -08002616 except ( TypeError, ValueError ):
2617 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
GlennRCed771242016-01-13 17:02:47 -08002618 return None
2619 except pexpect.EOF:
2620 main.log.error( self.name + ": EOF exception found" )
2621 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002622 if noExit:
2623 return main.FALSE
2624 else:
Devin Lim44075962017-08-11 10:56:37 -07002625 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07002626 except pexpect.TIMEOUT:
2627 main.log.error( self.name + ": ONOS timeout" )
2628 return None
GlennRCed771242016-01-13 17:02:47 -08002629 except Exception:
2630 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002631 if noExit:
2632 return main.FALSE
2633 else:
Devin Lim44075962017-08-11 10:56:37 -07002634 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002635
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002636 def flows( self, state="any", jsonFormat=True, timeout=60, noExit=False, noCore=False, device=""):
kelvin8ec71442015-01-15 16:57:00 -08002637 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002638 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002639 * jsonFormat: enable output formatting in json
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002640 * noCore: suppress core flows
Shreya Shah0f01c812014-10-26 20:15:28 -04002641 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002642 Obtain flows currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08002643 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002644 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002645 cmdStr = "flows"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002646 if jsonFormat:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002647 cmdStr += " -j"
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002648 if noCore:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002649 cmdStr += " -n"
2650 cmdStr += " " + state
2651 cmdStr += " " + device
YPZhangebf9eb52016-05-12 15:20:24 -07002652 handle = self.sendline( cmdStr, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002653 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002654 assert "Command not found:" not in handle, handle
2655 if re.search( "Error:", handle ):
2656 main.log.error( self.name + ": flows() response: " +
2657 str( handle ) )
2658 return handle
2659 except AssertionError:
2660 main.log.exception( "" )
GlennRCed771242016-01-13 17:02:47 -08002661 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002662 except TypeError:
2663 main.log.exception( self.name + ": Object not as expected" )
2664 return None
Jon Hallc6793552016-01-19 14:18:37 -08002665 except pexpect.TIMEOUT:
2666 main.log.error( self.name + ": ONOS timeout" )
2667 return None
Shreya Shah0f01c812014-10-26 20:15:28 -04002668 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002669 main.log.error( self.name + ": EOF exception found" )
2670 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002671 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002672 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002673 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002674 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002675
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002676 def checkFlowCount( self, min=0, timeout=60 ):
Flavio Castroa1286fe2016-07-25 14:48:51 -07002677 count = self.getTotalFlowsNum( timeout=timeout )
Jon Halle0f0b342017-04-18 11:43:47 -07002678 count = int( count ) if count else 0
steven30801eccfe212019-01-24 13:00:42 +08002679 main.log.debug( "found {} flows".format( count ) )
Jon Halle0f0b342017-04-18 11:43:47 -07002680 return count if ( count > min ) else False
GlennRCed771242016-01-13 17:02:47 -08002681
Jon Halle0f0b342017-04-18 11:43:47 -07002682 def checkFlowsState( self, isPENDING=True, timeout=60, noExit=False ):
kelvin-onlab4df89f22015-04-13 18:10:23 -07002683 """
2684 Description:
GlennRCed771242016-01-13 17:02:47 -08002685 Check the if all the current flows are in ADDED state
Jon Hallc6793552016-01-19 14:18:37 -08002686 We check PENDING_ADD, PENDING_REMOVE, REMOVED, and FAILED flows,
2687 if the count of those states is 0, which means all current flows
2688 are in ADDED state, and return main.TRUE otherwise return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002689 Optional:
GlennRCed771242016-01-13 17:02:47 -08002690 * isPENDING: whether the PENDING_ADD is also a correct status
kelvin-onlab4df89f22015-04-13 18:10:23 -07002691 Return:
2692 returnValue - Returns main.TRUE only if all flows are in
Jon Hallc6793552016-01-19 14:18:37 -08002693 ADDED state or PENDING_ADD if the isPENDING
pingping-linbab7f8a2015-09-21 17:33:36 -07002694 parameter is set true, return main.FALSE otherwise.
kelvin-onlab4df89f22015-04-13 18:10:23 -07002695 """
2696 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002697 states = [ "PENDING_ADD", "PENDING_REMOVE", "REMOVED", "FAILED" ]
GlennRCed771242016-01-13 17:02:47 -08002698 checkedStates = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002699 statesCount = [ 0, 0, 0, 0 ]
GlennRCed771242016-01-13 17:02:47 -08002700 for s in states:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002701 rawFlows = self.flows( state=s, timeout = timeout )
YPZhang240842b2016-05-17 12:00:50 -07002702 if rawFlows:
2703 # if we didn't get flows or flows function return None, we should return
2704 # main.Flase
2705 checkedStates.append( json.loads( rawFlows ) )
2706 else:
2707 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002708 for i in range( len( states ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002709 for c in checkedStates[ i ]:
Jon Hallc6793552016-01-19 14:18:37 -08002710 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002711 statesCount[ i ] += int( c.get( "flowCount" ) )
Jon Hallc6793552016-01-19 14:18:37 -08002712 except TypeError:
2713 main.log.exception( "Json object not as expected" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002714 main.log.info( states[ i ] + " flows: " + str( statesCount[ i ] ) )
kelvin-onlabf2ec6e02015-05-27 14:15:28 -07002715
GlennRCed771242016-01-13 17:02:47 -08002716 # We want to count PENDING_ADD if isPENDING is true
2717 if isPENDING:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002718 if statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002719 return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002720 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002721 if statesCount[ 0 ] + statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002722 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002723 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002724 except ( TypeError, ValueError ):
2725 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawFlows ) )
kelvin-onlab4df89f22015-04-13 18:10:23 -07002726 return None
Jeremy Songster9385d412016-06-02 17:57:36 -07002727
YPZhang240842b2016-05-17 12:00:50 -07002728 except AssertionError:
2729 main.log.exception( "" )
2730 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002731 except pexpect.TIMEOUT:
2732 main.log.error( self.name + ": ONOS timeout" )
2733 return None
kelvin-onlab4df89f22015-04-13 18:10:23 -07002734 except pexpect.EOF:
2735 main.log.error( self.name + ": EOF exception found" )
2736 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002737 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002738 except Exception:
2739 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002740 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002741
GlennRCed771242016-01-13 17:02:47 -08002742 def pushTestIntents( self, ingress, egress, batchSize, offset="",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002743 options="", timeout=10, background = False, noExit=False, getResponse=False ):
kelvin8ec71442015-01-15 16:57:00 -08002744 """
andrewonlab87852b02014-11-19 18:44:19 -05002745 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002746 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05002747 a specific point-to-point intent definition
2748 Required:
GlennRCed771242016-01-13 17:02:47 -08002749 * ingress: specify source dpid
2750 * egress: specify destination dpid
2751 * batchSize: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05002752 Optional:
GlennRCed771242016-01-13 17:02:47 -08002753 * offset: the keyOffset is where the next batch of intents
2754 will be installed
YPZhangb34b7e12016-06-14 14:28:19 -07002755 * noExit: If set to True, TestON will not exit if any error when issus command
2756 * getResponse: If set to True, function will return ONOS response.
2757
GlennRCed771242016-01-13 17:02:47 -08002758 Returns: If failed to push test intents, it will returen None,
2759 if successful, return true.
2760 Timeout expection will return None,
2761 TypeError will return false
2762 other expections will exit()
kelvin8ec71442015-01-15 16:57:00 -08002763 """
andrewonlab87852b02014-11-19 18:44:19 -05002764 try:
GlennRCed771242016-01-13 17:02:47 -08002765 if background:
2766 back = "&"
andrewonlab87852b02014-11-19 18:44:19 -05002767 else:
GlennRCed771242016-01-13 17:02:47 -08002768 back = ""
2769 cmd = "push-test-intents {} {} {} {} {} {}".format( options,
Jon Hallc6793552016-01-19 14:18:37 -08002770 ingress,
2771 egress,
2772 batchSize,
2773 offset,
2774 back )
YPZhangebf9eb52016-05-12 15:20:24 -07002775 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002776 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002777 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08002778 main.log.info( response )
YPZhangb34b7e12016-06-14 14:28:19 -07002779 if getResponse:
2780 return response
2781
GlennRCed771242016-01-13 17:02:47 -08002782 # TODO: We should handle if there is failure in installation
2783 return main.TRUE
2784
Jon Hallc6793552016-01-19 14:18:37 -08002785 except AssertionError:
2786 main.log.exception( "" )
2787 return None
GlennRCed771242016-01-13 17:02:47 -08002788 except pexpect.TIMEOUT:
2789 main.log.error( self.name + ": ONOS timeout" )
Jon Halld4d4b372015-01-28 16:02:41 -08002790 return None
andrewonlab87852b02014-11-19 18:44:19 -05002791 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002792 main.log.error( self.name + ": EOF exception found" )
2793 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002794 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002795 except TypeError:
2796 main.log.exception( self.name + ": Object not as expected" )
Jon Hallc6793552016-01-19 14:18:37 -08002797 return None
Jon Hallfebb1c72015-03-05 13:30:09 -08002798 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002799 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002800 main.cleanAndExit()
andrewonlab87852b02014-11-19 18:44:19 -05002801
YPZhangebf9eb52016-05-12 15:20:24 -07002802 def getTotalFlowsNum( self, timeout=60, noExit=False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002803 """
2804 Description:
YPZhangf6f14a02016-01-28 15:17:31 -08002805 Get the number of ADDED flows.
YPZhangb5d3f832016-01-23 22:54:26 -08002806 Return:
YPZhangf6f14a02016-01-28 15:17:31 -08002807 The number of ADDED flows
YPZhang14a4aa92016-07-15 13:37:15 -07002808 Or return None if any exceptions
YPZhangb5d3f832016-01-23 22:54:26 -08002809 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002810
YPZhangb5d3f832016-01-23 22:54:26 -08002811 try:
YPZhange3109a72016-02-02 11:25:37 -08002812 # get total added flows number
YPZhang14a4aa92016-07-15 13:37:15 -07002813 cmd = "flows -c added"
2814 rawFlows = self.sendline( cmd, timeout=timeout, noExit=noExit )
2815 if rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002816 rawFlows = rawFlows.split( "\n" )
YPZhange3109a72016-02-02 11:25:37 -08002817 totalFlows = 0
YPZhang14a4aa92016-07-15 13:37:15 -07002818 for l in rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002819 totalFlows += int( l.split( "Count=" )[ 1 ] )
YPZhang14a4aa92016-07-15 13:37:15 -07002820 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002821 main.log.error( "Response not as expected!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002822 return None
2823 return totalFlows
YPZhange3109a72016-02-02 11:25:37 -08002824
You Wangd3097f72018-12-12 11:56:03 -08002825 except IndexError:
2826 main.log.exception( "{}: Object not as expected!".format( self.name ) )
2827 main.log.debug( "rawFlows: {}".format( rawFlows ) )
2828 return None
You Wangd3cb2ce2016-05-16 14:01:24 -07002829 except ( TypeError, ValueError ):
YPZhang14a4aa92016-07-15 13:37:15 -07002830 main.log.exception( "{}: Object not as expected!".format( self.name ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002831 return None
2832 except pexpect.EOF:
2833 main.log.error( self.name + ": EOF exception found" )
2834 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002835 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002836 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002837 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002838 except pexpect.TIMEOUT:
2839 main.log.error( self.name + ": ONOS timeout" )
2840 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002841 except Exception:
2842 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002843 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002844 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002845 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002846
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002847 def getTotalIntentsNum( self, timeout=60, noExit = False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002848 """
2849 Description:
2850 Get the total number of intents, include every states.
YPZhang14a4aa92016-07-15 13:37:15 -07002851 Optional:
2852 noExit - If noExit, TestON will not exit if any except.
YPZhangb5d3f832016-01-23 22:54:26 -08002853 Return:
2854 The number of intents
2855 """
2856 try:
2857 cmd = "summary -j"
YPZhang14a4aa92016-07-15 13:37:15 -07002858 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002859 if response is None:
2860 return -1
YPZhangb5d3f832016-01-23 22:54:26 -08002861 response = json.loads( response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002862 return int( response.get( "intents" ) )
You Wangd3cb2ce2016-05-16 14:01:24 -07002863 except ( TypeError, ValueError ):
2864 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002865 return None
2866 except pexpect.EOF:
2867 main.log.error( self.name + ": EOF exception found" )
2868 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002869 if noExit:
2870 return -1
2871 else:
Devin Lim44075962017-08-11 10:56:37 -07002872 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002873 except Exception:
2874 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002875 if noExit:
2876 return -1
2877 else:
Devin Lim44075962017-08-11 10:56:37 -07002878 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002879
kelvin-onlabd3b64892015-01-20 13:26:24 -08002880 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002881 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002882 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002883 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002884 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002885 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002886 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002887 cmdStr = "intents-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002888 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002889 cmdStr += " -j"
2890 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002891 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002892 assert "Command not found:" not in handle, handle
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002893 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002894 except AssertionError:
2895 main.log.exception( "" )
2896 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002897 except TypeError:
2898 main.log.exception( self.name + ": Object not as expected" )
2899 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002900 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002901 main.log.error( self.name + ": EOF exception found" )
2902 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002903 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002904 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002905 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002906 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002907
kelvin-onlabd3b64892015-01-20 13:26:24 -08002908 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002909 """
2910 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04002911 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002912 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002913 """
andrewonlab867212a2014-10-22 20:13:38 -04002914 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002915 cmdStr = "topology-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002916 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002917 cmdStr += " -j"
2918 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002919 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002920 assert "Command not found:" not in handle, handle
jenkins7ead5a82015-03-13 10:28:21 -07002921 if handle:
2922 return handle
Jon Hallc6358dd2015-04-10 12:44:28 -07002923 elif jsonFormat:
Jon Hallbe379602015-03-24 13:39:32 -07002924 # Return empty json
jenkins7ead5a82015-03-13 10:28:21 -07002925 return '{}'
Jon Hallc6358dd2015-04-10 12:44:28 -07002926 else:
2927 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002928 except AssertionError:
2929 main.log.exception( "" )
2930 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002931 except TypeError:
2932 main.log.exception( self.name + ": Object not as expected" )
2933 return None
andrewonlab867212a2014-10-22 20:13:38 -04002934 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002935 main.log.error( self.name + ": EOF exception found" )
2936 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002937 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002938 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002939 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002940 main.cleanAndExit()
andrewonlab867212a2014-10-22 20:13:38 -04002941
kelvin8ec71442015-01-15 16:57:00 -08002942 # Wrapper functions ****************
2943 # Wrapper functions use existing driver
2944 # functions and extends their use case.
2945 # For example, we may use the output of
2946 # a normal driver function, and parse it
2947 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04002948
kelvin-onlabd3b64892015-01-20 13:26:24 -08002949 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002950 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002951 Description:
2952 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08002953 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002954 try:
kelvin8ec71442015-01-15 16:57:00 -08002955 # Obtain output of intents function
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002956 intentsStr = self.intents( jsonFormat=True )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07002957 if intentsStr is None:
2958 raise TypeError
Jon Hall6021e062017-01-30 11:10:06 -08002959 # Convert to a dictionary
2960 intents = json.loads( intentsStr )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002961 intentIdList = []
Jon Hall6021e062017-01-30 11:10:06 -08002962 for intent in intents:
2963 intentIdList.append( intent[ 'id' ] )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002964 return intentIdList
Jon Halld4d4b372015-01-28 16:02:41 -08002965 except TypeError:
2966 main.log.exception( self.name + ": Object not as expected" )
2967 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002968 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002969 main.log.error( self.name + ": EOF exception found" )
2970 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002971 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002972 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002973 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002974 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04002975
You Wang3c276252016-09-21 15:21:36 -07002976 def flowAddedCount( self, deviceId, core=False ):
Jon Hall30b82fa2015-03-04 17:15:43 -08002977 """
2978 Determine the number of flow rules for the given device id that are
2979 in the added state
You Wang3c276252016-09-21 15:21:36 -07002980 Params:
2981 core: if True, only return the number of core flows added
Jon Hall30b82fa2015-03-04 17:15:43 -08002982 """
2983 try:
You Wang3c276252016-09-21 15:21:36 -07002984 if core:
2985 cmdStr = "flows any " + str( deviceId ) + " | " +\
2986 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
2987 else:
2988 cmdStr = "flows any " + str( deviceId ) + " | " +\
2989 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08002990 handle = self.lineCount( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002991 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002992 assert "Command not found:" not in handle, handle
Jon Hall30b82fa2015-03-04 17:15:43 -08002993 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002994 except AssertionError:
2995 main.log.exception( "" )
2996 return None
Jon Hall30b82fa2015-03-04 17:15:43 -08002997 except pexpect.EOF:
2998 main.log.error( self.name + ": EOF exception found" )
2999 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003000 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003001 except Exception:
Jon Hall30b82fa2015-03-04 17:15:43 -08003002 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003003 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -04003004
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003005 def groupAddedCount( self, deviceId, core=False ):
3006 """
3007 Determine the number of group rules for the given device id that are
3008 in the added state
3009 Params:
3010 core: if True, only return the number of core groups added
3011 """
3012 try:
3013 if core:
3014 cmdStr = "groups any " + str( deviceId ) + " | " +\
3015 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
3016 else:
3017 cmdStr = "groups any " + str( deviceId ) + " | " +\
3018 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003019 handle = self.lineCount( cmdStr )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003020 assert handle is not None, "Error in sendline"
3021 assert "Command not found:" not in handle, handle
3022 return handle
3023 except AssertionError:
3024 main.log.exception( "" )
3025 return None
3026 except pexpect.EOF:
3027 main.log.error( self.name + ": EOF exception found" )
3028 main.log.error( self.name + ": " + self.handle.before )
3029 main.cleanAndExit()
3030 except Exception:
3031 main.log.exception( self.name + ": Uncaught exception!" )
3032 main.cleanAndExit()
3033
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003034 def addStaticRoute( self, subnet, intf):
3035 """
3036 Adds a static route to onos.
3037 Params:
3038 subnet: The subnet reaching through this route
3039 intf: The interface this route is reachable through
3040 """
3041 try:
3042 cmdStr = "route-add " + subnet + " " + intf
3043 handle = self.sendline( cmdStr )
3044 assert handle is not None, "Error in sendline"
3045 assert "Command not found:" not in handle, handle
3046 return handle
3047 except AssertionError:
3048 main.log.exception( "" )
3049 return None
3050 except pexpect.EOF:
3051 main.log.error( self.name + ": EOF exception found" )
3052 main.log.error( self.name + ": " + self.handle.before )
3053 main.cleanAndExit()
3054 except Exception:
3055 main.log.exception( self.name + ": Uncaught exception!" )
3056 main.cleanAndExit()
3057
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003058 def checkGroupAddedCount( self, deviceId, expectedGroupCount=0, core=False, comparison=0):
3059 """
3060 Description:
3061 Check whether the number of groups for the given device id that
3062 are in ADDED state is bigger than minGroupCount.
3063 Required:
3064 * deviceId: device id to check the number of added group rules
3065 Optional:
3066 * minGroupCount: the number of groups to compare
3067 * core: if True, only check the number of core groups added
3068 * comparison: if 0, compare with greater than minFlowCount
3069 * if 1, compare with equal to minFlowCount
3070 Return:
3071 Returns the number of groups if it is bigger than minGroupCount,
3072 returns main.FALSE otherwise.
3073 """
3074 count = self.groupAddedCount( deviceId, core )
3075 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003076 main.log.debug( "found {} groups".format( count ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003077 return count if ((count > expectedGroupCount) if (comparison == 0) else (count == expectedGroupCount)) else main.FALSE
3078
You Wangc02f3be2018-05-18 12:14:23 -07003079 def getGroups( self, deviceId, groupType="any" ):
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003080 """
3081 Retrieve groups from a specific device.
You Wangc02f3be2018-05-18 12:14:23 -07003082 deviceId: Id of the device from which we retrieve groups
3083 groupType: Type of group
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003084 """
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003085 try:
You Wangc02f3be2018-05-18 12:14:23 -07003086 groupCmd = "groups -t {0} any {1}".format( groupType, deviceId )
3087 handle = self.sendline( groupCmd )
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003088 assert handle is not None, "Error in sendline"
3089 assert "Command not found:" not in handle, handle
3090 return handle
3091 except AssertionError:
3092 main.log.exception( "" )
3093 return None
3094 except TypeError:
3095 main.log.exception( self.name + ": Object not as expected" )
3096 return None
3097 except pexpect.EOF:
3098 main.log.error( self.name + ": EOF exception found" )
3099 main.log.error( self.name + ": " + self.handle.before )
3100 main.cleanAndExit()
3101 except Exception:
3102 main.log.exception( self.name + ": Uncaught exception!" )
3103 main.cleanAndExit()
3104
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003105 def checkFlowAddedCount( self, deviceId, expectedFlowCount=0, core=False, comparison=0):
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003106 """
3107 Description:
3108 Check whether the number of flow rules for the given device id that
3109 are in ADDED state is bigger than minFlowCount.
3110 Required:
3111 * deviceId: device id to check the number of added flow rules
3112 Optional:
3113 * minFlowCount: the number of flow rules to compare
3114 * core: if True, only check the number of core flows added
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003115 * comparison: if 0, compare with greater than minFlowCount
3116 * if 1, compare with equal to minFlowCount
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003117 Return:
3118 Returns the number of flow rules if it is bigger than minFlowCount,
3119 returns main.FALSE otherwise.
3120 """
3121 count = self.flowAddedCount( deviceId, core )
3122 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003123 main.log.debug( "found {} flows".format( count ) )
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003124 return count if ((count > expectedFlowCount) if (comparison == 0) else (count == expectedFlowCount)) else main.FALSE
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003125
kelvin-onlabd3b64892015-01-20 13:26:24 -08003126 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003127 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003128 Use 'devices' function to obtain list of all devices
3129 and parse the result to obtain a list of all device
3130 id's. Returns this list. Returns empty list if no
3131 devices exist
kelvin8ec71442015-01-15 16:57:00 -08003132 List is ordered sequentially
3133
andrewonlab3e15ead2014-10-15 14:21:34 -04003134 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08003135 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04003136 the ids. By obtaining the list of device ids on the fly,
3137 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08003138 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003139 try:
kelvin8ec71442015-01-15 16:57:00 -08003140 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08003141 devicesStr = self.devices( jsonFormat=False )
3142 idList = []
kelvin8ec71442015-01-15 16:57:00 -08003143
kelvin-onlabd3b64892015-01-20 13:26:24 -08003144 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08003145 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003146 return idList
kelvin8ec71442015-01-15 16:57:00 -08003147
3148 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08003149 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08003150 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08003151 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08003152 # Split list further into arguments before and after string
3153 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08003154 # append to idList
3155 for arg in tempList:
3156 idList.append( arg.split( "id=" )[ 1 ] )
3157 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04003158
Jon Halld4d4b372015-01-28 16:02:41 -08003159 except TypeError:
3160 main.log.exception( self.name + ": Object not as expected" )
3161 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04003162 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003163 main.log.error( self.name + ": EOF exception found" )
3164 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003165 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003166 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003167 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003168 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003169
kelvin-onlabd3b64892015-01-20 13:26:24 -08003170 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003171 """
andrewonlab7c211572014-10-15 16:45:20 -04003172 Uses 'nodes' function to obtain list of all nodes
3173 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08003174 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04003175 Returns:
3176 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08003177 """
andrewonlab7c211572014-10-15 16:45:20 -04003178 try:
Jon Hall5aa168b2015-03-23 14:23:09 -07003179 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003180 idList = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003181 # Sample nodesStr output
Jon Hallbd182782016-03-28 16:42:22 -07003182 # id=local, address=127.0.0.1:9876, state=READY *
kelvin-onlabd3b64892015-01-20 13:26:24 -08003183 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08003184 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003185 return idList
Jon Hall5aa168b2015-03-23 14:23:09 -07003186 nodesJson = json.loads( nodesStr )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003187 idList = [ node.get( 'id' ) for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08003188 return idList
Jon Hallc6793552016-01-19 14:18:37 -08003189 except ( TypeError, ValueError ):
3190 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, nodesStr ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003191 return None
andrewonlab7c211572014-10-15 16:45:20 -04003192 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003193 main.log.error( self.name + ": EOF exception found" )
3194 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003195 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003196 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003197 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003198 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003199
kelvin-onlabd3b64892015-01-20 13:26:24 -08003200 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08003201 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003202 Return the first device from the devices api whose 'id' contains 'dpid'
3203 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08003204 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003205 try:
kelvin8ec71442015-01-15 16:57:00 -08003206 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04003207 return None
3208 else:
kelvin8ec71442015-01-15 16:57:00 -08003209 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003210 rawDevices = self.devices()
3211 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08003212 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08003213 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08003214 # print "%s in %s?" % ( dpid, device[ 'id' ] )
3215 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04003216 return device
3217 return None
Jon Hallc6793552016-01-19 14:18:37 -08003218 except ( TypeError, ValueError ):
3219 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawDevices ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003220 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04003221 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003222 main.log.error( self.name + ": EOF exception found" )
3223 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003224 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003225 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003226 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003227 main.cleanAndExit()
Jon Halla91c4dc2014-10-22 12:57:04 -04003228
You Wang24139872016-05-03 11:48:47 -07003229 def getTopology( self, topologyOutput ):
3230 """
3231 Definition:
3232 Loads a json topology output
3233 Return:
3234 topology = current ONOS topology
3235 """
3236 import json
3237 try:
3238 # either onos:topology or 'topology' will work in CLI
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003239 topology = json.loads( topologyOutput )
Jeremy Songsterbc2d8ac2016-05-04 11:25:42 -07003240 main.log.debug( topology )
You Wang24139872016-05-03 11:48:47 -07003241 return topology
You Wangd3cb2ce2016-05-16 14:01:24 -07003242 except ( TypeError, ValueError ):
3243 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, topologyOutput ) )
3244 return None
You Wang24139872016-05-03 11:48:47 -07003245 except pexpect.EOF:
3246 main.log.error( self.name + ": EOF exception found" )
3247 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003248 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003249 except Exception:
3250 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003251 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003252
Pier6a0c4de2018-03-18 16:01:30 -07003253 def checkStatus( self, numoswitch, numolink = -1, numoctrl = -1, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08003254 """
Jon Hallefbd9792015-03-05 16:11:36 -08003255 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08003256 supplied values. By default this will report to main.log, but the
You Wang24139872016-05-03 11:48:47 -07003257 log level can be specific.
kelvin8ec71442015-01-15 16:57:00 -08003258
Flavio Castro82ee2f62016-06-07 15:04:12 -07003259 Params: numoswitch = expected number of switches
Jon Hallefbd9792015-03-05 16:11:36 -08003260 numolink = expected number of links
Flavio Castro82ee2f62016-06-07 15:04:12 -07003261 numoctrl = expected number of controllers
You Wang24139872016-05-03 11:48:47 -07003262 logLevel = level to log to.
3263 Currently accepts 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04003264
Jon Hallefbd9792015-03-05 16:11:36 -08003265 Returns: main.TRUE if the number of switches and links are correct,
3266 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04003267 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08003268 """
Flavio Castro82ee2f62016-06-07 15:04:12 -07003269 import json
Jon Hall42db6dc2014-10-24 19:03:48 -04003270 try:
You Wang13310252016-07-31 10:56:14 -07003271 summary = self.summary()
3272 summary = json.loads( summary )
Flavio Castrof5b3f872016-06-23 17:52:31 -07003273 except ( TypeError, ValueError ):
3274 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summary ) )
3275 return main.ERROR
3276 try:
3277 topology = self.getTopology( self.topology() )
Jon Halle0f0b342017-04-18 11:43:47 -07003278 if topology == {} or topology is None or summary == {} or summary is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04003279 return main.ERROR
3280 output = ""
kelvin8ec71442015-01-15 16:57:00 -08003281 # Is the number of switches is what we expected
3282 devices = topology.get( 'devices', False )
3283 links = topology.get( 'links', False )
Flavio Castro82ee2f62016-06-07 15:04:12 -07003284 nodes = summary.get( 'nodes', False )
3285 if devices is False or links is False or nodes is False:
Jon Hall42db6dc2014-10-24 19:03:48 -04003286 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08003287 switchCheck = ( int( devices ) == int( numoswitch ) )
kelvin8ec71442015-01-15 16:57:00 -08003288 # Is the number of links is what we expected
Pier6a0c4de2018-03-18 16:01:30 -07003289 linkCheck = ( int( links ) == int( numolink ) ) or int( numolink ) == -1
Flavio Castro82ee2f62016-06-07 15:04:12 -07003290 nodeCheck = ( int( nodes ) == int( numoctrl ) ) or int( numoctrl ) == -1
3291 if switchCheck and linkCheck and nodeCheck:
kelvin8ec71442015-01-15 16:57:00 -08003292 # We expected the correct numbers
You Wang24139872016-05-03 11:48:47 -07003293 output = output + "The number of links and switches match "\
3294 + "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003295 result = main.TRUE
3296 else:
You Wang24139872016-05-03 11:48:47 -07003297 output = output + \
3298 "The number of links and switches does not match " + \
3299 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003300 result = main.FALSE
You Wang24139872016-05-03 11:48:47 -07003301 output = output + "\n ONOS sees %i devices" % int( devices )
3302 output = output + " (%i expected) " % int( numoswitch )
Pier6a0c4de2018-03-18 16:01:30 -07003303 if int( numolink ) > 0:
3304 output = output + "and %i links " % int( links )
3305 output = output + "(%i expected)" % int( numolink )
YPZhangd7e4b6e2016-06-17 16:07:55 -07003306 if int( numoctrl ) > 0:
Flavio Castro82ee2f62016-06-07 15:04:12 -07003307 output = output + "and %i controllers " % int( nodes )
3308 output = output + "(%i expected)" % int( numoctrl )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003309 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08003310 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003311 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08003312 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04003313 else:
You Wang24139872016-05-03 11:48:47 -07003314 main.log.info( output )
kelvin8ec71442015-01-15 16:57:00 -08003315 return result
Jon Hall42db6dc2014-10-24 19:03:48 -04003316 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003317 main.log.error( self.name + ": EOF exception found" )
3318 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003319 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003320 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003321 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003322 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003323
kelvin-onlabd3b64892015-01-20 13:26:24 -08003324 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08003325 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003326 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08003327 deviceId must be the id of a device as seen in the onos devices command
3328 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04003329 role must be either master, standby, or none
3330
Jon Halle3f39ff2015-01-13 11:50:53 -08003331 Returns:
3332 main.TRUE or main.FALSE based on argument verification and
3333 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003334 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003335 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003336 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04003337 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08003338 cmdStr = "device-role " +\
3339 str( deviceId ) + " " +\
3340 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003341 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003342 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003343 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003344 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08003345 if re.search( "Error", handle ):
3346 # end color output to escape any colours
3347 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08003348 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003349 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08003350 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08003351 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04003352 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003353 main.log.error( "Invalid 'role' given to device_role(). " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003354 "Value was '" + str( role ) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04003355 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003356 except AssertionError:
3357 main.log.exception( "" )
3358 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003359 except TypeError:
3360 main.log.exception( self.name + ": Object not as expected" )
3361 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04003362 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003363 main.log.error( self.name + ": EOF exception found" )
3364 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003365 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003366 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003367 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003368 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003369
kelvin-onlabd3b64892015-01-20 13:26:24 -08003370 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08003371 """
Jon Hall0dd09952018-04-19 09:59:11 -07003372 Lists all topology clusters
Jon Hallffb386d2014-11-21 13:43:38 -08003373 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003374 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08003375 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08003376 try:
Jon Hall0dd09952018-04-19 09:59:11 -07003377 cmdStr = "topo-clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003378 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003379 cmdStr += " -j"
3380 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003381 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003382 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07003383 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003384 except AssertionError:
3385 main.log.exception( "" )
3386 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003387 except TypeError:
3388 main.log.exception( self.name + ": Object not as expected" )
3389 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08003390 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003391 main.log.error( self.name + ": EOF exception found" )
3392 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003393 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003394 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003395 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003396 main.cleanAndExit()
Jon Hall73cf9cc2014-11-20 22:28:38 -08003397
kelvin-onlabd3b64892015-01-20 13:26:24 -08003398 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003399 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003400 CLI command to get the current leader for the Election test application
3401 NOTE: Requires installation of the onos-app-election feature
3402 Returns: Node IP of the leader if one exists
3403 None if none exists
3404 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003405 """
Jon Hall94fd0472014-12-08 11:52:42 -08003406 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003407 cmdStr = "election-test-leader"
3408 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003409 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003410 assert "Command not found:" not in response, response
Jon Halle3f39ff2015-01-13 11:50:53 -08003411 # Leader
3412 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003413 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08003414 nodeSearch = re.search( leaderPattern, response )
3415 if nodeSearch:
3416 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08003417 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003418 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08003419 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08003420 # no leader
3421 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003422 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003423 nullSearch = re.search( nullPattern, response )
3424 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08003425 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003426 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08003427 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08003428 # error
Jon Hall0e240372018-05-02 11:21:57 -07003429 main.log.error( self.name + ": Error in electionTestLeader on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003430 ": " + "unexpected response" )
3431 main.log.error( repr( response ) )
3432 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003433 except AssertionError:
3434 main.log.exception( "" )
3435 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003436 except TypeError:
3437 main.log.exception( self.name + ": Object not as expected" )
3438 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003439 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003440 main.log.error( self.name + ": EOF exception found" )
3441 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003442 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003443 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003444 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003445 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003446
kelvin-onlabd3b64892015-01-20 13:26:24 -08003447 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003448 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003449 CLI command to run for leadership of the Election test application.
3450 NOTE: Requires installation of the onos-app-election feature
3451 Returns: Main.TRUE on success
3452 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003453 """
Jon Hall94fd0472014-12-08 11:52:42 -08003454 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003455 cmdStr = "election-test-run"
3456 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003457 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003458 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003459 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003460 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003461 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003462 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08003463 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08003464 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003465 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003466 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003467 # error
Jon Hall0e240372018-05-02 11:21:57 -07003468 main.log.error( self.name + ": Error in electionTestRun on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003469 ": " + "unexpected response" )
3470 main.log.error( repr( response ) )
3471 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003472 except AssertionError:
3473 main.log.exception( "" )
3474 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003475 except TypeError:
3476 main.log.exception( self.name + ": Object not as expected" )
3477 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003478 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003479 main.log.error( self.name + ": EOF exception found" )
3480 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003481 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003482 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003483 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003484 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003485
kelvin-onlabd3b64892015-01-20 13:26:24 -08003486 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08003487 """
Jon Hall94fd0472014-12-08 11:52:42 -08003488 * CLI command to withdraw the local node from leadership election for
3489 * the Election test application.
3490 #NOTE: Requires installation of the onos-app-election feature
3491 Returns: Main.TRUE on success
3492 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08003493 """
Jon Hall94fd0472014-12-08 11:52:42 -08003494 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003495 cmdStr = "election-test-withdraw"
3496 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003497 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003498 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003499 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003500 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003501 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003502 if re.search( successPattern, response ):
3503 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003504 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003505 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003506 # error
Jon Hall0e240372018-05-02 11:21:57 -07003507 main.log.error( self.name + ": Error in electionTestWithdraw on " +
Jon Hall97cf84a2016-06-20 13:35:58 -07003508 self.name + ": " + "unexpected response" )
3509 main.log.error( repr( response ) )
3510 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003511 except AssertionError:
3512 main.log.exception( "" )
3513 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003514 except TypeError:
3515 main.log.exception( self.name + ": Object not as expected" )
3516 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003517 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003518 main.log.error( self.name + ": EOF exception found" )
3519 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003520 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003521 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003522 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003523 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003524
kelvin8ec71442015-01-15 16:57:00 -08003525 def getDevicePortsEnabledCount( self, dpid ):
3526 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003527 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003528 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003529 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003530 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003531 cmdStr = "onos:ports -e " + dpid + " | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003532 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003533 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003534 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003535 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003536 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003537 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003538 return output
Jon Hallc6793552016-01-19 14:18:37 -08003539 except AssertionError:
3540 main.log.exception( "" )
3541 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003542 except TypeError:
3543 main.log.exception( self.name + ": Object not as expected" )
3544 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003545 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003546 main.log.error( self.name + ": EOF exception found" )
3547 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003548 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003549 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003550 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003551 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003552
kelvin8ec71442015-01-15 16:57:00 -08003553 def getDeviceLinksActiveCount( self, dpid ):
3554 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003555 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003556 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003557 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003558 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003559 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003560 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003561 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003562 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003563 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003564 main.log.error( self.name + ": Error in getting ports " )
kelvin-onlab898a6c62015-01-16 14:13:53 -08003565 return ( output, "Error " )
Jon Halla495f562016-05-16 18:03:26 -07003566 return output
Jon Hallc6793552016-01-19 14:18:37 -08003567 except AssertionError:
3568 main.log.exception( "" )
3569 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003570 except TypeError:
3571 main.log.exception( self.name + ": Object not as expected" )
3572 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003573 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003574 main.log.error( self.name + ": EOF exception found" )
3575 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003576 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003577 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003578 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003579 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003580
kelvin8ec71442015-01-15 16:57:00 -08003581 def getAllIntentIds( self ):
3582 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003583 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08003584 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003585 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003586 cmdStr = "onos:intents | grep id="
3587 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003588 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003589 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003590 if re.search( "Error", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003591 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003592 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003593 return output
Jon Hallc6793552016-01-19 14:18:37 -08003594 except AssertionError:
3595 main.log.exception( "" )
3596 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003597 except TypeError:
3598 main.log.exception( self.name + ": Object not as expected" )
3599 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003600 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003601 main.log.error( self.name + ": EOF exception found" )
3602 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003603 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003604 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003605 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003606 main.cleanAndExit()
Jon Halld4d4b372015-01-28 16:02:41 -08003607
Jon Hall73509952015-02-24 16:42:56 -08003608 def intentSummary( self ):
3609 """
Jon Hallefbd9792015-03-05 16:11:36 -08003610 Returns a dictionary containing the current intent states and the count
Jon Hall73509952015-02-24 16:42:56 -08003611 """
3612 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003613 intents = self.intents( )
Jon Hall08f61bc2015-04-13 16:00:30 -07003614 states = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003615 for intent in json.loads( intents ):
Jon Hall08f61bc2015-04-13 16:00:30 -07003616 states.append( intent.get( 'state', None ) )
3617 out = [ ( i, states.count( i ) ) for i in set( states ) ]
Jon Hall63604932015-02-26 17:09:50 -08003618 main.log.info( dict( out ) )
Jon Hall73509952015-02-24 16:42:56 -08003619 return dict( out )
Jon Hallc6793552016-01-19 14:18:37 -08003620 except ( TypeError, ValueError ):
3621 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intents ) )
Jon Hall73509952015-02-24 16:42:56 -08003622 return None
3623 except pexpect.EOF:
3624 main.log.error( self.name + ": EOF exception found" )
3625 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003626 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003627 except Exception:
Jon Hall73509952015-02-24 16:42:56 -08003628 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003629 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003630
Jon Hall61282e32015-03-19 11:34:11 -07003631 def leaders( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003632 """
3633 Returns the output of the leaders command.
Jon Hall61282e32015-03-19 11:34:11 -07003634 Optional argument:
3635 * jsonFormat - boolean indicating if you want output in json
Jon Hall63604932015-02-26 17:09:50 -08003636 """
Jon Hall63604932015-02-26 17:09:50 -08003637 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003638 cmdStr = "onos:leaders"
Jon Hall61282e32015-03-19 11:34:11 -07003639 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003640 cmdStr += " -j"
3641 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003642 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003643 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003644 return output
Jon Hallc6793552016-01-19 14:18:37 -08003645 except AssertionError:
3646 main.log.exception( "" )
3647 return None
Jon Hall63604932015-02-26 17:09:50 -08003648 except TypeError:
3649 main.log.exception( self.name + ": Object not as expected" )
3650 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003651 except pexpect.EOF:
3652 main.log.error( self.name + ": EOF exception found" )
3653 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003654 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003655 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003656 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003657 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003658
acsmarsa4a4d1e2015-07-10 16:01:24 -07003659 def leaderCandidates( self, jsonFormat=True ):
3660 """
3661 Returns the output of the leaders -c command.
3662 Optional argument:
3663 * jsonFormat - boolean indicating if you want output in json
3664 """
3665 try:
3666 cmdStr = "onos:leaders -c"
3667 if jsonFormat:
3668 cmdStr += " -j"
3669 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003670 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003671 assert "Command not found:" not in output, output
acsmarsa4a4d1e2015-07-10 16:01:24 -07003672 return output
Jon Hallc6793552016-01-19 14:18:37 -08003673 except AssertionError:
3674 main.log.exception( "" )
3675 return None
acsmarsa4a4d1e2015-07-10 16:01:24 -07003676 except TypeError:
3677 main.log.exception( self.name + ": Object not as expected" )
3678 return None
3679 except pexpect.EOF:
3680 main.log.error( self.name + ": EOF exception found" )
3681 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003682 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003683 except Exception:
3684 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003685 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003686
Jon Hallc6793552016-01-19 14:18:37 -08003687 def specificLeaderCandidate( self, topic ):
acsmarsa4a4d1e2015-07-10 16:01:24 -07003688 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003689 Returns a list in format [leader,candidate1,candidate2,...] for a given
acsmarsa4a4d1e2015-07-10 16:01:24 -07003690 topic parameter and an empty list if the topic doesn't exist
3691 If no leader is elected leader in the returned list will be "none"
3692 Returns None if there is a type error processing the json object
3693 """
3694 try:
Jon Hall6e709752016-02-01 13:38:46 -08003695 cmdStr = "onos:leaders -j"
Jon Hallc6793552016-01-19 14:18:37 -08003696 rawOutput = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003697 assert rawOutput is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003698 assert "Command not found:" not in rawOutput, rawOutput
3699 output = json.loads( rawOutput )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003700 results = []
3701 for dict in output:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003702 if dict[ "topic" ] == topic:
3703 leader = dict[ "leader" ]
3704 candidates = re.split( ", ", dict[ "candidates" ][ 1:-1 ] )
Jon Hallc6793552016-01-19 14:18:37 -08003705 results.append( leader )
3706 results.extend( candidates )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003707 return results
Jon Hallc6793552016-01-19 14:18:37 -08003708 except AssertionError:
3709 main.log.exception( "" )
3710 return None
3711 except ( TypeError, ValueError ):
3712 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawOutput ) )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003713 return None
3714 except pexpect.EOF:
3715 main.log.error( self.name + ": EOF exception found" )
3716 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003717 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003718 except Exception:
3719 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003720 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003721
Jon Hall61282e32015-03-19 11:34:11 -07003722 def pendingMap( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003723 """
3724 Returns the output of the intent Pending map.
3725 """
Jon Hall63604932015-02-26 17:09:50 -08003726 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003727 cmdStr = "onos:intents -p"
Jon Hall61282e32015-03-19 11:34:11 -07003728 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003729 cmdStr += " -j"
3730 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003731 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003732 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003733 return output
Jon Hallc6793552016-01-19 14:18:37 -08003734 except AssertionError:
3735 main.log.exception( "" )
3736 return None
Jon Hall63604932015-02-26 17:09:50 -08003737 except TypeError:
3738 main.log.exception( self.name + ": Object not as expected" )
3739 return None
3740 except pexpect.EOF:
3741 main.log.error( self.name + ": EOF exception found" )
3742 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003743 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003744 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003745 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003746 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003747
Jon Hall2c8959e2016-12-16 12:17:34 -08003748 def partitions( self, candidates=False, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003749 """
3750 Returns the output of the raft partitions command for ONOS.
3751 """
Jon Hall61282e32015-03-19 11:34:11 -07003752 # Sample JSON
3753 # {
3754 # "leader": "tcp://10.128.30.11:7238",
3755 # "members": [
3756 # "tcp://10.128.30.11:7238",
3757 # "tcp://10.128.30.17:7238",
3758 # "tcp://10.128.30.13:7238",
3759 # ],
3760 # "name": "p1",
3761 # "term": 3
3762 # },
Jon Hall63604932015-02-26 17:09:50 -08003763 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003764 cmdStr = "onos:partitions"
Jon Hall2c8959e2016-12-16 12:17:34 -08003765 if candidates:
3766 cmdStr += " -c"
Jon Hall61282e32015-03-19 11:34:11 -07003767 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003768 cmdStr += " -j"
3769 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003770 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003771 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003772 return output
Jon Hallc6793552016-01-19 14:18:37 -08003773 except AssertionError:
3774 main.log.exception( "" )
3775 return None
Jon Hall63604932015-02-26 17:09:50 -08003776 except TypeError:
3777 main.log.exception( self.name + ": Object not as expected" )
3778 return None
3779 except pexpect.EOF:
3780 main.log.error( self.name + ": EOF exception found" )
3781 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003782 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003783 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003784 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003785 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003786
Jon Halle9f909e2016-09-23 10:43:12 -07003787 def apps( self, summary=False, active=False, jsonFormat=True ):
Jon Hallbe379602015-03-24 13:39:32 -07003788 """
3789 Returns the output of the apps command for ONOS. This command lists
3790 information about installed ONOS applications
3791 """
3792 # Sample JSON object
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003793 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
Jon Hallbe379602015-03-24 13:39:32 -07003794 # "description":"ONOS OpenFlow protocol southbound providers",
3795 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003796 # "features":"[onos-openflow]","state":"ACTIVE"}]
Jon Hallbe379602015-03-24 13:39:32 -07003797 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003798 cmdStr = "onos:apps"
Jon Hallf03ae762019-01-22 13:25:27 -08003799 expectJson = False
Jon Halle9f909e2016-09-23 10:43:12 -07003800 if summary:
3801 cmdStr += " -s"
3802 if active:
3803 cmdStr += " -a"
Jon Hallbe379602015-03-24 13:39:32 -07003804 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003805 cmdStr += " -j"
Jon Hallf03ae762019-01-22 13:25:27 -08003806 expectJson = True
3807 output = self.sendline( cmdStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07003808 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003809 assert "Command not found:" not in output, output
3810 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003811 return output
Jon Hallbe379602015-03-24 13:39:32 -07003812 # FIXME: look at specific exceptions/Errors
3813 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07003814 main.log.exception( self.name + ": Error in processing onos:app command." )
Jon Hallbe379602015-03-24 13:39:32 -07003815 return None
3816 except TypeError:
3817 main.log.exception( self.name + ": Object not as expected" )
3818 return None
3819 except pexpect.EOF:
3820 main.log.error( self.name + ": EOF exception found" )
3821 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003822 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003823 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003824 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003825 main.cleanAndExit()
Jon Hallbe379602015-03-24 13:39:32 -07003826
You Wangcdc51fe2018-08-12 17:14:56 -07003827 def appStatus( self, appName ):
Jon Hall146f1522015-03-24 15:33:24 -07003828 """
3829 Uses the onos:apps cli command to return the status of an application.
3830 Returns:
3831 "ACTIVE" - If app is installed and activated
3832 "INSTALLED" - If app is installed and deactivated
3833 "UNINSTALLED" - If app is not installed
3834 None - on error
3835 """
Jon Hall146f1522015-03-24 15:33:24 -07003836 try:
3837 if not isinstance( appName, types.StringType ):
3838 main.log.error( self.name + ".appStatus(): appName must be" +
3839 " a string" )
3840 return None
3841 output = self.apps( jsonFormat=True )
3842 appsJson = json.loads( output )
3843 state = None
3844 for app in appsJson:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003845 if appName == app.get( 'name' ):
3846 state = app.get( 'state' )
Jon Hall146f1522015-03-24 15:33:24 -07003847 break
3848 if state == "ACTIVE" or state == "INSTALLED":
3849 return state
3850 elif state is None:
You Wang0d9f2c02018-08-10 14:56:32 -07003851 main.log.warn( "{} app not found".format( appName ) )
Jon Hall146f1522015-03-24 15:33:24 -07003852 return "UNINSTALLED"
3853 elif state:
3854 main.log.error( "Unexpected state from 'onos:apps': " +
3855 str( state ) )
3856 return state
Jon Hallc6793552016-01-19 14:18:37 -08003857 except ( TypeError, ValueError ):
3858 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003859 return None
3860 except pexpect.EOF:
3861 main.log.error( self.name + ": EOF exception found" )
3862 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003863 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003864 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003865 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003866 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003867
Jon Hallbe379602015-03-24 13:39:32 -07003868 def app( self, appName, option ):
3869 """
3870 Interacts with the app command for ONOS. This command manages
3871 application inventory.
3872 """
Jon Hallbe379602015-03-24 13:39:32 -07003873 try:
Jon Hallbd16b922015-03-26 17:53:15 -07003874 # Validate argument types
3875 valid = True
3876 if not isinstance( appName, types.StringType ):
3877 main.log.error( self.name + ".app(): appName must be a " +
3878 "string" )
3879 valid = False
3880 if not isinstance( option, types.StringType ):
3881 main.log.error( self.name + ".app(): option must be a string" )
3882 valid = False
3883 if not valid:
3884 return main.FALSE
3885 # Validate Option
3886 option = option.lower()
3887 # NOTE: Install may become a valid option
3888 if option == "activate":
3889 pass
3890 elif option == "deactivate":
3891 pass
3892 elif option == "uninstall":
3893 pass
3894 else:
3895 # Invalid option
3896 main.log.error( "The ONOS app command argument only takes " +
3897 "the values: (activate|deactivate|uninstall)" +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003898 "; was given '" + option + "'" )
Jon Hallbd16b922015-03-26 17:53:15 -07003899 return main.FALSE
Jon Hall146f1522015-03-24 15:33:24 -07003900 cmdStr = "onos:app " + option + " " + appName
Jon Hallbe379602015-03-24 13:39:32 -07003901 output = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003902 assert output is not None, "Error in sendline"
3903 assert "Command not found:" not in output, output
Jon Hallbe379602015-03-24 13:39:32 -07003904 if "Error executing command" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003905 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hallbe379602015-03-24 13:39:32 -07003906 str( output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003907 return main.FALSE
Jon Hallbe379602015-03-24 13:39:32 -07003908 elif "No such application" in output:
3909 main.log.error( "The application '" + appName +
3910 "' is not installed in ONOS" )
Jon Hall146f1522015-03-24 15:33:24 -07003911 return main.FALSE
3912 elif "Command not found:" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003913 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hall146f1522015-03-24 15:33:24 -07003914 str( output ) )
3915 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003916 elif "Unsupported command:" in output:
3917 main.log.error( "Incorrect command given to 'app': " +
3918 str( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003919 # NOTE: we may need to add more checks here
Jon Hallbd16b922015-03-26 17:53:15 -07003920 # else: Command was successful
Jon Hall08f61bc2015-04-13 16:00:30 -07003921 # main.log.debug( "app response: " + repr( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003922 return main.TRUE
You Wangb5a55f72017-03-03 12:51:05 -08003923 except AssertionError:
3924 main.log.exception( self.name + ": AssertionError exception found" )
3925 return main.ERROR
Jon Hallbe379602015-03-24 13:39:32 -07003926 except TypeError:
3927 main.log.exception( self.name + ": Object not as expected" )
3928 return main.ERROR
3929 except pexpect.EOF:
3930 main.log.error( self.name + ": EOF exception found" )
3931 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003932 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003933 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003934 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003935 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003936
Jon Hallbd16b922015-03-26 17:53:15 -07003937 def activateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003938 """
3939 Activate an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003940 appName is the hierarchical app name, not the feature name
3941 If check is True, method will check the status of the app after the
3942 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003943 Returns main.TRUE if the command was successfully sent
3944 main.FALSE if the cli responded with an error or given
3945 incorrect input
3946 """
3947 try:
3948 if not isinstance( appName, types.StringType ):
3949 main.log.error( self.name + ".activateApp(): appName must be" +
3950 " a string" )
3951 return main.FALSE
3952 status = self.appStatus( appName )
3953 if status == "INSTALLED":
3954 response = self.app( appName, "activate" )
Jon Hallbd16b922015-03-26 17:53:15 -07003955 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003956 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07003957 status = self.appStatus( appName )
3958 if status == "ACTIVE":
3959 return main.TRUE
3960 else:
Jon Hall050e1bd2015-03-30 13:33:02 -07003961 main.log.debug( "The state of application " +
3962 appName + " is " + status )
Jon Hallbd16b922015-03-26 17:53:15 -07003963 time.sleep( 1 )
3964 return main.FALSE
3965 else: # not 'check' or command didn't succeed
3966 return response
Jon Hall146f1522015-03-24 15:33:24 -07003967 elif status == "ACTIVE":
3968 return main.TRUE
3969 elif status == "UNINSTALLED":
3970 main.log.error( self.name + ": Tried to activate the " +
3971 "application '" + appName + "' which is not " +
3972 "installed." )
3973 else:
3974 main.log.error( "Unexpected return value from appStatus: " +
3975 str( status ) )
3976 return main.ERROR
3977 except TypeError:
3978 main.log.exception( self.name + ": Object not as expected" )
3979 return main.ERROR
3980 except pexpect.EOF:
3981 main.log.error( self.name + ": EOF exception found" )
3982 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003983 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003984 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003985 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003986 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003987
Jon Hallbd16b922015-03-26 17:53:15 -07003988 def deactivateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003989 """
3990 Deactivate an app that is already activated in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003991 appName is the hierarchical app name, not the feature name
3992 If check is True, method will check the status of the app after the
3993 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003994 Returns main.TRUE if the command was successfully sent
3995 main.FALSE if the cli responded with an error or given
3996 incorrect input
3997 """
3998 try:
3999 if not isinstance( appName, types.StringType ):
4000 main.log.error( self.name + ".deactivateApp(): appName must " +
4001 "be a string" )
4002 return main.FALSE
4003 status = self.appStatus( appName )
4004 if status == "INSTALLED":
4005 return main.TRUE
4006 elif status == "ACTIVE":
4007 response = self.app( appName, "deactivate" )
Jon Hallbd16b922015-03-26 17:53:15 -07004008 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004009 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004010 status = self.appStatus( appName )
4011 if status == "INSTALLED":
4012 return main.TRUE
4013 else:
4014 time.sleep( 1 )
4015 return main.FALSE
4016 else: # not check or command didn't succeed
4017 return response
Jon Hall146f1522015-03-24 15:33:24 -07004018 elif status == "UNINSTALLED":
4019 main.log.warn( self.name + ": Tried to deactivate the " +
4020 "application '" + appName + "' which is not " +
4021 "installed." )
4022 return main.TRUE
4023 else:
4024 main.log.error( "Unexpected return value from appStatus: " +
4025 str( status ) )
4026 return main.ERROR
4027 except TypeError:
4028 main.log.exception( self.name + ": Object not as expected" )
4029 return main.ERROR
4030 except pexpect.EOF:
4031 main.log.error( self.name + ": EOF exception found" )
4032 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004033 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004034 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004035 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004036 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004037
Jon Hallbd16b922015-03-26 17:53:15 -07004038 def uninstallApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004039 """
4040 Uninstall an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004041 appName is the hierarchical app name, not the feature name
4042 If check is True, method will check the status of the app after the
4043 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004044 Returns main.TRUE if the command was successfully sent
4045 main.FALSE if the cli responded with an error or given
4046 incorrect input
4047 """
4048 # TODO: check with Thomas about the state machine for apps
4049 try:
4050 if not isinstance( appName, types.StringType ):
4051 main.log.error( self.name + ".uninstallApp(): appName must " +
4052 "be a string" )
4053 return main.FALSE
4054 status = self.appStatus( appName )
4055 if status == "INSTALLED":
4056 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004057 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004058 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004059 status = self.appStatus( appName )
4060 if status == "UNINSTALLED":
4061 return main.TRUE
4062 else:
4063 time.sleep( 1 )
4064 return main.FALSE
4065 else: # not check or command didn't succeed
4066 return response
Jon Hall146f1522015-03-24 15:33:24 -07004067 elif status == "ACTIVE":
4068 main.log.warn( self.name + ": Tried to uninstall the " +
4069 "application '" + appName + "' which is " +
4070 "currently active." )
4071 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004072 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004073 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004074 status = self.appStatus( appName )
4075 if status == "UNINSTALLED":
4076 return main.TRUE
4077 else:
4078 time.sleep( 1 )
4079 return main.FALSE
4080 else: # not check or command didn't succeed
4081 return response
Jon Hall146f1522015-03-24 15:33:24 -07004082 elif status == "UNINSTALLED":
4083 return main.TRUE
4084 else:
4085 main.log.error( "Unexpected return value from appStatus: " +
4086 str( status ) )
4087 return main.ERROR
4088 except TypeError:
4089 main.log.exception( self.name + ": Object not as expected" )
4090 return main.ERROR
4091 except pexpect.EOF:
4092 main.log.error( self.name + ": EOF exception found" )
4093 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004094 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004095 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004096 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004097 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004098
4099 def appIDs( self, jsonFormat=True ):
4100 """
4101 Show the mappings between app id and app names given by the 'app-ids'
4102 cli command
4103 """
4104 try:
4105 cmdStr = "app-ids"
4106 if jsonFormat:
4107 cmdStr += " -j"
Jon Hallc6358dd2015-04-10 12:44:28 -07004108 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004109 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004110 assert "Command not found:" not in output, output
4111 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07004112 return output
Jon Hallbd16b922015-03-26 17:53:15 -07004113 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004114 main.log.exception( self.name + ": Error in processing onos:app-ids command." )
Jon Hallbd16b922015-03-26 17:53:15 -07004115 return None
4116 except TypeError:
4117 main.log.exception( self.name + ": Object not as expected" )
4118 return None
4119 except pexpect.EOF:
4120 main.log.error( self.name + ": EOF exception found" )
4121 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004122 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004123 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004124 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004125 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004126
4127 def appToIDCheck( self ):
4128 """
4129 This method will check that each application's ID listed in 'apps' is
4130 the same as the ID listed in 'app-ids'. The check will also check that
4131 there are no duplicate IDs issued. Note that an app ID should be
4132 a globaly unique numerical identifier for app/app-like features. Once
4133 an ID is registered, the ID is never freed up so that if an app is
4134 reinstalled it will have the same ID.
4135
4136 Returns: main.TRUE if the check passes and
4137 main.FALSE if the check fails or
4138 main.ERROR if there is some error in processing the test
4139 """
4140 try:
Jon Hall0e240372018-05-02 11:21:57 -07004141 # Grab IDs
Jon Hallc6793552016-01-19 14:18:37 -08004142 rawJson = self.appIDs( jsonFormat=True )
4143 if rawJson:
4144 ids = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004145 else:
Jon Hall0e240372018-05-02 11:21:57 -07004146 main.log.error( "app-ids returned nothing: " + repr( rawJson ) )
4147 return main.FALSE
4148
4149 # Grab Apps
Jon Hallc6793552016-01-19 14:18:37 -08004150 rawJson = self.apps( jsonFormat=True )
4151 if rawJson:
4152 apps = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004153 else:
Jon Hallc6793552016-01-19 14:18:37 -08004154 main.log.error( "apps returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07004155 return main.FALSE
Jon Hall0e240372018-05-02 11:21:57 -07004156
Jon Hallbd16b922015-03-26 17:53:15 -07004157 result = main.TRUE
4158 for app in apps:
4159 appID = app.get( 'id' )
4160 if appID is None:
4161 main.log.error( "Error parsing app: " + str( app ) )
4162 result = main.FALSE
4163 appName = app.get( 'name' )
4164 if appName is None:
4165 main.log.error( "Error parsing app: " + str( app ) )
4166 result = main.FALSE
4167 # get the entry in ids that has the same appID
Jon Hall390696c2015-05-05 17:13:41 -07004168 current = filter( lambda item: item[ 'id' ] == appID, ids )
Jon Hallbd16b922015-03-26 17:53:15 -07004169 if not current: # if ids doesn't have this id
4170 result = main.FALSE
4171 main.log.error( "'app-ids' does not have the ID for " +
4172 str( appName ) + " that apps does." )
Jon Hallb9d381e2018-02-05 12:02:10 -08004173 main.log.debug( "apps command returned: " + str( app ) +
4174 "; app-ids has: " + str( ids ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004175 elif len( current ) > 1:
4176 # there is more than one app with this ID
4177 result = main.FALSE
4178 # We will log this later in the method
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004179 elif not current[ 0 ][ 'name' ] == appName:
4180 currentName = current[ 0 ][ 'name' ]
Jon Hallbd16b922015-03-26 17:53:15 -07004181 result = main.FALSE
4182 main.log.error( "'app-ids' has " + str( currentName ) +
4183 " registered under id:" + str( appID ) +
4184 " but 'apps' has " + str( appName ) )
4185 else:
4186 pass # id and name match!
Jon Hall0e240372018-05-02 11:21:57 -07004187
Jon Hallbd16b922015-03-26 17:53:15 -07004188 # now make sure that app-ids has no duplicates
4189 idsList = []
4190 namesList = []
4191 for item in ids:
4192 idsList.append( item[ 'id' ] )
4193 namesList.append( item[ 'name' ] )
4194 if len( idsList ) != len( set( idsList ) ) or\
4195 len( namesList ) != len( set( namesList ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004196 main.log.error( "'app-ids' has some duplicate entries: \n"
4197 + json.dumps( ids,
4198 sort_keys=True,
4199 indent=4,
4200 separators=( ',', ': ' ) ) )
4201 result = main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07004202 return result
Jon Hallc6793552016-01-19 14:18:37 -08004203 except ( TypeError, ValueError ):
4204 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004205 return main.ERROR
4206 except pexpect.EOF:
4207 main.log.error( self.name + ": EOF exception found" )
4208 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004209 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004210 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004211 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004212 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004213
Jon Hallfb760a02015-04-13 15:35:03 -07004214 def getCfg( self, component=None, propName=None, short=False,
4215 jsonFormat=True ):
4216 """
4217 Get configuration settings from onos cli
4218 Optional arguments:
4219 component - Optionally only list configurations for a specific
4220 component. If None, all components with configurations
4221 are displayed. Case Sensitive string.
4222 propName - If component is specified, propName option will show
4223 only this specific configuration from that component.
4224 Case Sensitive string.
4225 jsonFormat - Returns output as json. Note that this will override
4226 the short option
4227 short - Short, less verbose, version of configurations.
4228 This is overridden by the json option
4229 returns:
4230 Output from cli as a string or None on error
4231 """
4232 try:
4233 baseStr = "cfg"
4234 cmdStr = " get"
4235 componentStr = ""
4236 if component:
4237 componentStr += " " + component
4238 if propName:
4239 componentStr += " " + propName
4240 if jsonFormat:
4241 baseStr += " -j"
Jon Hall22e94ce2019-01-15 14:52:17 -08004242 expectJson = True
Jon Hallfb760a02015-04-13 15:35:03 -07004243 elif short:
4244 baseStr += " -s"
Jon Hall22e94ce2019-01-15 14:52:17 -08004245 expectJson = False
4246 output = self.sendline( baseStr + cmdStr + componentStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07004247 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004248 assert "Command not found:" not in output, output
4249 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004250 return output
4251 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004252 main.log.exception( self.name + ": Error in processing 'cfg get' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004253 return None
4254 except TypeError:
4255 main.log.exception( self.name + ": Object not as expected" )
4256 return None
4257 except pexpect.EOF:
4258 main.log.error( self.name + ": EOF exception found" )
4259 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004260 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004261 except Exception:
4262 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004263 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004264
4265 def setCfg( self, component, propName, value=None, check=True ):
4266 """
4267 Set/Unset configuration settings from ONOS cli
Jon Hall390696c2015-05-05 17:13:41 -07004268 Required arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004269 component - The case sensitive name of the component whose
4270 property is to be set
4271 propName - The case sensitive name of the property to be set/unset
Jon Hall390696c2015-05-05 17:13:41 -07004272 Optional arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004273 value - The value to set the property to. If None, will unset the
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004274 property and revert it to it's default value(if applicable)
Jon Hallfb760a02015-04-13 15:35:03 -07004275 check - Boolean, Check whether the option was successfully set this
4276 only applies when a value is given.
4277 returns:
4278 main.TRUE on success or main.FALSE on failure. If check is False,
4279 will return main.TRUE unless there is an error
4280 """
4281 try:
4282 baseStr = "cfg"
4283 cmdStr = " set " + str( component ) + " " + str( propName )
4284 if value is not None:
4285 cmdStr += " " + str( value )
4286 output = self.sendline( baseStr + cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004287 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004288 assert "Command not found:" not in output, output
4289 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004290 if value and check:
4291 results = self.getCfg( component=str( component ),
4292 propName=str( propName ),
4293 jsonFormat=True )
4294 # Check if current value is what we just set
4295 try:
4296 jsonOutput = json.loads( results )
4297 current = jsonOutput[ 'value' ]
Jon Hallc6793552016-01-19 14:18:37 -08004298 except ( TypeError, ValueError ):
Jon Hallfb760a02015-04-13 15:35:03 -07004299 main.log.exception( "Error parsing cfg output" )
4300 main.log.error( "output:" + repr( results ) )
4301 return main.FALSE
4302 if current == str( value ):
4303 return main.TRUE
4304 return main.FALSE
4305 return main.TRUE
4306 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004307 main.log.exception( self.name + ": Error in processing 'cfg set' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004308 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08004309 except ( TypeError, ValueError ):
4310 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, results ) )
Jon Hallfb760a02015-04-13 15:35:03 -07004311 return main.FALSE
4312 except pexpect.EOF:
4313 main.log.error( self.name + ": EOF exception found" )
4314 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004315 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004316 except Exception:
4317 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004318 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004319
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004320 def distPrimitivesSend( self, cmd ):
4321 """
4322 Function to handle sending cli commands for the distributed primitives test app
4323
4324 This command will catch some exceptions and retry the command on some
4325 specific store exceptions.
4326
4327 Required arguments:
4328 cmd - The command to send to the cli
4329 returns:
4330 string containing the cli output
4331 None on Error
4332 """
4333 try:
4334 output = self.sendline( cmd )
4335 try:
4336 assert output is not None, "Error in sendline"
4337 # TODO: Maybe make this less hardcoded
4338 # ConsistentMap Exceptions
4339 assert "org.onosproject.store.service" not in output
4340 # Node not leader
4341 assert "java.lang.IllegalStateException" not in output
4342 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004343 main.log.error( self.name + ": Error in processing '" + cmd + "' " +
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004344 "command: " + str( output ) )
4345 retryTime = 30 # Conservative time, given by Madan
4346 main.log.info( "Waiting " + str( retryTime ) +
4347 "seconds before retrying." )
4348 time.sleep( retryTime ) # Due to change in mastership
4349 output = self.sendline( cmd )
4350 assert output is not None, "Error in sendline"
4351 assert "Command not found:" not in output, output
4352 assert "Error executing command" not in output, output
4353 main.log.info( self.name + ": " + output )
4354 return output
4355 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004356 main.log.exception( self.name + ": Error in processing '" + cmd + "' command." )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004357 return None
4358 except TypeError:
4359 main.log.exception( self.name + ": Object not as expected" )
4360 return None
4361 except pexpect.EOF:
4362 main.log.error( self.name + ": EOF exception found" )
4363 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004364 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004365 except Exception:
4366 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004367 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004368
Jon Hall390696c2015-05-05 17:13:41 -07004369 def setTestAdd( self, setName, values ):
4370 """
4371 CLI command to add elements to a distributed set.
4372 Arguments:
4373 setName - The name of the set to add to.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004374 values - The value(s) to add to the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004375 Example usages:
4376 setTestAdd( "set1", "a b c" )
4377 setTestAdd( "set2", "1" )
4378 returns:
4379 main.TRUE on success OR
4380 main.FALSE if elements were already in the set OR
4381 main.ERROR on error
4382 """
4383 try:
4384 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004385 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004386 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
4387 negativeMatch = "\[(.*)\] was already in set " + str( setName )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004388 if re.search( positiveMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004389 return main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004390 elif re.search( negativeMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004391 return main.FALSE
4392 else:
4393 main.log.error( self.name + ": setTestAdd did not" +
4394 " match expected output" )
Jon Hall390696c2015-05-05 17:13:41 -07004395 main.log.debug( self.name + " actual: " + repr( output ) )
4396 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004397 except TypeError:
4398 main.log.exception( self.name + ": Object not as expected" )
4399 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004400 except Exception:
4401 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004402 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004403
4404 def setTestRemove( self, setName, values, clear=False, retain=False ):
4405 """
4406 CLI command to remove elements from a distributed set.
4407 Required arguments:
4408 setName - The name of the set to remove from.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004409 values - The value(s) to remove from the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004410 Optional arguments:
4411 clear - Clear all elements from the set
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004412 retain - Retain only the given values. (intersection of the
4413 original set and the given set)
Jon Hall390696c2015-05-05 17:13:41 -07004414 returns:
4415 main.TRUE on success OR
4416 main.FALSE if the set was not changed OR
4417 main.ERROR on error
4418 """
4419 try:
4420 cmdStr = "set-test-remove "
4421 if clear:
4422 cmdStr += "-c " + str( setName )
4423 elif retain:
4424 cmdStr += "-r " + str( setName ) + " " + str( values )
4425 else:
4426 cmdStr += str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004427 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004428 if clear:
4429 pattern = "Set " + str( setName ) + " cleared"
4430 if re.search( pattern, output ):
4431 return main.TRUE
4432 elif retain:
4433 positivePattern = str( setName ) + " was pruned to contain " +\
4434 "only elements of set \[(.*)\]"
4435 negativePattern = str( setName ) + " was not changed by " +\
4436 "retaining only elements of the set " +\
4437 "\[(.*)\]"
4438 if re.search( positivePattern, output ):
4439 return main.TRUE
4440 elif re.search( negativePattern, output ):
4441 return main.FALSE
4442 else:
4443 positivePattern = "\[(.*)\] was removed from the set " +\
4444 str( setName )
4445 if ( len( values.split() ) == 1 ):
4446 negativePattern = "\[(.*)\] was not in set " +\
4447 str( setName )
4448 else:
4449 negativePattern = "No element of \[(.*)\] was in set " +\
4450 str( setName )
4451 if re.search( positivePattern, output ):
4452 return main.TRUE
4453 elif re.search( negativePattern, output ):
4454 return main.FALSE
4455 main.log.error( self.name + ": setTestRemove did not" +
4456 " match expected output" )
4457 main.log.debug( self.name + " expected: " + pattern )
4458 main.log.debug( self.name + " actual: " + repr( output ) )
4459 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004460 except TypeError:
4461 main.log.exception( self.name + ": Object not as expected" )
4462 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004463 except Exception:
4464 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004465 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004466
4467 def setTestGet( self, setName, values="" ):
4468 """
4469 CLI command to get the elements in a distributed set.
4470 Required arguments:
4471 setName - The name of the set to remove from.
4472 Optional arguments:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004473 values - The value(s) to check if in the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004474 returns:
4475 main.ERROR on error OR
4476 A list of elements in the set if no optional arguments are
4477 supplied OR
4478 A tuple containing the list then:
4479 main.FALSE if the given values are not in the set OR
4480 main.TRUE if the given values are in the set OR
4481 """
4482 try:
4483 values = str( values ).strip()
4484 setName = str( setName ).strip()
4485 length = len( values.split() )
4486 containsCheck = None
4487 # Patterns to match
4488 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004489 pattern = "Items in set " + setName + ":\r\n" + setPattern
Jon Hall390696c2015-05-05 17:13:41 -07004490 containsTrue = "Set " + setName + " contains the value " + values
4491 containsFalse = "Set " + setName + " did not contain the value " +\
4492 values
4493 containsAllTrue = "Set " + setName + " contains the the subset " +\
4494 setPattern
4495 containsAllFalse = "Set " + setName + " did not contain the the" +\
4496 " subset " + setPattern
4497
4498 cmdStr = "set-test-get "
4499 cmdStr += setName + " " + values
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004500 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004501 if length == 0:
4502 match = re.search( pattern, output )
4503 else: # if given values
4504 if length == 1: # Contains output
Jon Hall54b994f2016-12-05 10:48:59 -08004505 patternTrue = pattern + "\r\n" + containsTrue
4506 patternFalse = pattern + "\r\n" + containsFalse
Jon Hall390696c2015-05-05 17:13:41 -07004507 else: # ContainsAll output
Jon Hall54b994f2016-12-05 10:48:59 -08004508 patternTrue = pattern + "\r\n" + containsAllTrue
4509 patternFalse = pattern + "\r\n" + containsAllFalse
Jon Hall390696c2015-05-05 17:13:41 -07004510 matchTrue = re.search( patternTrue, output )
4511 matchFalse = re.search( patternFalse, output )
4512 if matchTrue:
4513 containsCheck = main.TRUE
4514 match = matchTrue
4515 elif matchFalse:
4516 containsCheck = main.FALSE
4517 match = matchFalse
4518 else:
Jon Halle0f0b342017-04-18 11:43:47 -07004519 main.log.error( self.name + " setTestGet did not match " +
Jon Hall390696c2015-05-05 17:13:41 -07004520 "expected output" )
4521 main.log.debug( self.name + " expected: " + pattern )
4522 main.log.debug( self.name + " actual: " + repr( output ) )
4523 match = None
4524 if match:
4525 setMatch = match.group( 1 )
4526 if setMatch == '':
4527 setList = []
4528 else:
4529 setList = setMatch.split( ", " )
4530 if length > 0:
4531 return ( setList, containsCheck )
4532 else:
4533 return setList
4534 else: # no match
4535 main.log.error( self.name + ": setTestGet did not" +
4536 " match expected output" )
4537 main.log.debug( self.name + " expected: " + pattern )
4538 main.log.debug( self.name + " actual: " + repr( output ) )
4539 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004540 except TypeError:
4541 main.log.exception( self.name + ": Object not as expected" )
4542 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004543 except Exception:
4544 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004545 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004546
4547 def setTestSize( self, setName ):
4548 """
4549 CLI command to get the elements in a distributed set.
4550 Required arguments:
4551 setName - The name of the set to remove from.
4552 returns:
Jon Hallfeff3082015-05-19 10:23:26 -07004553 The integer value of the size returned or
Jon Hall390696c2015-05-05 17:13:41 -07004554 None on error
4555 """
4556 try:
4557 # TODO: Should this check against the number of elements returned
4558 # and then return true/false based on that?
4559 setName = str( setName ).strip()
4560 # Patterns to match
4561 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004562 pattern = "There are (\d+) items in set " + setName + ":\r\n" +\
Jon Hall390696c2015-05-05 17:13:41 -07004563 setPattern
4564 cmdStr = "set-test-get -s "
4565 cmdStr += setName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004566 output = self.distPrimitivesSend( cmdStr )
Jon Hall0e240372018-05-02 11:21:57 -07004567 if output:
4568 match = re.search( pattern, output )
4569 if match:
4570 setSize = int( match.group( 1 ) )
4571 setMatch = match.group( 2 )
4572 if len( setMatch.split() ) == setSize:
4573 main.log.info( "The size returned by " + self.name +
4574 " matches the number of elements in " +
4575 "the returned set" )
4576 else:
4577 main.log.error( "The size returned by " + self.name +
4578 " does not match the number of " +
4579 "elements in the returned set." )
4580 return setSize
Jon Hall390696c2015-05-05 17:13:41 -07004581 else: # no match
4582 main.log.error( self.name + ": setTestGet did not" +
4583 " match expected output" )
4584 main.log.debug( self.name + " expected: " + pattern )
4585 main.log.debug( self.name + " actual: " + repr( output ) )
4586 return None
Jon Hall390696c2015-05-05 17:13:41 -07004587 except TypeError:
4588 main.log.exception( self.name + ": Object not as expected" )
4589 return None
Jon Hall390696c2015-05-05 17:13:41 -07004590 except Exception:
4591 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004592 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004593
Jon Hall80daded2015-05-27 16:07:00 -07004594 def counters( self, jsonFormat=True ):
Jon Hall390696c2015-05-05 17:13:41 -07004595 """
4596 Command to list the various counters in the system.
4597 returns:
Jon Hall80daded2015-05-27 16:07:00 -07004598 if jsonFormat, a string of the json object returned by the cli
4599 command
4600 if not jsonFormat, the normal string output of the cli command
Jon Hall390696c2015-05-05 17:13:41 -07004601 None on error
4602 """
Jon Hall390696c2015-05-05 17:13:41 -07004603 try:
Jon Hall390696c2015-05-05 17:13:41 -07004604 cmdStr = "counters"
Jon Hall80daded2015-05-27 16:07:00 -07004605 if jsonFormat:
4606 cmdStr += " -j"
Jon Hall390696c2015-05-05 17:13:41 -07004607 output = self.sendline( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004608 main.log.debug( self.name + ": Counters unparsed: " + output )
4609 output = output.split( "\r\n" )[ -1 ]
4610 main.log.debug( self.name + ": Counters parsed: " + output )
Jon Halla495f562016-05-16 18:03:26 -07004611 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004612 assert "Command not found:" not in output, output
4613 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004614 main.log.info( self.name + ": " + output )
Jon Hall80daded2015-05-27 16:07:00 -07004615 return output
Jon Hall390696c2015-05-05 17:13:41 -07004616 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004617 main.log.exception( self.name + ": Error in processing 'counters' command." )
Jon Hall80daded2015-05-27 16:07:00 -07004618 return None
Jon Hall390696c2015-05-05 17:13:41 -07004619 except TypeError:
4620 main.log.exception( self.name + ": Object not as expected" )
Jon Hall80daded2015-05-27 16:07:00 -07004621 return None
Jon Hall390696c2015-05-05 17:13:41 -07004622 except pexpect.EOF:
4623 main.log.error( self.name + ": EOF exception found" )
4624 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004625 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004626 except Exception:
4627 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004628 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004629
Jon Hall935db192016-04-19 00:22:04 -07004630 def counterTestAddAndGet( self, counter, delta=1 ):
Jon Hall390696c2015-05-05 17:13:41 -07004631 """
Jon Halle1a3b752015-07-22 13:02:46 -07004632 CLI command to add a delta to then get a distributed counter.
Jon Hall390696c2015-05-05 17:13:41 -07004633 Required arguments:
4634 counter - The name of the counter to increment.
4635 Optional arguments:
Jon Halle1a3b752015-07-22 13:02:46 -07004636 delta - The long to add to the counter
Jon Hall390696c2015-05-05 17:13:41 -07004637 returns:
4638 integer value of the counter or
4639 None on Error
4640 """
4641 try:
4642 counter = str( counter )
Jon Halle1a3b752015-07-22 13:02:46 -07004643 delta = int( delta )
Jon Hall390696c2015-05-05 17:13:41 -07004644 cmdStr = "counter-test-increment "
Jon Hall390696c2015-05-05 17:13:41 -07004645 cmdStr += counter
Jon Halle1a3b752015-07-22 13:02:46 -07004646 if delta != 1:
4647 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004648 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004649 pattern = counter + " was updated to (-?\d+)"
Jon Hall390696c2015-05-05 17:13:41 -07004650 match = re.search( pattern, output )
4651 if match:
4652 return int( match.group( 1 ) )
4653 else:
Jon Halle1a3b752015-07-22 13:02:46 -07004654 main.log.error( self.name + ": counterTestAddAndGet did not" +
Jon Hall390696c2015-05-05 17:13:41 -07004655 " match expected output." )
4656 main.log.debug( self.name + " expected: " + pattern )
4657 main.log.debug( self.name + " actual: " + repr( output ) )
4658 return None
Jon Hall390696c2015-05-05 17:13:41 -07004659 except TypeError:
4660 main.log.exception( self.name + ": Object not as expected" )
4661 return None
Jon Hall390696c2015-05-05 17:13:41 -07004662 except Exception:
4663 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004664 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004665
Jon Hall935db192016-04-19 00:22:04 -07004666 def counterTestGetAndAdd( self, counter, delta=1 ):
Jon Halle1a3b752015-07-22 13:02:46 -07004667 """
4668 CLI command to get a distributed counter then add a delta to it.
4669 Required arguments:
4670 counter - The name of the counter to increment.
4671 Optional arguments:
4672 delta - The long to add to the counter
Jon Halle1a3b752015-07-22 13:02:46 -07004673 returns:
4674 integer value of the counter or
4675 None on Error
4676 """
4677 try:
4678 counter = str( counter )
4679 delta = int( delta )
4680 cmdStr = "counter-test-increment -g "
Jon Halle1a3b752015-07-22 13:02:46 -07004681 cmdStr += counter
4682 if delta != 1:
4683 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004684 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004685 pattern = counter + " was updated to (-?\d+)"
4686 match = re.search( pattern, output )
4687 if match:
4688 return int( match.group( 1 ) )
4689 else:
4690 main.log.error( self.name + ": counterTestGetAndAdd did not" +
4691 " match expected output." )
4692 main.log.debug( self.name + " expected: " + pattern )
4693 main.log.debug( self.name + " actual: " + repr( output ) )
4694 return None
Jon Halle1a3b752015-07-22 13:02:46 -07004695 except TypeError:
4696 main.log.exception( self.name + ": Object not as expected" )
4697 return None
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004698 except Exception:
4699 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004700 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004701
4702 def valueTestGet( self, valueName ):
4703 """
4704 CLI command to get the value of an atomic value.
4705 Required arguments:
4706 valueName - The name of the value to get.
4707 returns:
4708 string value of the value or
4709 None on Error
4710 """
4711 try:
4712 valueName = str( valueName )
4713 cmdStr = "value-test "
4714 operation = "get"
4715 cmdStr = "value-test {} {}".format( valueName,
4716 operation )
4717 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004718 main.log.debug( self.name + ": value test unparsed: " + output )
4719 output = output.split( "\r\n" )[ -1 ]
4720 main.log.debug( self.name + ": value test parsed: " + output )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004721 pattern = "(\w+)"
4722 match = re.search( pattern, output )
4723 if match:
4724 return match.group( 1 )
4725 else:
4726 main.log.error( self.name + ": valueTestGet did not" +
4727 " match expected output." )
4728 main.log.debug( self.name + " expected: " + pattern )
4729 main.log.debug( self.name + " actual: " + repr( output ) )
4730 return None
4731 except TypeError:
4732 main.log.exception( self.name + ": Object not as expected" )
4733 return None
4734 except Exception:
4735 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004736 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004737
4738 def valueTestSet( self, valueName, newValue ):
4739 """
4740 CLI command to set the value of an atomic value.
4741 Required arguments:
4742 valueName - The name of the value to set.
4743 newValue - The value to assign to the given value.
4744 returns:
4745 main.TRUE on success or
4746 main.ERROR on Error
4747 """
4748 try:
4749 valueName = str( valueName )
4750 newValue = str( newValue )
4751 operation = "set"
4752 cmdStr = "value-test {} {} {}".format( valueName,
4753 operation,
4754 newValue )
4755 output = self.distPrimitivesSend( cmdStr )
4756 if output is not None:
4757 return main.TRUE
4758 else:
4759 return main.ERROR
4760 except TypeError:
4761 main.log.exception( self.name + ": Object not as expected" )
4762 return main.ERROR
4763 except Exception:
4764 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004765 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004766
4767 def valueTestCompareAndSet( self, valueName, oldValue, newValue ):
4768 """
4769 CLI command to compareAndSet the value of an atomic value.
4770 Required arguments:
4771 valueName - The name of the value.
4772 oldValue - Compare the current value of the atomic value to this
4773 newValue - If the value equals oldValue, set the value to newValue
4774 returns:
4775 main.TRUE on success or
4776 main.FALSE on failure or
4777 main.ERROR on Error
4778 """
4779 try:
4780 valueName = str( valueName )
4781 oldValue = str( oldValue )
4782 newValue = str( newValue )
4783 operation = "compareAndSet"
4784 cmdStr = "value-test {} {} {} {}".format( valueName,
4785 operation,
4786 oldValue,
4787 newValue )
4788 output = self.distPrimitivesSend( cmdStr )
4789 pattern = "(\w+)"
4790 match = re.search( pattern, output )
4791 if match:
4792 result = match.group( 1 )
4793 if result == "true":
4794 return main.TRUE
4795 elif result == "false":
4796 return main.FALSE
4797 else:
4798 main.log.error( self.name + ": valueTestCompareAndSet did not" +
4799 " match expected output." )
4800 main.log.debug( self.name + " expected: " + pattern )
4801 main.log.debug( self.name + " actual: " + repr( output ) )
4802 return main.ERROR
4803 except TypeError:
4804 main.log.exception( self.name + ": Object not as expected" )
4805 return main.ERROR
4806 except Exception:
4807 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004808 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004809
4810 def valueTestGetAndSet( self, valueName, newValue ):
4811 """
4812 CLI command to getAndSet the value of an atomic value.
4813 Required arguments:
4814 valueName - The name of the value to get.
4815 newValue - The value to assign to the given value
4816 returns:
4817 string value of the value or
4818 None on Error
4819 """
4820 try:
4821 valueName = str( valueName )
4822 cmdStr = "value-test "
4823 operation = "getAndSet"
4824 cmdStr += valueName + " " + operation
4825 cmdStr = "value-test {} {} {}".format( valueName,
4826 operation,
4827 newValue )
4828 output = self.distPrimitivesSend( cmdStr )
4829 pattern = "(\w+)"
4830 match = re.search( pattern, output )
4831 if match:
4832 return match.group( 1 )
4833 else:
4834 main.log.error( self.name + ": valueTestGetAndSet did not" +
4835 " match expected output." )
4836 main.log.debug( self.name + " expected: " + pattern )
4837 main.log.debug( self.name + " actual: " + repr( output ) )
4838 return None
4839 except TypeError:
4840 main.log.exception( self.name + ": Object not as expected" )
4841 return None
4842 except Exception:
4843 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004844 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004845
4846 def valueTestDestroy( self, valueName ):
4847 """
4848 CLI command to destroy an atomic value.
4849 Required arguments:
4850 valueName - The name of the value to destroy.
4851 returns:
4852 main.TRUE on success or
4853 main.ERROR on Error
4854 """
4855 try:
4856 valueName = str( valueName )
4857 cmdStr = "value-test "
4858 operation = "destroy"
4859 cmdStr += valueName + " " + operation
4860 output = self.distPrimitivesSend( cmdStr )
4861 if output is not None:
4862 return main.TRUE
4863 else:
4864 return main.ERROR
4865 except TypeError:
4866 main.log.exception( self.name + ": Object not as expected" )
4867 return main.ERROR
Jon Halle1a3b752015-07-22 13:02:46 -07004868 except Exception:
4869 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004870 main.cleanAndExit()
Jon Halle1a3b752015-07-22 13:02:46 -07004871
YPZhangfebf7302016-05-24 16:45:56 -07004872 def summary( self, jsonFormat=True, timeout=30 ):
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004873 """
4874 Description: Execute summary command in onos
4875 Returns: json object ( summary -j ), returns main.FALSE if there is
4876 no output
4877
4878 """
4879 try:
4880 cmdStr = "summary"
4881 if jsonFormat:
4882 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07004883 handle = self.sendline( cmdStr, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07004884 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004885 assert "Command not found:" not in handle, handle
Jon Hall6e709752016-02-01 13:38:46 -08004886 assert "Error:" not in handle, handle
Devin Lima7cfdbd2017-09-29 15:02:22 -07004887 assert "Error executing" not in handle, handle
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004888 if not handle:
4889 main.log.error( self.name + ": There is no output in " +
4890 "summary command" )
4891 return main.FALSE
4892 return handle
Jon Hallc6793552016-01-19 14:18:37 -08004893 except AssertionError:
Jon Hall6e709752016-02-01 13:38:46 -08004894 main.log.exception( "{} Error in summary output:".format( self.name ) )
Jon Hallc6793552016-01-19 14:18:37 -08004895 return None
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004896 except TypeError:
4897 main.log.exception( self.name + ": Object not as expected" )
4898 return None
4899 except pexpect.EOF:
4900 main.log.error( self.name + ": EOF exception found" )
4901 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004902 main.cleanAndExit()
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004903 except Exception:
4904 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004905 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004906
Jon Hall935db192016-04-19 00:22:04 -07004907 def transactionalMapGet( self, keyName ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004908 """
4909 CLI command to get the value of a key in a consistent map using
4910 transactions. This a test function and can only get keys from the
4911 test map hard coded into the cli command
4912 Required arguments:
4913 keyName - The name of the key to get
Jon Hall2a5002c2015-08-21 16:49:11 -07004914 returns:
4915 The string value of the key or
4916 None on Error
4917 """
4918 try:
4919 keyName = str( keyName )
4920 cmdStr = "transactional-map-test-get "
Jon Hall2a5002c2015-08-21 16:49:11 -07004921 cmdStr += keyName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004922 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07004923 pattern = "Key-value pair \(" + keyName + ", (?P<value>.+)\) found."
4924 if "Key " + keyName + " not found." in output:
Jon Hall9bfadd22016-05-11 14:48:07 -07004925 main.log.warn( output )
Jon Hall2a5002c2015-08-21 16:49:11 -07004926 return None
4927 else:
4928 match = re.search( pattern, output )
4929 if match:
4930 return match.groupdict()[ 'value' ]
4931 else:
4932 main.log.error( self.name + ": transactionlMapGet did not" +
4933 " match expected output." )
4934 main.log.debug( self.name + " expected: " + pattern )
4935 main.log.debug( self.name + " actual: " + repr( output ) )
4936 return None
4937 except TypeError:
4938 main.log.exception( self.name + ": Object not as expected" )
4939 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004940 except Exception:
4941 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004942 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004943
Jon Hall935db192016-04-19 00:22:04 -07004944 def transactionalMapPut( self, numKeys, value ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004945 """
4946 CLI command to put a value into 'numKeys' number of keys in a
4947 consistent map using transactions. This a test function and can only
4948 put into keys named 'Key#' of the test map hard coded into the cli command
4949 Required arguments:
4950 numKeys - Number of keys to add the value to
4951 value - The string value to put into the keys
Jon Hall2a5002c2015-08-21 16:49:11 -07004952 returns:
4953 A dictionary whose keys are the name of the keys put into the map
4954 and the values of the keys are dictionaries whose key-values are
4955 'value': value put into map and optionaly
4956 'oldValue': Previous value in the key or
4957 None on Error
4958
4959 Example output
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004960 { 'Key1': {'oldValue': 'oldTestValue', 'value': 'Testing'},
4961 'Key2': {'value': 'Testing'} }
Jon Hall2a5002c2015-08-21 16:49:11 -07004962 """
4963 try:
4964 numKeys = str( numKeys )
4965 value = str( value )
4966 cmdStr = "transactional-map-test-put "
Jon Hall2a5002c2015-08-21 16:49:11 -07004967 cmdStr += numKeys + " " + value
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004968 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07004969 newPattern = 'Created Key (?P<key>(\w)+) with value (?P<value>(.)+)\.'
4970 updatedPattern = "Put (?P<value>(.)+) into key (?P<key>(\w)+)\. The old value was (?P<oldValue>(.)+)\."
4971 results = {}
4972 for line in output.splitlines():
4973 new = re.search( newPattern, line )
4974 updated = re.search( updatedPattern, line )
4975 if new:
4976 results[ new.groupdict()[ 'key' ] ] = { 'value': new.groupdict()[ 'value' ] }
4977 elif updated:
4978 results[ updated.groupdict()[ 'key' ] ] = { 'value': updated.groupdict()[ 'value' ],
Jon Hallc6793552016-01-19 14:18:37 -08004979 'oldValue': updated.groupdict()[ 'oldValue' ] }
Jon Hall2a5002c2015-08-21 16:49:11 -07004980 else:
4981 main.log.error( self.name + ": transactionlMapGet did not" +
4982 " match expected output." )
Jon Hallc6793552016-01-19 14:18:37 -08004983 main.log.debug( "{} expected: {!r} or {!r}".format( self.name,
4984 newPattern,
4985 updatedPattern ) )
Jon Hall2a5002c2015-08-21 16:49:11 -07004986 main.log.debug( self.name + " actual: " + repr( output ) )
4987 return results
Jon Hall0e240372018-05-02 11:21:57 -07004988 except ( TypeError, AttributeError ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004989 main.log.exception( self.name + ": Object not as expected" )
4990 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004991 except Exception:
4992 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004993 main.cleanAndExit()
Jon Hallc6793552016-01-19 14:18:37 -08004994
acsmarsdaea66c2015-09-03 11:44:06 -07004995 def maps( self, jsonFormat=True ):
4996 """
4997 Description: Returns result of onos:maps
4998 Optional:
4999 * jsonFormat: enable json formatting of output
5000 """
5001 try:
5002 cmdStr = "maps"
5003 if jsonFormat:
5004 cmdStr += " -j"
5005 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07005006 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005007 assert "Command not found:" not in handle, handle
acsmarsdaea66c2015-09-03 11:44:06 -07005008 return handle
Jon Hallc6793552016-01-19 14:18:37 -08005009 except AssertionError:
5010 main.log.exception( "" )
5011 return None
acsmarsdaea66c2015-09-03 11:44:06 -07005012 except TypeError:
5013 main.log.exception( self.name + ": Object not as expected" )
5014 return None
5015 except pexpect.EOF:
5016 main.log.error( self.name + ": EOF exception found" )
5017 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005018 main.cleanAndExit()
acsmarsdaea66c2015-09-03 11:44:06 -07005019 except Exception:
5020 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005021 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005022
5023 def getSwController( self, uri, jsonFormat=True ):
5024 """
5025 Descrition: Gets the controller information from the device
5026 """
5027 try:
5028 cmd = "device-controllers "
5029 if jsonFormat:
5030 cmd += "-j "
5031 response = self.sendline( cmd + uri )
Jon Halla495f562016-05-16 18:03:26 -07005032 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005033 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005034 return response
Jon Hallc6793552016-01-19 14:18:37 -08005035 except AssertionError:
5036 main.log.exception( "" )
5037 return None
GlennRC050596c2015-11-18 17:06:41 -08005038 except TypeError:
5039 main.log.exception( self.name + ": Object not as expected" )
5040 return None
5041 except pexpect.EOF:
5042 main.log.error( self.name + ": EOF exception found" )
5043 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005044 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005045 except Exception:
5046 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005047 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005048
5049 def setSwController( self, uri, ip, proto="tcp", port="6653", jsonFormat=True ):
5050 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005051 Descrition: sets the controller(s) for the specified device
GlennRC050596c2015-11-18 17:06:41 -08005052
5053 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005054 Required: uri - String: The uri of the device(switch).
GlennRC050596c2015-11-18 17:06:41 -08005055 ip - String or List: The ip address of the controller.
5056 This parameter can be formed in a couple of different ways.
5057 VALID:
5058 10.0.0.1 - just the ip address
5059 tcp:10.0.0.1 - the protocol and the ip address
5060 tcp:10.0.0.1:6653 - the protocol and port can be specified,
5061 so that you can add controllers with different
5062 protocols and ports
5063 INVALID:
5064 10.0.0.1:6653 - this is not supported by ONOS
5065
5066 Optional: proto - The type of connection e.g. tcp, ssl. If a list of ips are given
5067 port - The port number.
5068 jsonFormat - If set ONOS will output in json NOTE: This is currently not supported
5069
5070 Returns: main.TRUE if ONOS returns without any errors, otherwise returns main.FALSE
5071 """
5072 try:
5073 cmd = "device-setcontrollers"
5074
5075 if jsonFormat:
5076 cmd += " -j"
5077 cmd += " " + uri
5078 if isinstance( ip, str ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005079 ip = [ ip ]
GlennRC050596c2015-11-18 17:06:41 -08005080 for item in ip:
5081 if ":" in item:
5082 sitem = item.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005083 if len( sitem ) == 3:
GlennRC050596c2015-11-18 17:06:41 -08005084 cmd += " " + item
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005085 elif "." in sitem[ 1 ]:
5086 cmd += " {}:{}".format( item, port )
GlennRC050596c2015-11-18 17:06:41 -08005087 else:
5088 main.log.error( "Malformed entry: " + item )
5089 raise TypeError
5090 else:
5091 cmd += " {}:{}:{}".format( proto, item, port )
GlennRC050596c2015-11-18 17:06:41 -08005092 response = self.sendline( cmd )
Jon Halla495f562016-05-16 18:03:26 -07005093 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005094 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005095 if "Error" in response:
5096 main.log.error( response )
5097 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005098 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005099 except AssertionError:
5100 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005101 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005102 except TypeError:
5103 main.log.exception( self.name + ": Object not as expected" )
5104 return main.FALSE
5105 except pexpect.EOF:
5106 main.log.error( self.name + ": EOF exception found" )
5107 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005108 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005109 except Exception:
5110 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005111 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005112
5113 def removeDevice( self, device ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005114 '''
GlennRC20fc6522015-12-23 23:26:57 -08005115 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005116 Remove a device from ONOS by passing the uri of the device(s).
GlennRC20fc6522015-12-23 23:26:57 -08005117 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005118 device - (str or list) the id or uri of the device ex. "of:0000000000000001"
GlennRC20fc6522015-12-23 23:26:57 -08005119 Returns:
5120 Returns main.FALSE if an exception is thrown or an error is present
5121 in the response. Otherwise, returns main.TRUE.
5122 NOTE:
5123 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005124 '''
GlennRC20fc6522015-12-23 23:26:57 -08005125 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005126 if isinstance( device, str ):
You Wang823f5022016-08-18 15:24:41 -07005127 deviceStr = device
5128 device = []
5129 device.append( deviceStr )
GlennRC20fc6522015-12-23 23:26:57 -08005130
5131 for d in device:
5132 time.sleep( 1 )
5133 response = self.sendline( "device-remove {}".format( d ) )
Jon Halla495f562016-05-16 18:03:26 -07005134 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005135 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005136 if "Error" in response:
5137 main.log.warn( "Error for device: {}\nResponse: {}".format( d, response ) )
5138 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005139 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005140 except AssertionError:
5141 main.log.exception( "" )
5142 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005143 except TypeError:
5144 main.log.exception( self.name + ": Object not as expected" )
5145 return main.FALSE
5146 except pexpect.EOF:
5147 main.log.error( self.name + ": EOF exception found" )
5148 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005149 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005150 except Exception:
5151 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005152 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005153
5154 def removeHost( self, host ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005155 '''
GlennRC20fc6522015-12-23 23:26:57 -08005156 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005157 Remove a host from ONOS by passing the id of the host(s)
GlennRC20fc6522015-12-23 23:26:57 -08005158 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005159 hostId - (str or list) the id or mac of the host ex. "00:00:00:00:00:01"
GlennRC20fc6522015-12-23 23:26:57 -08005160 Returns:
5161 Returns main.FALSE if an exception is thrown or an error is present
5162 in the response. Otherwise, returns main.TRUE.
5163 NOTE:
5164 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005165 '''
GlennRC20fc6522015-12-23 23:26:57 -08005166 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005167 if isinstance( host, str ):
GlennRC20fc6522015-12-23 23:26:57 -08005168 host = list( host )
5169
5170 for h in host:
5171 time.sleep( 1 )
5172 response = self.sendline( "host-remove {}".format( h ) )
Jon Halla495f562016-05-16 18:03:26 -07005173 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005174 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005175 if "Error" in response:
5176 main.log.warn( "Error for host: {}\nResponse: {}".format( h, response ) )
5177 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005178 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005179 except AssertionError:
5180 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005181 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005182 except TypeError:
5183 main.log.exception( self.name + ": Object not as expected" )
5184 return main.FALSE
5185 except pexpect.EOF:
5186 main.log.error( self.name + ": EOF exception found" )
5187 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005188 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005189 except Exception:
5190 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005191 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005192
YPZhangfebf7302016-05-24 16:45:56 -07005193 def link( self, begin, end, state, timeout=30, showResponse=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005194 '''
GlennRCed771242016-01-13 17:02:47 -08005195 Description:
5196 Bring link down or up in the null-provider.
5197 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005198 begin - (string) One end of a device or switch.
5199 end - (string) the other end of the device or switch
GlennRCed771242016-01-13 17:02:47 -08005200 returns:
5201 main.TRUE if no exceptions were thrown and no Errors are
5202 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005203 '''
GlennRCed771242016-01-13 17:02:47 -08005204 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005205 cmd = "null-link null:{} null:{} {}".format( begin, end, state )
YPZhangfebf7302016-05-24 16:45:56 -07005206 response = self.sendline( cmd, showResponse=showResponse, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07005207 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005208 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08005209 if "Error" in response or "Failure" in response:
5210 main.log.error( response )
5211 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005212 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005213 except AssertionError:
5214 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005215 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005216 except TypeError:
5217 main.log.exception( self.name + ": Object not as expected" )
5218 return main.FALSE
5219 except pexpect.EOF:
5220 main.log.error( self.name + ": EOF exception found" )
5221 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005222 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005223 except Exception:
5224 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005225 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005226
Jon Hall2c8959e2016-12-16 12:17:34 -08005227 def portstate( self, dpid, port, state ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005228 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005229 Description:
5230 Changes the state of port in an OF switch by means of the
5231 PORTSTATUS OF messages.
5232 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005233 dpid - (string) Datapath ID of the device. Ex: 'of:0000000000000102'
5234 port - (string) target port in the device. Ex: '2'
5235 state - (string) target state (enable or disable)
Flavio Castro82ee2f62016-06-07 15:04:12 -07005236 returns:
5237 main.TRUE if no exceptions were thrown and no Errors are
5238 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005239 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005240 try:
Jon Hall2c8959e2016-12-16 12:17:34 -08005241 state = state.lower()
5242 assert state == 'enable' or state == 'disable', "Unknown state"
Jon Halle0f0b342017-04-18 11:43:47 -07005243 cmd = "portstate {} {} {}".format( dpid, port, state )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005244 response = self.sendline( cmd, showResponse=True )
5245 assert response is not None, "Error in sendline"
5246 assert "Command not found:" not in response, response
5247 if "Error" in response or "Failure" in response:
5248 main.log.error( response )
5249 return main.FALSE
5250 return main.TRUE
5251 except AssertionError:
5252 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005253 return main.FALSE
Flavio Castro82ee2f62016-06-07 15:04:12 -07005254 except TypeError:
5255 main.log.exception( self.name + ": Object not as expected" )
5256 return main.FALSE
5257 except pexpect.EOF:
5258 main.log.error( self.name + ": EOF exception found" )
5259 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005260 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005261 except Exception:
5262 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005263 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005264
5265 def logSet( self, level="INFO", app="org.onosproject" ):
5266 """
5267 Set the logging level to lvl for a specific app
5268 returns main.TRUE on success
5269 returns main.FALSE if Error occurred
5270 if noExit is True, TestON will not exit, but clean up
5271 Available level: DEBUG, TRACE, INFO, WARN, ERROR
5272 Level defaults to INFO
5273 """
5274 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005275 self.handle.sendline( "log:set %s %s" % ( level, app ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -08005276 self.handle.expect( self.karafPrompt )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005277
5278 response = self.handle.before
5279 if re.search( "Error", response ):
5280 return main.FALSE
5281 return main.TRUE
5282 except pexpect.TIMEOUT:
5283 main.log.exception( self.name + ": TIMEOUT exception found" )
Devin Lim44075962017-08-11 10:56:37 -07005284 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005285 except pexpect.EOF:
5286 main.log.error( self.name + ": EOF exception found" )
5287 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005288 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005289 except Exception:
5290 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005291 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07005292
5293 def getGraphDict( self, timeout=60, includeHost=False ):
5294 """
5295 Return a dictionary which describes the latest network topology data as a
5296 graph.
5297 An example of the dictionary:
5298 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
5299 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
5300 Each vertex should at least have an 'edges' attribute which describes the
5301 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005302 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07005303 list of attributes.
5304 An example of the edges dictionary:
5305 'edges': { vertex2: { 'port': ..., 'weight': ... },
5306 vertex3: { 'port': ..., 'weight': ... } }
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005307 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07005308 in topology data.
5309 """
5310 graphDict = {}
5311 try:
5312 links = self.links()
5313 links = json.loads( links )
5314 devices = self.devices()
5315 devices = json.loads( devices )
5316 idToDevice = {}
5317 for device in devices:
5318 idToDevice[ device[ 'id' ] ] = device
5319 if includeHost:
5320 hosts = self.hosts()
5321 # FIXME: support 'includeHost' argument
5322 for link in links:
5323 nodeA = link[ 'src' ][ 'device' ]
5324 nodeB = link[ 'dst' ][ 'device' ]
5325 assert idToDevice[ nodeA ][ 'available' ] and idToDevice[ nodeB ][ 'available' ]
Jon Halle0f0b342017-04-18 11:43:47 -07005326 if nodeA not in graphDict.keys():
5327 graphDict[ nodeA ] = { 'edges': {},
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005328 'dpid': idToDevice[ nodeA ][ 'id' ][ 3: ],
Jon Halle0f0b342017-04-18 11:43:47 -07005329 'type': idToDevice[ nodeA ][ 'type' ],
5330 'available': idToDevice[ nodeA ][ 'available' ],
5331 'role': idToDevice[ nodeA ][ 'role' ],
5332 'mfr': idToDevice[ nodeA ][ 'mfr' ],
5333 'hw': idToDevice[ nodeA ][ 'hw' ],
5334 'sw': idToDevice[ nodeA ][ 'sw' ],
5335 'serial': idToDevice[ nodeA ][ 'serial' ],
5336 'chassisId': idToDevice[ nodeA ][ 'chassisId' ],
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005337 'annotations': idToDevice[ nodeA ][ 'annotations' ]}
You Wangdb8cd0a2016-05-26 15:19:45 -07005338 else:
5339 # Assert nodeB is not connected to any current links of nodeA
You Wang7d14d642019-01-23 15:10:08 -08005340 # assert nodeB not in graphDict[ nodeA ][ 'edges' ].keys()
5341 pass
Jon Halle0f0b342017-04-18 11:43:47 -07005342 graphDict[ nodeA ][ 'edges' ][ nodeB ] = { 'port': link[ 'src' ][ 'port' ],
5343 'type': link[ 'type' ],
5344 'state': link[ 'state' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07005345 return graphDict
5346 except ( TypeError, ValueError ):
5347 main.log.exception( self.name + ": Object not as expected" )
5348 return None
5349 except KeyError:
5350 main.log.exception( self.name + ": KeyError exception found" )
5351 return None
5352 except AssertionError:
5353 main.log.exception( self.name + ": AssertionError exception found" )
5354 return None
5355 except pexpect.EOF:
5356 main.log.error( self.name + ": EOF exception found" )
5357 main.log.error( self.name + ": " + self.handle.before )
5358 return None
5359 except Exception:
5360 main.log.exception( self.name + ": Uncaught exception!" )
5361 return None
YPZhangcbc2a062016-07-11 10:55:44 -07005362
5363 def getIntentPerfSummary( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005364 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005365 Send command to check intent-perf summary
5366 Returns: dictionary for intent-perf summary
5367 if something wrong, function will return None
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005368 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005369 cmd = "intent-perf -s"
5370 respDic = {}
5371 resp = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08005372 assert resp is not None, "Error in sendline"
5373 assert "Command not found:" not in resp, resp
YPZhangcbc2a062016-07-11 10:55:44 -07005374 try:
5375 # Generate the dictionary to return
5376 for l in resp.split( "\n" ):
5377 # Delete any white space in line
5378 temp = re.sub( r'\s+', '', l )
5379 temp = temp.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005380 respDic[ temp[ 0 ] ] = temp[ 1 ]
YPZhangcbc2a062016-07-11 10:55:44 -07005381
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005382 except ( TypeError, ValueError ):
YPZhangcbc2a062016-07-11 10:55:44 -07005383 main.log.exception( self.name + ": Object not as expected" )
5384 return None
5385 except KeyError:
5386 main.log.exception( self.name + ": KeyError exception found" )
5387 return None
5388 except AssertionError:
5389 main.log.exception( self.name + ": AssertionError exception found" )
5390 return None
5391 except pexpect.EOF:
5392 main.log.error( self.name + ": EOF exception found" )
5393 main.log.error( self.name + ": " + self.handle.before )
5394 return None
5395 except Exception:
5396 main.log.exception( self.name + ": Uncaught exception!" )
5397 return None
5398 return respDic
5399
Chiyu Chengec63bde2016-11-17 18:11:36 -08005400 def logSearch( self, mode='all', searchTerm='', startLine='', logNum=1 ):
chengchiyu08303a02016-09-08 17:40:26 -07005401 """
5402 Searches the latest ONOS log file for the given search term and
5403 return a list that contains all the lines that have the search term.
YPZhangcbc2a062016-07-11 10:55:44 -07005404
chengchiyu08303a02016-09-08 17:40:26 -07005405 Arguments:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005406 searchTerm:
5407 The string to grep from the ONOS log.
5408 startLine:
5409 The term that decides which line is the start to search the searchTerm in
5410 the karaf log. For now, startTerm only works in 'first' mode.
5411 logNum:
5412 In some extreme cases, one karaf log is not big enough to contain all the
5413 information.Because of this, search mutiply logs is necessary to capture
5414 the right result. logNum is the number of karaf logs that we need to search
5415 the searchTerm.
chengchiyu08303a02016-09-08 17:40:26 -07005416 mode:
5417 all: return all the strings that contain the search term
5418 last: return the last string that contains the search term
5419 first: return the first string that contains the search term
Chiyu Chengec63bde2016-11-17 18:11:36 -08005420 num: return the number of times that the searchTerm appears in the log
5421 total: return how many lines in karaf log
chengchiyu08303a02016-09-08 17:40:26 -07005422 """
5423 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005424 assert isinstance( searchTerm, str )
Jon Halle0f0b342017-04-18 11:43:47 -07005425 # Build the log paths string
Chiyu Chengec63bde2016-11-17 18:11:36 -08005426 logPath = '/opt/onos/log/karaf.log.'
5427 logPaths = '/opt/onos/log/karaf.log'
5428 for i in range( 1, logNum ):
5429 logPaths = logPath + str( i ) + " " + logPaths
5430 cmd = "cat " + logPaths
You Wang6d301d42017-04-21 10:49:33 -07005431 if startLine:
Jon Halla478b852017-12-04 15:00:15 -08005432 # 100000000 is just a extreme large number to make sure this function can
5433 # grep all the lines after startLine
You Wang6d301d42017-04-21 10:49:33 -07005434 cmd = cmd + " | grep -A 100000000 \'" + startLine + "\'"
Chiyu Chengec63bde2016-11-17 18:11:36 -08005435 if mode == 'all':
5436 cmd = cmd + " | grep \'" + searchTerm + "\'"
You Wang6d301d42017-04-21 10:49:33 -07005437 elif mode == 'last':
Chiyu Chengec63bde2016-11-17 18:11:36 -08005438 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | tail -n 1"
You Wang6d301d42017-04-21 10:49:33 -07005439 elif mode == 'first':
5440 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | head -n 1"
5441 elif mode == 'num':
You Wangd91a70f2019-01-03 15:28:10 -08005442 cmd = cmd + " | grep \'" + searchTerm + "\' | wc -l"
5443 num = self.lineCount( cmd )
Chiyu Chengb8c2c842016-10-05 12:40:49 -07005444 return num
You Wang6d301d42017-04-21 10:49:33 -07005445 elif mode == 'total':
Jon Halld5a94fb2018-11-13 14:32:23 -08005446 totalLines = self.lineCount( "cat /opt/onos/log/karaf.log | wc -l" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005447 return int( totalLines )
You Wang6d301d42017-04-21 10:49:33 -07005448 else:
5449 main.log.error( self.name + " unsupported mode" )
5450 return main.ERROR
chengchiyu08303a02016-09-08 17:40:26 -07005451 before = self.sendline( cmd )
5452 before = before.splitlines()
5453 # make sure the returned list only contains the search term
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005454 returnLines = [ line for line in before if searchTerm in line ]
chengchiyu08303a02016-09-08 17:40:26 -07005455 return returnLines
5456 except AssertionError:
5457 main.log.error( self.name + " searchTerm is not string type" )
5458 return None
5459 except pexpect.EOF:
5460 main.log.error( self.name + ": EOF exception found" )
5461 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005462 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005463 except pexpect.TIMEOUT:
5464 main.log.error( self.name + ": TIMEOUT exception found" )
5465 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005466 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005467 except Exception:
5468 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005469 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005470
5471 def vplsShow( self, jsonFormat=True ):
5472 """
5473 Description: Returns result of onos:vpls show, which should list the
5474 configured VPLS networks and the assigned interfaces.
5475 Optional:
5476 * jsonFormat: enable json formatting of output
5477 Returns:
5478 The output of the command or None on error.
5479 """
5480 try:
5481 cmdStr = "vpls show"
5482 if jsonFormat:
5483 raise NotImplementedError
5484 cmdStr += " -j"
5485 handle = self.sendline( cmdStr )
5486 assert handle is not None, "Error in sendline"
5487 assert "Command not found:" not in handle, handle
5488 return handle
5489 except AssertionError:
5490 main.log.exception( "" )
5491 return None
5492 except TypeError:
5493 main.log.exception( self.name + ": Object not as expected" )
5494 return None
5495 except pexpect.EOF:
5496 main.log.error( self.name + ": EOF exception found" )
5497 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005498 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005499 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005500 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005501 return None
5502 except Exception:
5503 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005504 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005505
5506 def parseVplsShow( self ):
5507 """
5508 Parse the cli output of 'vpls show' into json output. This is required
5509 as there is currently no json output available.
5510 """
5511 try:
5512 output = []
5513 raw = self.vplsShow( jsonFormat=False )
5514 namePat = "VPLS name: (?P<name>\w+)"
5515 interfacesPat = "Associated interfaces: \[(?P<interfaces>.*)\]"
5516 encapPat = "Encapsulation: (?P<encap>\w+)"
5517 pattern = "\s+".join( [ namePat, interfacesPat, encapPat ] )
5518 mIter = re.finditer( pattern, raw )
5519 for match in mIter:
5520 item = {}
5521 item[ 'name' ] = match.group( 'name' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005522 ifaces = match.group( 'interfaces' ).split( ', ' )
Jon Hall2c8959e2016-12-16 12:17:34 -08005523 if ifaces == [ "" ]:
5524 ifaces = []
5525 item[ 'interfaces' ] = ifaces
5526 encap = match.group( 'encap' )
5527 if encap != 'NONE':
5528 item[ 'encapsulation' ] = encap.lower()
5529 output.append( item )
5530 return output
5531 except Exception:
5532 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005533 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005534
5535 def vplsList( self, jsonFormat=True ):
5536 """
5537 Description: Returns result of onos:vpls list, which should list the
5538 configured VPLS networks.
5539 Optional:
5540 * jsonFormat: enable json formatting of output
5541 """
5542 try:
5543 cmdStr = "vpls list"
5544 if jsonFormat:
5545 raise NotImplementedError
5546 cmdStr += " -j"
5547 handle = self.sendline( cmdStr )
5548 assert handle is not None, "Error in sendline"
5549 assert "Command not found:" not in handle, handle
5550 return handle
5551 except AssertionError:
5552 main.log.exception( "" )
5553 return None
5554 except TypeError:
5555 main.log.exception( self.name + ": Object not as expected" )
5556 return None
5557 except pexpect.EOF:
5558 main.log.error( self.name + ": EOF exception found" )
5559 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005560 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005561 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005562 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005563 return None
5564 except Exception:
5565 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005566 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005567
5568 def vplsCreate( self, network ):
5569 """
5570 CLI command to create a new VPLS network.
5571 Required arguments:
5572 network - String name of the network to create.
5573 returns:
5574 main.TRUE on success and main.FALSE on failure
5575 """
5576 try:
5577 network = str( network )
5578 cmdStr = "vpls create "
5579 cmdStr += network
5580 output = self.sendline( cmdStr )
5581 assert output is not None, "Error in sendline"
5582 assert "Command not found:" not in output, output
5583 assert "Error executing command" not in output, output
5584 assert "VPLS already exists:" not in output, output
5585 return main.TRUE
5586 except AssertionError:
5587 main.log.exception( "" )
5588 return main.FALSE
5589 except TypeError:
5590 main.log.exception( self.name + ": Object not as expected" )
5591 return main.FALSE
5592 except pexpect.EOF:
5593 main.log.error( self.name + ": EOF exception found" )
5594 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005595 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005596 except Exception:
5597 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005598 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005599
5600 def vplsDelete( self, network ):
5601 """
5602 CLI command to delete a VPLS network.
5603 Required arguments:
5604 network - Name of the network to delete.
5605 returns:
5606 main.TRUE on success and main.FALSE on failure
5607 """
5608 try:
5609 network = str( network )
5610 cmdStr = "vpls delete "
5611 cmdStr += network
5612 output = self.sendline( cmdStr )
5613 assert output is not None, "Error in sendline"
5614 assert "Command not found:" not in output, output
5615 assert "Error executing command" not in output, output
5616 assert " not found" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005617 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005618 return main.TRUE
5619 except AssertionError:
5620 main.log.exception( "" )
5621 return main.FALSE
5622 except TypeError:
5623 main.log.exception( self.name + ": Object not as expected" )
5624 return main.FALSE
5625 except pexpect.EOF:
5626 main.log.error( self.name + ": EOF exception found" )
5627 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005628 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005629 except Exception:
5630 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005631 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005632
5633 def vplsAddIface( self, network, iface ):
5634 """
5635 CLI command to add an interface to a VPLS network.
5636 Required arguments:
5637 network - Name of the network to add the interface to.
5638 iface - The ONOS name for an interface.
5639 returns:
5640 main.TRUE on success and main.FALSE on failure
5641 """
5642 try:
5643 network = str( network )
5644 iface = str( iface )
5645 cmdStr = "vpls add-if "
5646 cmdStr += network + " " + iface
5647 output = self.sendline( cmdStr )
5648 assert output is not None, "Error in sendline"
5649 assert "Command not found:" not in output, output
5650 assert "Error executing command" not in output, output
5651 assert "already associated to network" not in output, output
5652 assert "Interface cannot be added." not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005653 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005654 return main.TRUE
5655 except AssertionError:
5656 main.log.exception( "" )
5657 return main.FALSE
5658 except TypeError:
5659 main.log.exception( self.name + ": Object not as expected" )
5660 return main.FALSE
5661 except pexpect.EOF:
5662 main.log.error( self.name + ": EOF exception found" )
5663 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005664 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005665 except Exception:
5666 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005667 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005668
5669 def vplsRemIface( self, network, iface ):
5670 """
5671 CLI command to remove an interface from a VPLS network.
5672 Required arguments:
5673 network - Name of the network to remove the interface from.
5674 iface - Name of the interface to remove.
5675 returns:
5676 main.TRUE on success and main.FALSE on failure
5677 """
5678 try:
5679 iface = str( iface )
5680 cmdStr = "vpls rem-if "
5681 cmdStr += network + " " + iface
5682 output = self.sendline( cmdStr )
5683 assert output is not None, "Error in sendline"
5684 assert "Command not found:" not in output, output
5685 assert "Error executing command" not in output, output
5686 assert "is not configured" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005687 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005688 return main.TRUE
5689 except AssertionError:
5690 main.log.exception( "" )
5691 return main.FALSE
5692 except TypeError:
5693 main.log.exception( self.name + ": Object not as expected" )
5694 return main.FALSE
5695 except pexpect.EOF:
5696 main.log.error( self.name + ": EOF exception found" )
5697 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005698 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005699 except Exception:
5700 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005701 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005702
5703 def vplsClean( self ):
5704 """
5705 Description: Clears the VPLS app configuration.
5706 Returns: main.TRUE on success and main.FALSE on failure
5707 """
5708 try:
5709 cmdStr = "vpls clean"
5710 handle = self.sendline( cmdStr )
5711 assert handle is not None, "Error in sendline"
5712 assert "Command not found:" not in handle, handle
Jon Hallcf97cf12017-06-06 09:37:51 -07005713 assert "still updating" not in handle, handle
Jon Hall2c8959e2016-12-16 12:17:34 -08005714 return handle
5715 except AssertionError:
5716 main.log.exception( "" )
5717 return main.FALSE
5718 except TypeError:
5719 main.log.exception( self.name + ": Object not as expected" )
5720 return main.FALSE
5721 except pexpect.EOF:
5722 main.log.error( self.name + ": EOF exception found" )
5723 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005724 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005725 except Exception:
5726 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005727 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005728
5729 def vplsSetEncap( self, network, encapType ):
5730 """
5731 CLI command to add an interface to a VPLS network.
5732 Required arguments:
5733 network - Name of the network to create.
5734 encapType - Type of encapsulation.
5735 returns:
5736 main.TRUE on success and main.FALSE on failure
5737 """
5738 try:
5739 network = str( network )
5740 encapType = str( encapType ).upper()
5741 assert encapType in [ "MPLS", "VLAN", "NONE" ], "Incorrect type"
5742 cmdStr = "vpls set-encap "
5743 cmdStr += network + " " + encapType
5744 output = self.sendline( cmdStr )
5745 assert output is not None, "Error in sendline"
5746 assert "Command not found:" not in output, output
5747 assert "Error executing command" not in output, output
5748 assert "already associated to network" not in output, output
5749 assert "Encapsulation type " not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005750 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005751 return main.TRUE
5752 except AssertionError:
5753 main.log.exception( "" )
5754 return main.FALSE
5755 except TypeError:
5756 main.log.exception( self.name + ": Object not as expected" )
5757 return main.FALSE
5758 except pexpect.EOF:
5759 main.log.error( self.name + ": EOF exception found" )
5760 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005761 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005762 except Exception:
5763 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005764 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005765
5766 def interfaces( self, jsonFormat=True ):
5767 """
5768 Description: Returns result of interfaces command.
5769 Optional:
5770 * jsonFormat: enable json formatting of output
5771 Returns:
5772 The output of the command or None on error.
5773 """
5774 try:
5775 cmdStr = "interfaces"
5776 if jsonFormat:
Jon Halle0f0b342017-04-18 11:43:47 -07005777 raise NotImplementedError
Jon Hall2c8959e2016-12-16 12:17:34 -08005778 cmdStr += " -j"
5779 handle = self.sendline( cmdStr )
5780 assert handle is not None, "Error in sendline"
5781 assert "Command not found:" not in handle, handle
5782 return handle
5783 except AssertionError:
5784 main.log.exception( "" )
5785 return None
5786 except TypeError:
5787 main.log.exception( self.name + ": Object not as expected" )
5788 return None
5789 except pexpect.EOF:
5790 main.log.error( self.name + ": EOF exception found" )
5791 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005792 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005793 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005794 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005795 return None
5796 except Exception:
5797 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005798 main.cleanAndExit()
Chiyu Chengec63bde2016-11-17 18:11:36 -08005799
5800 def getTimeStampFromLog( self, mode, searchTerm, splitTerm_before, splitTerm_after, startLine='', logNum=1 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005801 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005802 Get the timestamp of searchTerm from karaf log.
5803
5804 Arguments:
5805 splitTerm_before and splitTerm_after:
5806
5807 The terms that split the string that contains the timeStamp of
5808 searchTerm. For example, if that string is "xxxxxxxcreationTime =
5809 1419510501xxxxxx", then the splitTerm_before is "CreationTime = "
5810 and the splitTerm_after is "x"
5811
5812 others:
Jon Halle0f0b342017-04-18 11:43:47 -07005813 Please look at the "logsearch" Function in onosclidriver.py
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005814 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005815 if logNum < 0:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005816 main.log.error( "Get wrong log number ")
Chiyu Chengec63bde2016-11-17 18:11:36 -08005817 return main.ERROR
5818 lines = self.logSearch( mode=mode, searchTerm=searchTerm, startLine=startLine, logNum=logNum )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005819 if len( lines ) == 0:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005820 main.log.warn( "Captured timestamp string is empty" )
5821 return main.ERROR
5822 lines = lines[ 0 ]
5823 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005824 assert isinstance( lines, str )
Chiyu Chengec63bde2016-11-17 18:11:36 -08005825 # get the target value
5826 line = lines.split( splitTerm_before )
5827 key = line[ 1 ].split( splitTerm_after )
5828 return int( key[ 0 ] )
5829 except IndexError:
5830 main.log.warn( "Index Error!" )
5831 return main.ERROR
5832 except AssertionError:
5833 main.log.warn( "Search Term Not Found " )
5834 return main.ERROR
Jon Halle0f0b342017-04-18 11:43:47 -07005835
5836 def workQueueAdd( self, queueName, value ):
5837 """
5838 CLI command to add a string to the specified Work Queue.
5839 This function uses the distributed primitives test app, which
5840 gives some cli access to distributed primitives for testing
5841 purposes only.
5842
5843 Required arguments:
5844 queueName - The name of the queue to add to
5845 value - The value to add to the queue
5846 returns:
5847 main.TRUE on success, main.FALSE on failure and
5848 main.ERROR on error.
5849 """
5850 try:
5851 queueName = str( queueName )
5852 value = str( value )
5853 prefix = "work-queue-test"
5854 operation = "add"
5855 cmdStr = " ".join( [ prefix, queueName, operation, value ] )
5856 output = self.distPrimitivesSend( cmdStr )
5857 if "Invalid operation name" in output:
5858 main.log.warn( output )
5859 return main.ERROR
5860 elif "Done" in output:
5861 return main.TRUE
5862 except TypeError:
5863 main.log.exception( self.name + ": Object not as expected" )
5864 return main.ERROR
5865 except Exception:
5866 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005867 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005868
5869 def workQueueAddMultiple( self, queueName, value1, value2 ):
5870 """
5871 CLI command to add two strings to the specified Work Queue.
5872 This function uses the distributed primitives test app, which
5873 gives some cli access to distributed primitives for testing
5874 purposes only.
5875
5876 Required arguments:
5877 queueName - The name of the queue to add to
5878 value1 - The first value to add to the queue
5879 value2 - The second value to add to the queue
5880 returns:
5881 main.TRUE on success, main.FALSE on failure and
5882 main.ERROR on error.
5883 """
5884 try:
5885 queueName = str( queueName )
5886 value1 = str( value1 )
5887 value2 = str( value2 )
5888 prefix = "work-queue-test"
5889 operation = "addMultiple"
5890 cmdStr = " ".join( [ prefix, queueName, operation, value1, value2 ] )
5891 output = self.distPrimitivesSend( cmdStr )
5892 if "Invalid operation name" in output:
5893 main.log.warn( output )
5894 return main.ERROR
5895 elif "Done" in output:
5896 return main.TRUE
5897 except TypeError:
5898 main.log.exception( self.name + ": Object not as expected" )
5899 return main.ERROR
5900 except Exception:
5901 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005902 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005903
5904 def workQueueTakeAndComplete( self, queueName, number=1 ):
5905 """
5906 CLI command to take a value from the specified Work Queue and compelte it.
5907 This function uses the distributed primitives test app, which
5908 gives some cli access to distributed primitives for testing
5909 purposes only.
5910
5911 Required arguments:
5912 queueName - The name of the queue to add to
5913 number - The number of items to take and complete
5914 returns:
5915 main.TRUE on success, main.FALSE on failure and
5916 main.ERROR on error.
5917 """
5918 try:
5919 queueName = str( queueName )
5920 number = str( int( number ) )
5921 prefix = "work-queue-test"
5922 operation = "takeAndComplete"
5923 cmdStr = " ".join( [ prefix, queueName, operation, number ] )
5924 output = self.distPrimitivesSend( cmdStr )
5925 if "Invalid operation name" in output:
5926 main.log.warn( output )
5927 return main.ERROR
5928 elif "Done" in output:
5929 return main.TRUE
5930 except TypeError:
5931 main.log.exception( self.name + ": Object not as expected" )
5932 return main.ERROR
5933 except Exception:
5934 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005935 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005936
5937 def workQueueDestroy( self, queueName ):
5938 """
5939 CLI command to destroy the specified Work Queue.
5940 This function uses the distributed primitives test app, which
5941 gives some cli access to distributed primitives for testing
5942 purposes only.
5943
5944 Required arguments:
5945 queueName - The name of the queue to add to
5946 returns:
5947 main.TRUE on success, main.FALSE on failure and
5948 main.ERROR on error.
5949 """
5950 try:
5951 queueName = str( queueName )
5952 prefix = "work-queue-test"
5953 operation = "destroy"
5954 cmdStr = " ".join( [ prefix, queueName, operation ] )
5955 output = self.distPrimitivesSend( cmdStr )
5956 if "Invalid operation name" in output:
5957 main.log.warn( output )
5958 return main.ERROR
5959 return main.TRUE
5960 except TypeError:
5961 main.log.exception( self.name + ": Object not as expected" )
5962 return main.ERROR
5963 except Exception:
5964 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005965 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005966
5967 def workQueueTotalPending( self, queueName ):
5968 """
5969 CLI command to get the Total Pending items of the specified Work Queue.
5970 This function uses the distributed primitives test app, which
5971 gives some cli access to distributed primitives for testing
5972 purposes only.
5973
5974 Required arguments:
5975 queueName - The name of the queue to add to
5976 returns:
5977 The number of Pending items in the specified work queue or
5978 None on error
5979 """
5980 try:
5981 queueName = str( queueName )
5982 prefix = "work-queue-test"
5983 operation = "totalPending"
5984 cmdStr = " ".join( [ prefix, queueName, operation ] )
5985 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08005986 main.log.debug( self.name + ": work queue unparsed: " + output )
5987 output = output.split( "\r\n" )[ -1 ]
5988 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07005989 pattern = r'\d+'
5990 if "Invalid operation name" in output:
5991 main.log.warn( output )
5992 return None
5993 else:
5994 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005995 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07005996 except ( AttributeError, TypeError ):
5997 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
5998 return None
5999 except Exception:
6000 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006001 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006002
6003 def workQueueTotalCompleted( self, queueName ):
6004 """
6005 CLI command to get the Total Completed items of the specified Work Queue.
6006 This function uses the distributed primitives test app, which
6007 gives some cli access to distributed primitives for testing
6008 purposes only.
6009
6010 Required arguments:
6011 queueName - The name of the queue to add to
6012 returns:
6013 The number of complete items in the specified work queue or
6014 None on error
6015 """
6016 try:
6017 queueName = str( queueName )
6018 prefix = "work-queue-test"
6019 operation = "totalCompleted"
6020 cmdStr = " ".join( [ prefix, queueName, operation ] )
6021 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006022 main.log.debug( self.name + ": work queue unparsed: " + output )
6023 output = output.split( "\r\n" )[ -1 ]
6024 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006025 pattern = r'\d+'
6026 if "Invalid operation name" in output:
6027 main.log.warn( output )
6028 return None
6029 else:
6030 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006031 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006032 except ( AttributeError, TypeError ):
6033 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6034 return None
6035 except Exception:
6036 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006037 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006038
6039 def workQueueTotalInProgress( self, queueName ):
6040 """
6041 CLI command to get the Total In Progress items of the specified Work Queue.
6042 This function uses the distributed primitives test app, which
6043 gives some cli access to distributed primitives for testing
6044 purposes only.
6045
6046 Required arguments:
6047 queueName - The name of the queue to add to
6048 returns:
6049 The number of In Progress items in the specified work queue or
6050 None on error
6051 """
6052 try:
6053 queueName = str( queueName )
6054 prefix = "work-queue-test"
6055 operation = "totalInProgress"
6056 cmdStr = " ".join( [ prefix, queueName, operation ] )
6057 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006058 main.log.debug( self.name + ": work queue unparsed: " + output )
6059 output = output.split( "\r\n" )[ -1 ]
6060 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006061 pattern = r'\d+'
6062 if "Invalid operation name" in output:
6063 main.log.warn( output )
6064 return None
6065 else:
6066 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006067 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006068 except ( AttributeError, TypeError ):
6069 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6070 return None
6071 except Exception:
6072 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006073 main.cleanAndExit()
Jeremy Ronquillo818bc7c2017-08-09 17:14:53 +00006074
6075 def events( self, args='-a' ):
6076 """
6077 Description: Returns events -a command output
6078 Optional:
6079 add other arguments
6080 """
6081 try:
6082 cmdStr = "events"
6083 if args:
6084 cmdStr += " " + args
6085 handle = self.sendline( cmdStr )
6086 assert handle is not None, "Error in sendline"
6087 assert "Command not found:" not in handle, handle
6088 return handle
6089 except AssertionError:
6090 main.log.exception( "" )
6091 return None
6092 except TypeError:
6093 main.log.exception( self.name + ": Object not as expected" )
6094 return None
6095 except pexpect.EOF:
6096 main.log.error( self.name + ": EOF exception found" )
6097 main.log.error( self.name + ": " + self.handle.before )
6098 main.cleanAndExit()
6099 except Exception:
6100 main.log.exception( self.name + ": Uncaught exception!" )
6101 main.cleanAndExit()
6102
6103 def getMaster( self, deviceID ):
6104 """
6105 Description: Obtains current master using "roles" command for a specific deviceID
6106 """
6107 try:
6108 return str( self.getRole( deviceID )[ 'master' ] )
6109 except AssertionError:
6110 main.log.exception( "" )
6111 return None
6112 except TypeError:
6113 main.log.exception( self.name + ": Object not as expected" )
6114 return None
6115 except pexpect.EOF:
6116 main.log.error( self.name + ": EOF exception found" )
6117 main.log.error( self.name + ": " + self.handle.before )
6118 main.cleanAndExit()
6119 except Exception:
6120 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lime6fe3c42017-10-18 16:28:40 -07006121 main.cleanAndExit()
Jon Halla478b852017-12-04 15:00:15 -08006122
6123 def issu( self ):
6124 """
6125 Short summary of In-Service Software Upgrade status
6126
6127 Returns the output of the cli command or None on Error
6128 """
6129 try:
6130 cmdStr = "issu"
6131 handle = self.sendline( cmdStr )
6132 assert handle is not None, "Error in sendline"
6133 assert "Command not found:" not in handle, handle
6134 assert "Unsupported command:" not in handle, handle
6135 return handle
6136 except AssertionError:
6137 main.log.exception( "" )
6138 return None
6139 except TypeError:
6140 main.log.exception( self.name + ": Object not as expected" )
6141 return None
6142 except pexpect.EOF:
6143 main.log.error( self.name + ": EOF exception found" )
6144 main.log.error( self.name + ": " + self.handle.before )
6145 main.cleanAndExit()
6146 except Exception:
6147 main.log.exception( self.name + ": Uncaught exception!" )
6148 main.cleanAndExit()
6149
6150 def issuInit( self ):
6151 """
6152 Initiates an In-Service Software Upgrade
6153
6154 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6155 """
6156 try:
6157 cmdStr = "issu init"
6158 handle = self.sendline( cmdStr )
6159 assert handle is not None, "Error in sendline"
6160 assert "Command not found:" not in handle, handle
6161 assert "Unsupported command:" not in handle, handle
6162 if "Initialized" in handle:
6163 return main.TRUE
6164 else:
6165 return main.FALSE
6166 except AssertionError:
6167 main.log.exception( "" )
6168 return main.ERROR
6169 except TypeError:
6170 main.log.exception( self.name + ": Object not as expected" )
6171 return main.ERROR
6172 except pexpect.EOF:
6173 main.log.error( self.name + ": EOF exception found" )
6174 main.log.error( self.name + ": " + self.handle.before )
6175 main.cleanAndExit()
6176 except Exception:
6177 main.log.exception( self.name + ": Uncaught exception!" )
6178 main.cleanAndExit()
6179
6180 def issuUpgrade( self ):
6181 """
6182 Transitions stores to upgraded nodes
6183
6184 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6185 """
6186 try:
6187 cmdStr = "issu upgrade"
6188 handle = self.sendline( cmdStr )
6189 assert handle is not None, "Error in sendline"
6190 assert "Command not found:" not in handle, handle
6191 assert "Unsupported command:" not in handle, handle
6192 if "Upgraded" in handle:
6193 return main.TRUE
6194 else:
6195 return main.FALSE
6196 except AssertionError:
6197 main.log.exception( "" )
6198 return main.ERROR
6199 except TypeError:
6200 main.log.exception( self.name + ": Object not as expected" )
6201 return main.ERROR
6202 except pexpect.EOF:
6203 main.log.error( self.name + ": EOF exception found" )
6204 main.log.error( self.name + ": " + self.handle.before )
6205 main.cleanAndExit()
6206 except Exception:
6207 main.log.exception( self.name + ": Uncaught exception!" )
6208 main.cleanAndExit()
6209
6210 def issuCommit( self ):
6211 """
6212 Finalizes an In-Service Software Upgrade
6213
6214 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6215 """
6216 try:
6217 cmdStr = "issu commit"
6218 handle = self.sendline( cmdStr )
6219 assert handle is not None, "Error in sendline"
6220 assert "Command not found:" not in handle, handle
6221 assert "Unsupported command:" not in handle, handle
6222 # TODO: Check the version returned by this command
6223 if "Committed version" in handle:
6224 return main.TRUE
6225 else:
6226 return main.FALSE
6227 except AssertionError:
6228 main.log.exception( "" )
6229 return main.ERROR
6230 except TypeError:
6231 main.log.exception( self.name + ": Object not as expected" )
6232 return main.ERROR
6233 except pexpect.EOF:
6234 main.log.error( self.name + ": EOF exception found" )
6235 main.log.error( self.name + ": " + self.handle.before )
6236 main.cleanAndExit()
6237 except Exception:
6238 main.log.exception( self.name + ": Uncaught exception!" )
6239 main.cleanAndExit()
6240
6241 def issuRollback( self ):
6242 """
6243 Rolls back an In-Service Software Upgrade
6244
6245 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6246 """
6247 try:
6248 cmdStr = "issu rollback"
6249 handle = self.sendline( cmdStr )
6250 assert handle is not None, "Error in sendline"
6251 assert "Command not found:" not in handle, handle
6252 assert "Unsupported command:" not in handle, handle
6253 # TODO: Check the version returned by this command
6254 if "Rolled back to version" in handle:
6255 return main.TRUE
6256 else:
6257 return main.FALSE
6258 except AssertionError:
6259 main.log.exception( "" )
6260 return main.ERROR
6261 except TypeError:
6262 main.log.exception( self.name + ": Object not as expected" )
6263 return main.ERROR
6264 except pexpect.EOF:
6265 main.log.error( self.name + ": EOF exception found" )
6266 main.log.error( self.name + ": " + self.handle.before )
6267 main.cleanAndExit()
6268 except Exception:
6269 main.log.exception( self.name + ": Uncaught exception!" )
6270 main.cleanAndExit()
6271
6272 def issuReset( self ):
6273 """
6274 Resets the In-Service Software Upgrade status after a rollback
6275
6276 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6277 """
6278 try:
6279 cmdStr = "issu reset"
6280 handle = self.sendline( cmdStr )
6281 assert handle is not None, "Error in sendline"
6282 assert "Command not found:" not in handle, handle
6283 assert "Unsupported command:" not in handle, handle
6284 # TODO: Check the version returned by this command
6285 if "Reset version" in handle:
6286 return main.TRUE
6287 else:
6288 return main.FALSE
6289 except AssertionError:
6290 main.log.exception( "" )
6291 return main.ERROR
6292 except TypeError:
6293 main.log.exception( self.name + ": Object not as expected" )
6294 return main.ERROR
6295 except pexpect.EOF:
6296 main.log.error( self.name + ": EOF exception found" )
6297 main.log.error( self.name + ": " + self.handle.before )
6298 main.cleanAndExit()
6299 except Exception:
6300 main.log.exception( self.name + ": Uncaught exception!" )
6301 main.cleanAndExit()
6302
6303 def issuStatus( self ):
6304 """
6305 Status of an In-Service Software Upgrade
6306
6307 Returns the output of the cli command or None on Error
6308 """
6309 try:
6310 cmdStr = "issu status"
6311 handle = self.sendline( cmdStr )
6312 assert handle is not None, "Error in sendline"
6313 assert "Command not found:" not in handle, handle
6314 assert "Unsupported command:" not in handle, handle
6315 return handle
6316 except AssertionError:
6317 main.log.exception( "" )
6318 return None
6319 except TypeError:
6320 main.log.exception( self.name + ": Object not as expected" )
6321 return None
6322 except pexpect.EOF:
6323 main.log.error( self.name + ": EOF exception found" )
6324 main.log.error( self.name + ": " + self.handle.before )
6325 main.cleanAndExit()
6326 except Exception:
6327 main.log.exception( self.name + ": Uncaught exception!" )
6328 main.cleanAndExit()
6329
6330 def issuVersion( self ):
6331 """
6332 Get the version of an In-Service Software Upgrade
6333
6334 Returns the output of the cli command or None on Error
6335 """
6336 try:
6337 cmdStr = "issu version"
6338 handle = self.sendline( cmdStr )
6339 assert handle is not None, "Error in sendline"
6340 assert "Command not found:" not in handle, handle
6341 assert "Unsupported command:" not in handle, handle
6342 return handle
6343 except AssertionError:
6344 main.log.exception( "" )
6345 return None
6346 except TypeError:
6347 main.log.exception( self.name + ": Object not as expected" )
6348 return None
6349 except pexpect.EOF:
6350 main.log.error( self.name + ": EOF exception found" )
6351 main.log.error( self.name + ": " + self.handle.before )
6352 main.cleanAndExit()
6353 except Exception:
6354 main.log.exception( self.name + ": Uncaught exception!" )
6355 main.cleanAndExit()
You Wange24d6272018-03-27 21:18:50 -07006356
6357 def mcastJoin( self, sIP, groupIP, sPort, dPorts ):
6358 """
6359 Create a multicast route by calling 'mcast-join' command
6360 sIP: source IP of the multicast route
6361 groupIP: group IP of the multicast route
6362 sPort: source port (e.g. of:0000000000000001/3 ) of the multicast route
6363 dPorts: a list of destination ports of the multicast route
6364 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6365 """
6366 try:
6367 cmdStr = "mcast-join"
6368 cmdStr += " " + str( sIP )
6369 cmdStr += " " + str( groupIP )
6370 cmdStr += " " + str( sPort )
6371 assert isinstance( dPorts, list )
6372 for dPort in dPorts:
6373 cmdStr += " " + str( dPort )
6374 handle = self.sendline( cmdStr )
6375 assert handle is not None, "Error in sendline"
6376 assert "Command not found:" not in handle, handle
6377 assert "Unsupported command:" not in handle, handle
6378 assert "Error executing command" not in handle, handle
6379 if "Added the mcast route" in handle:
6380 return main.TRUE
6381 else:
6382 return main.FALSE
6383 except AssertionError:
6384 main.log.exception( "" )
6385 return None
6386 except TypeError:
6387 main.log.exception( self.name + ": Object not as expected" )
6388 return None
6389 except pexpect.EOF:
6390 main.log.error( self.name + ": EOF exception found" )
6391 main.log.error( self.name + ": " + self.handle.before )
6392 main.cleanAndExit()
6393 except Exception:
6394 main.log.exception( self.name + ": Uncaught exception!" )
6395 main.cleanAndExit()
6396
6397 def mcastDelete( self, sIP, groupIP, dPorts ):
6398 """
6399 Delete a multicast route by calling 'mcast-delete' command
6400 sIP: source IP of the multicast route
6401 groupIP: group IP of the multicast route
6402 dPorts: a list of destination ports of the multicast route
6403 Returns main.TRUE if mcast route is deleted; Otherwise main.FALSE
6404 """
6405 try:
6406 cmdStr = "mcast-delete"
6407 cmdStr += " " + str( sIP )
6408 cmdStr += " " + str( groupIP )
6409 assert isinstance( dPorts, list )
6410 for dPort in dPorts:
6411 cmdStr += " " + str( dPort )
6412 handle = self.sendline( cmdStr )
6413 assert handle is not None, "Error in sendline"
6414 assert "Command not found:" not in handle, handle
6415 assert "Unsupported command:" not in handle, handle
6416 assert "Error executing command" not in handle, handle
6417 if "Updated the mcast route" in handle:
6418 return main.TRUE
6419 else:
6420 return main.FALSE
6421 except AssertionError:
6422 main.log.exception( "" )
6423 return None
6424 except TypeError:
6425 main.log.exception( self.name + ": Object not as expected" )
6426 return None
6427 except pexpect.EOF:
6428 main.log.error( self.name + ": EOF exception found" )
6429 main.log.error( self.name + ": " + self.handle.before )
6430 main.cleanAndExit()
6431 except Exception:
6432 main.log.exception( self.name + ": Uncaught exception!" )
6433 main.cleanAndExit()
6434
6435 def mcastHostJoin( self, sAddr, gAddr, srcs, sinks ):
6436 """
6437 Create a multicast route by calling 'mcast-host-join' command
6438 sAddr: we can provide * for ASM or a specific address for SSM
6439 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006440 srcs: a list of HostId of the sources e.g. ["00:AA:00:00:00:01/None"]
You Wange24d6272018-03-27 21:18:50 -07006441 sinks: a list of HostId of the sinks e.g. ["00:AA:00:00:01:05/40"]
6442 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6443 """
6444 try:
6445 cmdStr = "mcast-host-join"
6446 cmdStr += " -sAddr " + str( sAddr )
6447 cmdStr += " -gAddr " + str( gAddr )
6448 assert isinstance( srcs, list )
6449 for src in srcs:
6450 cmdStr += " -srcs " + str( src )
6451 assert isinstance( sinks, list )
6452 for sink in sinks:
6453 cmdStr += " -sinks " + str( sink )
6454 handle = self.sendline( cmdStr )
6455 assert handle is not None, "Error in sendline"
6456 assert "Command not found:" not in handle, handle
6457 assert "Unsupported command:" not in handle, handle
6458 assert "Error executing command" not in handle, handle
6459 if "Added the mcast route" in handle:
6460 return main.TRUE
6461 else:
6462 return main.FALSE
6463 except AssertionError:
6464 main.log.exception( "" )
6465 return None
6466 except TypeError:
6467 main.log.exception( self.name + ": Object not as expected" )
6468 return None
6469 except pexpect.EOF:
6470 main.log.error( self.name + ": EOF exception found" )
6471 main.log.error( self.name + ": " + self.handle.before )
6472 main.cleanAndExit()
6473 except Exception:
6474 main.log.exception( self.name + ": Uncaught exception!" )
6475 main.cleanAndExit()
6476
6477 def mcastHostDelete( self, sAddr, gAddr, host=None ):
6478 """
6479 Delete multicast sink(s) by calling 'mcast-host-delete' command
6480 sAddr: we can provide * for ASM or a specific address for SSM
6481 gAddr: specifies multicast group address
You Wangc02d8352018-04-17 16:42:10 -07006482 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
You Wange24d6272018-03-27 21:18:50 -07006483 will delete the route if not specified
6484 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6485 """
6486 try:
6487 cmdStr = "mcast-host-delete"
6488 cmdStr += " -sAddr " + str( sAddr )
6489 cmdStr += " -gAddr " + str( gAddr )
6490 if host:
6491 cmdStr += " -h " + str( host )
6492 handle = self.sendline( cmdStr )
6493 assert handle is not None, "Error in sendline"
6494 assert "Command not found:" not in handle, handle
6495 assert "Unsupported command:" not in handle, handle
6496 assert "Error executing command" not in handle, handle
6497 if "Updated the mcast route" in handle:
6498 return main.TRUE
6499 elif "Deleted the mcast route" in handle:
6500 return main.TRUE
6501 else:
6502 return main.FALSE
6503 except AssertionError:
6504 main.log.exception( "" )
6505 return None
6506 except TypeError:
6507 main.log.exception( self.name + ": Object not as expected" )
6508 return None
6509 except pexpect.EOF:
6510 main.log.error( self.name + ": EOF exception found" )
6511 main.log.error( self.name + ": " + self.handle.before )
6512 main.cleanAndExit()
6513 except Exception:
6514 main.log.exception( self.name + ": Uncaught exception!" )
6515 main.cleanAndExit()
6516
You Wang547893e2018-05-08 13:34:59 -07006517 def mcastSinkDelete( self, sAddr, gAddr, sink=None ):
6518 """
6519 Delete multicast sink(s) by calling 'mcast-sink-delete' command
6520 sAddr: we can provide * for ASM or a specific address for SSM
6521 gAddr: specifies multicast group address
6522 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
6523 will delete the route if not specified
6524 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6525 """
6526 try:
6527 cmdStr = "mcast-sink-delete"
6528 cmdStr += " -sAddr " + str( sAddr )
6529 cmdStr += " -gAddr " + str( gAddr )
6530 if sink:
6531 cmdStr += " -s " + str( sink )
6532 handle = self.sendline( cmdStr )
6533 assert handle is not None, "Error in sendline"
6534 assert "Command not found:" not in handle, handle
6535 assert "Unsupported command:" not in handle, handle
6536 assert "Error executing command" not in handle, handle
6537 if "Updated the mcast route" in handle:
6538 return main.TRUE
6539 elif "Deleted the mcast route" in handle:
6540 return main.TRUE
6541 else:
6542 return main.FALSE
6543 except AssertionError:
6544 main.log.exception( "" )
6545 return None
6546 except TypeError:
6547 main.log.exception( self.name + ": Object not as expected" )
6548 return None
6549 except pexpect.EOF:
6550 main.log.error( self.name + ": EOF exception found" )
6551 main.log.error( self.name + ": " + self.handle.before )
6552 main.cleanAndExit()
6553 except Exception:
6554 main.log.exception( self.name + ": Uncaught exception!" )
6555 main.cleanAndExit()
6556
You Wange24d6272018-03-27 21:18:50 -07006557 def mcastSourceDelete( self, sAddr, gAddr, srcs=None ):
6558 """
6559 Delete multicast src(s) by calling 'mcast-source-delete' command
6560 sAddr: we can provide * for ASM or a specific address for SSM
6561 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006562 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 -07006563 will delete the route if not specified
6564 Returns main.TRUE if mcast sink is deleted; Otherwise main.FALSE
6565 """
6566 try:
6567 cmdStr = "mcast-source-delete"
6568 cmdStr += " -sAddr " + str( sAddr )
6569 cmdStr += " -gAddr " + str( gAddr )
6570 if srcs:
6571 assert isinstance( srcs, list )
6572 for src in srcs:
6573 cmdStr += " -src " + str( src )
6574 handle = self.sendline( cmdStr )
6575 assert handle is not None, "Error in sendline"
6576 assert "Command not found:" not in handle, handle
6577 assert "Unsupported command:" not in handle, handle
6578 assert "Error executing command" not in handle, handle
6579 if "Updated the mcast route" in handle:
6580 return main.TRUE
6581 elif "Deleted the mcast route" in handle:
6582 return main.TRUE
6583 else:
6584 return main.FALSE
6585 except AssertionError:
6586 main.log.exception( "" )
6587 return None
6588 except TypeError:
6589 main.log.exception( self.name + ": Object not as expected" )
6590 return None
6591 except pexpect.EOF:
6592 main.log.error( self.name + ": EOF exception found" )
6593 main.log.error( self.name + ": " + self.handle.before )
6594 main.cleanAndExit()
6595 except Exception:
6596 main.log.exception( self.name + ": Uncaught exception!" )
6597 main.cleanAndExit()
You Wang5da39c82018-04-26 22:55:08 -07006598
6599 def netcfg( self, jsonFormat=True, args="" ):
6600 """
6601 Run netcfg cli command with given args
6602 """
6603 try:
6604 cmdStr = "netcfg"
6605 if jsonFormat:
6606 cmdStr = cmdStr + " -j"
6607 if args:
6608 cmdStr = cmdStr + " " + str( args )
6609 handle = self.sendline( cmdStr )
6610 assert handle is not None, "Error in sendline"
6611 assert "Command not found:" not in handle, handle
6612 assert "Unsupported command:" not in handle, handle
6613 assert "Error executing command" not in handle, handle
6614 return handle
6615 except AssertionError:
6616 main.log.exception( "" )
6617 return None
6618 except TypeError:
6619 main.log.exception( self.name + ": Object not as expected" )
6620 return None
6621 except pexpect.EOF:
6622 main.log.error( self.name + ": EOF exception found" )
6623 main.log.error( self.name + ": " + self.handle.before )
6624 main.cleanAndExit()
6625 except Exception:
6626 main.log.exception( self.name + ": Uncaught exception!" )
6627 main.cleanAndExit()
6628
You Wang0fa76e72018-05-18 11:33:25 -07006629 def composeT3Command( self, sAddr, dAddr, ipv6=False, verbose=True, simple=False ):
You Wang5da39c82018-04-26 22:55:08 -07006630 """
You Wang54b1d672018-06-11 16:44:13 -07006631 Compose and return a list of t3-troubleshoot cli commands for given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006632 Options:
6633 sAddr: IP address of the source host
6634 dAddr: IP address of the destination host
You Wang0fa76e72018-05-18 11:33:25 -07006635 ipv6: True if hosts are IPv6
6636 verbose: return verbose t3 output if True
6637 simple: compose command for t3-troubleshoot-simple if True
You Wang5da39c82018-04-26 22:55:08 -07006638 """
6639 try:
6640 # Collect information of both hosts from onos
6641 hosts = self.hosts()
6642 hosts = json.loads( hosts )
6643 sHost = None
6644 dHost = None
6645 for host in hosts:
6646 if sAddr in host[ "ipAddresses" ]:
6647 sHost = host
6648 elif dAddr in host[ "ipAddresses" ]:
6649 dHost = host
6650 if sHost and dHost:
6651 break
6652 assert sHost, "Not able to find host with IP {}".format( sAddr )
You Wang54b1d672018-06-11 16:44:13 -07006653 cmdList = []
You Wang5d9527b2018-05-29 17:08:54 -07006654 if simple:
6655 assert dHost, "Not able to find host with IP {}".format( dAddr )
You Wang54b1d672018-06-11 16:44:13 -07006656 cmdStr = "t3-troubleshoot-simple"
6657 if verbose:
6658 cmdStr += " -vv"
6659 if ipv6:
6660 cmdStr += " -et ipv6"
You Wang0fa76e72018-05-18 11:33:25 -07006661 cmdStr += " {}/{} {}/{}".format( sHost[ "mac" ], sHost[ "vlan" ], dHost[ "mac" ], dHost[ "vlan" ] )
You Wang54b1d672018-06-11 16:44:13 -07006662 cmdList.append( cmdStr )
You Wang0fa76e72018-05-18 11:33:25 -07006663 else:
You Wang54b1d672018-06-11 16:44:13 -07006664 for location in sHost[ "locations" ]:
6665 cmdStr = "t3-troubleshoot"
6666 if verbose:
6667 cmdStr += " -vv"
6668 if ipv6:
6669 cmdStr += " -et ipv6"
6670 cmdStr += " -s " + str( sAddr )
6671 cmdStr += " -sp " + str( location[ "elementId" ] ) + "/" + str( location[ "port" ] )
6672 cmdStr += " -sm " + str( sHost[ "mac" ] )
6673 if sHost[ "vlan" ] != "None":
6674 cmdStr += " -vid " + sHost[ "vlan" ]
6675 cmdStr += " -d " + str( dAddr )
6676 netcfg = self.netcfg( args="devices {}".format( location[ "elementId" ] ) )
6677 netcfg = json.loads( netcfg )
6678 assert netcfg, "Failed to get netcfg"
6679 cmdStr += " -dm " + str( netcfg[ "segmentrouting" ][ "routerMac" ] )
6680 cmdList.append( cmdStr )
6681 return cmdList
You Wang5da39c82018-04-26 22:55:08 -07006682 except AssertionError:
6683 main.log.exception( "" )
6684 return None
6685 except ( KeyError, TypeError ):
6686 main.log.exception( self.name + ": Object not as expected" )
6687 return None
6688 except Exception:
6689 main.log.exception( self.name + ": Uncaught exception!" )
6690 main.cleanAndExit()
6691
6692 def t3( self, sAddr, dAddr, ipv6=False ):
6693 """
You Wang54b1d672018-06-11 16:44:13 -07006694 Run t3-troubleshoot cli commands for all posible routes given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006695 Options:
6696 sAddr: IP address of the source host
6697 dAddr: IP address of the destination host
6698 """
6699 try:
You Wang54b1d672018-06-11 16:44:13 -07006700 cmdList = self.composeT3Command( sAddr, dAddr, ipv6 )
6701 assert cmdList is not None, "composeT3Command returned None"
6702 t3Output = ""
6703 for cmdStr in cmdList:
6704 handle = self.sendline( cmdStr )
6705 assert handle is not None, "Error in sendline"
6706 assert "Command not found:" not in handle, handle
6707 assert "Unsupported command:" not in handle, handle
6708 assert "Error executing command" not in handle, handle
6709 assert "Tracing packet" in handle
6710 t3Output += handle
6711 return t3Output
You Wang5da39c82018-04-26 22:55:08 -07006712 except AssertionError:
6713 main.log.exception( "" )
6714 return None
6715 except pexpect.EOF:
6716 main.log.error( self.name + ": EOF exception found" )
6717 main.log.error( self.name + ": " + self.handle.before )
6718 main.cleanAndExit()
6719 except Exception:
6720 main.log.exception( self.name + ": Uncaught exception!" )
6721 main.cleanAndExit()