blob: 490f5841d0023a4467fb69fd075570e0652d5f0c [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 Wang6b5e5ba2019-01-31 15:32:40 -0800639 self.exitFromCmd( self.karafPrompt, 100 )
GlennRCed771242016-01-13 17:02:47 -0800640 return None
Jon Hallc6358dd2015-04-10 12:44:28 -0700641 except IndexError:
642 main.log.exception( self.name + ": Object not as expected" )
Jon Halla495f562016-05-16 18:03:26 -0700643 main.log.debug( "response: {}".format( repr( response ) ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700644 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800645 except TypeError:
646 main.log.exception( self.name + ": Object not as expected" )
647 return None
andrewonlaba18f6bf2014-10-13 19:31:54 -0400648 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800649 main.log.error( self.name + ": EOF exception found" )
650 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700651 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700652 return None
653 else:
Devin Lim44075962017-08-11 10:56:37 -0700654 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800655 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800656 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700657 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700658 return None
659 else:
Devin Lim44075962017-08-11 10:56:37 -0700660 main.cleanAndExit()
andrewonlaba18f6bf2014-10-13 19:31:54 -0400661
Jon Halld5a94fb2018-11-13 14:32:23 -0800662 def lineCount( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False, relaxedRegex=True ):
663 """
664 A wrapper around sendline(). Will return the number of lines returned or None on error
665
666 Required Arguments:
667 cmdStr - String to send to the pexpect session
668
669 Optional Arguments:
670 showResponse - Defaults to False. If True will log the response.
671 debug - Defaults to False. If True, will enable debug logging.
672 timeout - Defaults to 10. Amount of time in seconds for a command to return
673 before a timeout.
674 noExit - Defaults to False. If True, will not exit TestON in the event of a
675 closed channel, but instead return None
676 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.
677
678 Warning: There are no sanity checking to commands sent using this method.
679
680 """
681 try:
682 numLines = self.sendline( cmdStr, showResponse, debug, timeout, noExit, relaxedRegex )
Jon Hall8c9dd1c2018-11-14 15:40:39 -0800683 parsed = re.search( "(\d+)\s+(\d+)", numLines )
684 if not parsed:
685 main.log.error( "Warning, output of karaf's wc may have changed" )
686 return None
687 return parsed.group( 1 )
Jon Halld5a94fb2018-11-13 14:32:23 -0800688 except IndexError:
689 main.log.exception( self.name + ": Object not as expected" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800690 main.log.debug( "response: {}".format( repr( numLines ) ) )
Jon Halld5a94fb2018-11-13 14:32:23 -0800691 return None
692 except TypeError:
693 main.log.exception( self.name + ": Object not as expected" )
694 return None
695 except Exception:
696 main.log.exception( self.name + ": Uncaught exception!" )
697 if noExit:
698 return None
699 else:
700 main.cleanAndExit()
701
kelvin8ec71442015-01-15 16:57:00 -0800702 # IMPORTANT NOTE:
703 # For all cli commands, naming convention should match
kelvin-onlabd3b64892015-01-20 13:26:24 -0800704 # the cli command changing 'a:b' with 'aB'.
705 # Ex ) onos:topology > onosTopology
706 # onos:links > onosLinks
707 # feature:list > featureList
Jon Halle3f39ff2015-01-13 11:50:53 -0800708
kelvin-onlabd3b64892015-01-20 13:26:24 -0800709 def addNode( self, nodeId, ONOSIp, tcpPort="" ):
kelvin8ec71442015-01-15 16:57:00 -0800710 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400711 Adds a new cluster node by ID and address information.
712 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800713 * nodeId
714 * ONOSIp
andrewonlabc2d05aa2014-10-13 16:51:10 -0400715 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800716 * tcpPort
kelvin8ec71442015-01-15 16:57:00 -0800717 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400718 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800719 cmdStr = "add-node " + str( nodeId ) + " " +\
720 str( ONOSIp ) + " " + str( tcpPort )
721 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700722 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800723 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -0800724 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700725 main.log.error( self.name + ": Error in adding node" )
kelvin8ec71442015-01-15 16:57:00 -0800726 main.log.error( handle )
Jon Halle3f39ff2015-01-13 11:50:53 -0800727 return main.FALSE
andrewonlabc2d05aa2014-10-13 16:51:10 -0400728 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800729 main.log.info( "Node " + str( ONOSIp ) + " added" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400730 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800731 except AssertionError:
732 main.log.exception( "" )
733 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800734 except TypeError:
735 main.log.exception( self.name + ": Object not as expected" )
736 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400737 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800738 main.log.error( self.name + ": EOF exception found" )
739 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700740 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800741 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800742 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700743 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400744
kelvin-onlabd3b64892015-01-20 13:26:24 -0800745 def removeNode( self, nodeId ):
kelvin8ec71442015-01-15 16:57:00 -0800746 """
andrewonlab86dc3082014-10-13 18:18:38 -0400747 Removes a cluster by ID
748 Issues command: 'remove-node [<node-id>]'
749 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800750 * nodeId
kelvin8ec71442015-01-15 16:57:00 -0800751 """
andrewonlab86dc3082014-10-13 18:18:38 -0400752 try:
andrewonlab86dc3082014-10-13 18:18:38 -0400753
kelvin-onlabd3b64892015-01-20 13:26:24 -0800754 cmdStr = "remove-node " + str( nodeId )
Jon Hall08f61bc2015-04-13 16:00:30 -0700755 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700756 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800757 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700758 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700759 main.log.error( self.name + ": Error in removing node" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700760 main.log.error( handle )
761 return main.FALSE
762 else:
763 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800764 except AssertionError:
765 main.log.exception( "" )
766 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800767 except TypeError:
768 main.log.exception( self.name + ": Object not as expected" )
769 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400770 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800771 main.log.error( self.name + ": EOF exception found" )
772 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700773 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800774 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800775 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700776 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400777
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700778 def nodes( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800779 """
andrewonlab7c211572014-10-15 16:45:20 -0400780 List the nodes currently visible
781 Issues command: 'nodes'
Jon Hall61282e32015-03-19 11:34:11 -0700782 Optional argument:
783 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800784 """
andrewonlab7c211572014-10-15 16:45:20 -0400785 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700786 cmdStr = "nodes"
Jon Hall61282e32015-03-19 11:34:11 -0700787 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700788 cmdStr += " -j"
789 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700790 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800791 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -0700792 return output
Jon Hallc6793552016-01-19 14:18:37 -0800793 except AssertionError:
794 main.log.exception( "" )
795 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800796 except TypeError:
797 main.log.exception( self.name + ": Object not as expected" )
798 return None
andrewonlab7c211572014-10-15 16:45:20 -0400799 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800800 main.log.error( self.name + ": EOF exception found" )
801 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700802 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800803 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800804 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700805 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400806
kelvin8ec71442015-01-15 16:57:00 -0800807 def topology( self ):
808 """
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700809 Definition:
Jon Hall390696c2015-05-05 17:13:41 -0700810 Returns the output of topology command.
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700811 Return:
812 topology = current ONOS topology
kelvin8ec71442015-01-15 16:57:00 -0800813 """
andrewonlab95ce8322014-10-13 14:12:04 -0400814 try:
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700815 cmdStr = "topology -j"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800816 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800817 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800818 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700819 main.log.info( cmdStr + " returned: " + str( handle ) )
andrewonlab95ce8322014-10-13 14:12:04 -0400820 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800821 except AssertionError:
822 main.log.exception( "" )
Jon Halld4d4b372015-01-28 16:02:41 -0800823 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800824 except TypeError:
825 main.log.exception( self.name + ": Object not as expected" )
826 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400827 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800828 main.log.error( self.name + ": EOF exception found" )
829 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700830 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800831 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800832 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700833 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -0800834
jenkins7ead5a82015-03-13 10:28:21 -0700835 def deviceRemove( self, deviceId ):
836 """
837 Removes particular device from storage
838
839 TODO: refactor this function
840 """
841 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700842 cmdStr = "device-remove " + str( deviceId )
843 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800844 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800845 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700846 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700847 main.log.error( self.name + ": Error in removing device" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700848 main.log.error( handle )
849 return main.FALSE
850 else:
851 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800852 except AssertionError:
853 main.log.exception( "" )
854 return None
jenkins7ead5a82015-03-13 10:28:21 -0700855 except TypeError:
856 main.log.exception( self.name + ": Object not as expected" )
857 return None
858 except pexpect.EOF:
859 main.log.error( self.name + ": EOF exception found" )
860 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700861 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700862 except Exception:
863 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700864 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700865
You Wang3b9689a2018-08-30 12:24:00 -0700866 def devices( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -0800867 """
Jon Hall7b02d952014-10-17 20:14:54 -0400868 Lists all infrastructure devices or switches
andrewonlab86dc3082014-10-13 18:18:38 -0400869 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800870 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800871 """
andrewonlab86dc3082014-10-13 18:18:38 -0400872 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700873 cmdStr = "devices"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800874 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700875 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -0700876 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -0800877 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800878 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700879 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800880 except AssertionError:
881 main.log.exception( "" )
882 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800883 except TypeError:
884 main.log.exception( self.name + ": Object not as expected" )
885 return None
andrewonlab7c211572014-10-15 16:45:20 -0400886 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800887 main.log.error( self.name + ": EOF exception found" )
888 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700889 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800890 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800891 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700892 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400893
kelvin-onlabd3b64892015-01-20 13:26:24 -0800894 def balanceMasters( self ):
kelvin8ec71442015-01-15 16:57:00 -0800895 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800896 This balances the devices across all controllers
897 by issuing command: 'onos> onos:balance-masters'
898 If required this could be extended to return devices balanced output.
kelvin8ec71442015-01-15 16:57:00 -0800899 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800900 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800901 cmdStr = "onos:balance-masters"
Jon Hallc6358dd2015-04-10 12:44:28 -0700902 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800903 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800904 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700905 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700906 main.log.error( self.name + ": Error in balancing masters" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700907 main.log.error( handle )
908 return main.FALSE
909 else:
910 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800911 except AssertionError:
912 main.log.exception( "" )
913 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800914 except TypeError:
915 main.log.exception( self.name + ": Object not as expected" )
916 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800917 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800918 main.log.error( self.name + ": EOF exception found" )
919 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700920 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800921 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800922 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700923 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800924
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000925 def checkMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700926 """
927 Returns the output of the masters command.
928 Optional argument:
929 * jsonFormat - boolean indicating if you want output in json
930 """
931 try:
932 cmdStr = "onos:masters"
933 if jsonFormat:
934 cmdStr += " -j"
935 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700936 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800937 assert "Command not found:" not in output, output
acsmars24950022015-07-30 18:00:43 -0700938 return output
Jon Hallc6793552016-01-19 14:18:37 -0800939 except AssertionError:
940 main.log.exception( "" )
941 return None
acsmars24950022015-07-30 18:00:43 -0700942 except TypeError:
943 main.log.exception( self.name + ": Object not as expected" )
944 return None
945 except pexpect.EOF:
946 main.log.error( self.name + ": EOF exception found" )
947 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700948 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700949 except Exception:
950 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700951 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700952
Jon Hallc6793552016-01-19 14:18:37 -0800953 def checkBalanceMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700954 """
955 Uses the master command to check that the devices' leadership
956 is evenly divided
957
958 Dependencies: checkMasters() and summary()
959
Jon Hall6509dbf2016-06-21 17:01:17 -0700960 Returns main.TRUE if the devices are balanced
961 Returns main.FALSE if the devices are unbalanced
acsmars24950022015-07-30 18:00:43 -0700962 Exits on Exception
963 Returns None on TypeError
964 """
965 try:
Jon Hallc6793552016-01-19 14:18:37 -0800966 summaryOutput = self.summary()
967 totalDevices = json.loads( summaryOutput )[ "devices" ]
968 except ( TypeError, ValueError ):
969 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summaryOutput ) )
970 return None
971 try:
acsmars24950022015-07-30 18:00:43 -0700972 totalOwnedDevices = 0
Jon Hallc6793552016-01-19 14:18:37 -0800973 mastersOutput = self.checkMasters()
974 masters = json.loads( mastersOutput )
acsmars24950022015-07-30 18:00:43 -0700975 first = masters[ 0 ][ "size" ]
976 for master in masters:
977 totalOwnedDevices += master[ "size" ]
978 if master[ "size" ] > first + 1 or master[ "size" ] < first - 1:
979 main.log.error( "Mastership not balanced" )
980 main.log.info( "\n" + self.checkMasters( False ) )
981 return main.FALSE
Jon Halle0f0b342017-04-18 11:43:47 -0700982 main.log.info( "Mastership balanced between " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700983 str( len( masters ) ) + " masters" )
acsmars24950022015-07-30 18:00:43 -0700984 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800985 except ( TypeError, ValueError ):
986 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, mastersOutput ) )
acsmars24950022015-07-30 18:00:43 -0700987 return None
988 except pexpect.EOF:
989 main.log.error( self.name + ": EOF exception found" )
990 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700991 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700992 except Exception:
993 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700994 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700995
YPZhangfebf7302016-05-24 16:45:56 -0700996 def links( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -0800997 """
Jon Halle8217482014-10-17 13:49:14 -0400998 Lists all core links
999 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001000 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001001 """
Jon Halle8217482014-10-17 13:49:14 -04001002 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001003 cmdStr = "links"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001004 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001005 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07001006 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001007 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001008 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001009 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001010 except AssertionError:
1011 main.log.exception( "" )
1012 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001013 except TypeError:
1014 main.log.exception( self.name + ": Object not as expected" )
1015 return None
Jon Halle8217482014-10-17 13:49:14 -04001016 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001017 main.log.error( self.name + ": EOF exception found" )
1018 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001019 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001020 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001021 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001022 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001023
You Wang3b9689a2018-08-30 12:24:00 -07001024 def ports( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -08001025 """
Jon Halle8217482014-10-17 13:49:14 -04001026 Lists all ports
1027 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001028 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001029 """
Jon Halle8217482014-10-17 13:49:14 -04001030 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001031 cmdStr = "ports"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001032 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001033 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -07001034 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001035 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001036 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001037 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001038 except AssertionError:
1039 main.log.exception( "" )
1040 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001041 except TypeError:
1042 main.log.exception( self.name + ": Object not as expected" )
1043 return None
Jon Halle8217482014-10-17 13:49:14 -04001044 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001045 main.log.error( self.name + ": EOF exception found" )
1046 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001047 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001048 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001049 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001050 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001051
kelvin-onlabd3b64892015-01-20 13:26:24 -08001052 def roles( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001053 """
Jon Hall983a1702014-10-28 18:44:22 -04001054 Lists all devices and the controllers with roles assigned to them
1055 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001056 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001057 """
andrewonlab7c211572014-10-15 16:45:20 -04001058 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001059 cmdStr = "roles"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001060 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001061 cmdStr += " -j"
1062 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001063 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001064 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001065 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001066 except AssertionError:
1067 main.log.exception( "" )
1068 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001069 except TypeError:
1070 main.log.exception( self.name + ": Object not as expected" )
1071 return None
Jon Hall983a1702014-10-28 18:44:22 -04001072 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001073 main.log.error( self.name + ": EOF exception found" )
1074 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001075 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001076 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001077 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001078 main.cleanAndExit()
Jon Hall983a1702014-10-28 18:44:22 -04001079
kelvin-onlabd3b64892015-01-20 13:26:24 -08001080 def getRole( self, deviceId ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001081 """
Jon Halle3f39ff2015-01-13 11:50:53 -08001082 Given the a string containing the json representation of the "roles"
1083 cli command and a partial or whole device id, returns a json object
1084 containing the roles output for the first device whose id contains
1085 "device_id"
Jon Hall983a1702014-10-28 18:44:22 -04001086
1087 Returns:
Jon Halle3f39ff2015-01-13 11:50:53 -08001088 A dict of the role assignments for the given device or
1089 None if no match
kelvin8ec71442015-01-15 16:57:00 -08001090 """
Jon Hall983a1702014-10-28 18:44:22 -04001091 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001092 if deviceId is None:
Jon Hall983a1702014-10-28 18:44:22 -04001093 return None
1094 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001095 rawRoles = self.roles()
1096 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001097 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001098 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001099 # print device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001100 if str( deviceId ) in device[ 'id' ]:
Jon Hall983a1702014-10-28 18:44:22 -04001101 return device
1102 return None
Jon Hallc6793552016-01-19 14:18:37 -08001103 except ( TypeError, ValueError ):
1104 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001105 return None
andrewonlab86dc3082014-10-13 18:18:38 -04001106 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001107 main.log.error( self.name + ": EOF exception found" )
1108 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001109 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001110 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001111 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001112 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001113
kelvin-onlabd3b64892015-01-20 13:26:24 -08001114 def rolesNotNull( self ):
kelvin8ec71442015-01-15 16:57:00 -08001115 """
Jon Hall94fd0472014-12-08 11:52:42 -08001116 Iterates through each device and checks if there is a master assigned
1117 Returns: main.TRUE if each device has a master
1118 main.FALSE any device has no master
kelvin8ec71442015-01-15 16:57:00 -08001119 """
Jon Hall94fd0472014-12-08 11:52:42 -08001120 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001121 rawRoles = self.roles()
1122 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001123 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001124 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001125 # print device
1126 if device[ 'master' ] == "none":
1127 main.log.warn( "Device has no master: " + str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08001128 return main.FALSE
1129 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08001130 except ( TypeError, ValueError ):
1131 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001132 return None
Jon Hall94fd0472014-12-08 11:52:42 -08001133 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001134 main.log.error( self.name + ": EOF exception found" )
1135 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001136 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001137 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001138 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001139 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001140
kelvin-onlabd3b64892015-01-20 13:26:24 -08001141 def paths( self, srcId, dstId ):
kelvin8ec71442015-01-15 16:57:00 -08001142 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001143 Returns string of paths, and the cost.
1144 Issues command: onos:paths <src> <dst>
kelvin8ec71442015-01-15 16:57:00 -08001145 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001146 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001147 cmdStr = "onos:paths " + str( srcId ) + " " + str( dstId )
1148 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001149 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001150 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08001151 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001152 main.log.error( self.name + ": Error in getting paths" )
kelvin8ec71442015-01-15 16:57:00 -08001153 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001154 else:
kelvin8ec71442015-01-15 16:57:00 -08001155 path = handle.split( ";" )[ 0 ]
1156 cost = handle.split( ";" )[ 1 ]
1157 return ( path, cost )
Jon Hallc6793552016-01-19 14:18:37 -08001158 except AssertionError:
1159 main.log.exception( "" )
1160 return ( handle, "Error" )
Jon Halld4d4b372015-01-28 16:02:41 -08001161 except TypeError:
1162 main.log.exception( self.name + ": Object not as expected" )
1163 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001164 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001165 main.log.error( self.name + ": EOF exception found" )
1166 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001167 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001168 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001169 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001170 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -08001171
kelvin-onlabd3b64892015-01-20 13:26:24 -08001172 def hosts( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001173 """
Jon Hallffb386d2014-11-21 13:43:38 -08001174 Lists all discovered hosts
Jon Hall42db6dc2014-10-24 19:03:48 -04001175 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001176 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001177 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001178 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001179 cmdStr = "hosts"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001180 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001181 cmdStr += " -j"
1182 handle = self.sendline( cmdStr )
Jeremyd9e4eb12016-04-13 12:09:06 -07001183 if handle:
1184 assert "Command not found:" not in handle, handle
Jon Hallbaf53162015-12-17 17:04:34 -08001185 # TODO: Maybe make this less hardcoded
1186 # ConsistentMap Exceptions
1187 assert "org.onosproject.store.service" not in handle
1188 # Node not leader
1189 assert "java.lang.IllegalStateException" not in handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001190 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001191 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07001192 main.log.exception( self.name + ": Error in processing '" + cmdStr + "' " +
Jeremy Songster6949cea2016-04-19 18:13:18 -07001193 "command: " + str( handle ) )
Jon Hallc6793552016-01-19 14:18:37 -08001194 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001195 except TypeError:
1196 main.log.exception( self.name + ": Object not as expected" )
1197 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001198 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001199 main.log.error( self.name + ": EOF exception found" )
1200 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001201 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001202 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001203 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001204 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001205
kelvin-onlabd3b64892015-01-20 13:26:24 -08001206 def getHost( self, mac ):
kelvin8ec71442015-01-15 16:57:00 -08001207 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001208 Return the first host from the hosts api whose 'id' contains 'mac'
Jon Halle3f39ff2015-01-13 11:50:53 -08001209
Jon Hallefbd9792015-03-05 16:11:36 -08001210 Note: mac must be a colon separated mac address, but could be a
Jon Halle3f39ff2015-01-13 11:50:53 -08001211 partial mac address
1212
Jon Hall42db6dc2014-10-24 19:03:48 -04001213 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08001214 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001215 try:
kelvin8ec71442015-01-15 16:57:00 -08001216 if mac is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04001217 return None
1218 else:
1219 mac = mac
kelvin-onlabd3b64892015-01-20 13:26:24 -08001220 rawHosts = self.hosts()
1221 hostsJson = json.loads( rawHosts )
kelvin8ec71442015-01-15 16:57:00 -08001222 # search json for the host with mac then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001223 for host in hostsJson:
kelvin8ec71442015-01-15 16:57:00 -08001224 # print "%s in %s?" % ( mac, host[ 'id' ] )
Jon Halld4d4b372015-01-28 16:02:41 -08001225 if not host:
1226 pass
1227 elif mac in host[ 'id' ]:
Jon Hall42db6dc2014-10-24 19:03:48 -04001228 return host
1229 return None
Jon Hallc6793552016-01-19 14:18:37 -08001230 except ( TypeError, ValueError ):
1231 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawHosts ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001232 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001233 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001234 main.log.error( self.name + ": EOF exception found" )
1235 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001236 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001237 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001238 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001239 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001240
kelvin-onlabd3b64892015-01-20 13:26:24 -08001241 def getHostsId( self, hostList ):
kelvin8ec71442015-01-15 16:57:00 -08001242 """
1243 Obtain list of hosts
andrewonlab3f0a4af2014-10-17 12:25:14 -04001244 Issues command: 'onos> hosts'
kelvin8ec71442015-01-15 16:57:00 -08001245
andrewonlab3f0a4af2014-10-17 12:25:14 -04001246 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001247 * hostList: List of hosts obtained by Mininet
andrewonlab3f0a4af2014-10-17 12:25:14 -04001248 IMPORTANT:
1249 This function assumes that you started your
kelvin8ec71442015-01-15 16:57:00 -08001250 topology with the option '--mac'.
andrewonlab3f0a4af2014-10-17 12:25:14 -04001251 Furthermore, it assumes that value of VLAN is '-1'
1252 Description:
kelvin8ec71442015-01-15 16:57:00 -08001253 Converts mininet hosts ( h1, h2, h3... ) into
1254 ONOS format ( 00:00:00:00:00:01/-1 , ... )
1255 """
andrewonlab3f0a4af2014-10-17 12:25:14 -04001256 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001257 onosHostList = []
andrewonlab3f0a4af2014-10-17 12:25:14 -04001258
kelvin-onlabd3b64892015-01-20 13:26:24 -08001259 for host in hostList:
kelvin8ec71442015-01-15 16:57:00 -08001260 host = host.replace( "h", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001261 hostHex = hex( int( host ) ).zfill( 12 )
1262 hostHex = str( hostHex ).replace( 'x', '0' )
1263 i = iter( str( hostHex ) )
1264 hostHex = ":".join( a + b for a, b in zip( i, i ) )
1265 hostHex = hostHex + "/-1"
1266 onosHostList.append( hostHex )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001267
kelvin-onlabd3b64892015-01-20 13:26:24 -08001268 return onosHostList
andrewonlab3f0a4af2014-10-17 12:25:14 -04001269
Jon Halld4d4b372015-01-28 16:02:41 -08001270 except TypeError:
1271 main.log.exception( self.name + ": Object not as expected" )
1272 return None
andrewonlab3f0a4af2014-10-17 12:25:14 -04001273 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001274 main.log.error( self.name + ": EOF exception found" )
1275 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001276 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001277 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001278 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001279 main.cleanAndExit()
andrewonlab3e15ead2014-10-15 14:21:34 -04001280
You Wangbc898b82018-05-03 16:22:34 -07001281 def verifyHostLocation( self, hostIp, location ):
1282 """
1283 Description:
1284 Verify the host given is discovered in all locations expected
1285 Required:
1286 hostIp: IP address of the host
1287 location: expected location(s) of the given host. ex. "of:0000000000000005/8"
1288 Could be a string or list
1289 Returns:
1290 main.TRUE if host is discovered on all locations provided
1291 main.FALSE otherwise
1292 """
1293 import json
1294 locations = [ location ] if isinstance( location, str ) else location
1295 assert isinstance( locations, list ), "Wrong type of location: {}".format( type( location ) )
1296 try:
1297 hosts = self.hosts()
1298 hosts = json.loads( hosts )
1299 targetHost = None
1300 for host in hosts:
1301 if hostIp in host[ "ipAddresses" ]:
1302 targetHost = host
You Wangfd80ab42018-05-10 17:21:53 -07001303 assert targetHost, "Not able to find host with IP {}".format( hostIp )
You Wangbc898b82018-05-03 16:22:34 -07001304 result = main.TRUE
1305 locationsDiscovered = [ loc[ "elementId" ] + "/" + loc[ "port" ] for loc in targetHost[ "locations" ] ]
1306 for loc in locations:
1307 discovered = False
1308 for locDiscovered in locationsDiscovered:
You Wang547893e2018-05-08 13:34:59 -07001309 locToMatch = locDiscovered if "/" in loc else locDiscovered.split( "/" )[0]
1310 if loc == locToMatch:
You Wangbc898b82018-05-03 16:22:34 -07001311 main.log.debug( "Host {} discovered with location {}".format( hostIp, loc ) )
You Wang547893e2018-05-08 13:34:59 -07001312 discovered = True
You Wangbc898b82018-05-03 16:22:34 -07001313 break
1314 if discovered:
1315 locationsDiscovered.remove( locDiscovered )
1316 else:
1317 main.log.warn( "Host {} not discovered with location {}".format( hostIp, loc ) )
1318 result = main.FALSE
1319 if locationsDiscovered:
1320 main.log.warn( "Host {} is also discovered with location {}".format( hostIp, locationsDiscovered ) )
1321 result = main.FALSE
1322 return result
1323 except KeyError:
1324 main.log.exception( self.name + ": host data not as expected: " + hosts )
1325 return None
1326 except pexpect.EOF:
1327 main.log.error( self.name + ": EOF exception found" )
1328 main.log.error( self.name + ": " + self.handle.before )
1329 main.cleanAndExit()
1330 except Exception:
1331 main.log.exception( self.name + ": Uncaught exception" )
1332 return None
1333
You Wang53dba1e2018-02-02 17:45:44 -08001334 def verifyHostIp( self, hostList=[], prefix="" ):
1335 """
1336 Description:
1337 Verify that all hosts have IP address assigned to them
1338 Optional:
1339 hostList: If specified, verifications only happen to the hosts
1340 in hostList
1341 prefix: at least one of the ip address assigned to the host
1342 needs to have the specified prefix
1343 Returns:
1344 main.TRUE if all hosts have specific IP address assigned;
1345 main.FALSE otherwise
1346 """
1347 import json
1348 try:
1349 hosts = self.hosts()
1350 hosts = json.loads( hosts )
1351 if not hostList:
1352 hostList = [ host[ "id" ] for host in hosts ]
1353 for host in hosts:
1354 hostId = host[ "id" ]
1355 if hostId not in hostList:
1356 continue
1357 ipList = host[ "ipAddresses" ]
1358 main.log.debug( self.name + ": IP list on host " + str( hostId ) + ": " + str( ipList ) )
1359 if not ipList:
1360 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostId ) )
1361 else:
1362 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
1363 main.log.warn( self.name + ": None of the IPs on host " + str( hostId ) + " has prefix " + str( prefix ) )
1364 else:
1365 main.log.debug( self.name + ": Found matching IP on host " + str( hostId ) )
1366 hostList.remove( hostId )
1367 if hostList:
1368 main.log.warn( self.name + ": failed to verify IP on following hosts: " + str( hostList) )
1369 return main.FALSE
1370 else:
1371 return main.TRUE
1372 except KeyError:
1373 main.log.exception( self.name + ": host data not as expected: " + hosts )
1374 return None
1375 except pexpect.EOF:
1376 main.log.error( self.name + ": EOF exception found" )
1377 main.log.error( self.name + ": " + self.handle.before )
1378 main.cleanAndExit()
1379 except Exception:
1380 main.log.exception( self.name + ": Uncaught exception" )
1381 return None
1382
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001383 def addHostIntent( self, hostIdOne, hostIdTwo, vlanId="", setVlan="", encap="", bandwidth="" ):
kelvin8ec71442015-01-15 16:57:00 -08001384 """
andrewonlabe6745342014-10-17 14:29:13 -04001385 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001386 * hostIdOne: ONOS host id for host1
1387 * hostIdTwo: ONOS host id for host2
Jeremy Songster832f9e92016-05-05 14:30:49 -07001388 Optional:
1389 * vlanId: specify a VLAN id for the intent
Jeremy Songsterff553672016-05-12 17:06:23 -07001390 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001391 * encap: specify an encapsulation type
andrewonlabe6745342014-10-17 14:29:13 -04001392 Description:
Jon Hallefbd9792015-03-05 16:11:36 -08001393 Adds a host-to-host intent ( bidirectional ) by
Jon Hallb1290e82014-11-18 16:17:48 -05001394 specifying the two hosts.
kelvin-onlabfb521662015-02-27 09:52:40 -08001395 Returns:
1396 A string of the intent id or None on Error
kelvin8ec71442015-01-15 16:57:00 -08001397 """
andrewonlabe6745342014-10-17 14:29:13 -04001398 try:
Jeremy Songster832f9e92016-05-05 14:30:49 -07001399 cmdStr = "add-host-intent "
1400 if vlanId:
1401 cmdStr += "-v " + str( vlanId ) + " "
Jeremy Songsterff553672016-05-12 17:06:23 -07001402 if setVlan:
1403 cmdStr += "--setVlan " + str( vlanId ) + " "
Jeremy Songsterc032f162016-08-04 17:14:49 -07001404 if encap:
1405 cmdStr += "--encapsulation " + str( encap ) + " "
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001406 if bandwidth:
1407 cmdStr += "-b " + str( bandwidth ) + " "
Jeremy Songster832f9e92016-05-05 14:30:49 -07001408 cmdStr += str( hostIdOne ) + " " + str( hostIdTwo )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001409 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001410 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001411 assert "Command not found:" not in handle, handle
Hari Krishnaac4e1782015-01-26 12:09:12 -08001412 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001413 main.log.error( self.name + ": Error in adding Host intent" )
Jon Hall61282e32015-03-19 11:34:11 -07001414 main.log.debug( "Response from ONOS was: " + repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001415 return None
Hari Krishnaac4e1782015-01-26 12:09:12 -08001416 else:
1417 main.log.info( "Host intent installed between " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001418 str( hostIdOne ) + " and " + str( hostIdTwo ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001419 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001420 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001421 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001422 else:
1423 main.log.error( "Error, intent ID not found" )
Jon Hall61282e32015-03-19 11:34:11 -07001424 main.log.debug( "Response from ONOS was: " +
1425 repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001426 return None
Jon Hallc6793552016-01-19 14:18:37 -08001427 except AssertionError:
1428 main.log.exception( "" )
1429 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001430 except TypeError:
1431 main.log.exception( self.name + ": Object not as expected" )
1432 return None
andrewonlabe6745342014-10-17 14:29:13 -04001433 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001434 main.log.error( self.name + ": EOF exception found" )
1435 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001436 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001437 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001438 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001439 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04001440
kelvin-onlabd3b64892015-01-20 13:26:24 -08001441 def addOpticalIntent( self, ingressDevice, egressDevice ):
kelvin8ec71442015-01-15 16:57:00 -08001442 """
andrewonlab7b31d232014-10-24 13:31:47 -04001443 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001444 * ingressDevice: device id of ingress device
1445 * egressDevice: device id of egress device
andrewonlab7b31d232014-10-24 13:31:47 -04001446 Optional:
1447 TODO: Still needs to be implemented via dev side
kelvin-onlabfb521662015-02-27 09:52:40 -08001448 Description:
1449 Adds an optical intent by specifying an ingress and egress device
1450 Returns:
1451 A string of the intent id or None on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08001452 """
andrewonlab7b31d232014-10-24 13:31:47 -04001453 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001454 cmdStr = "add-optical-intent " + str( ingressDevice ) +\
1455 " " + str( egressDevice )
1456 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001457 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001458 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08001459 # If error, return error message
Jon Halle3f39ff2015-01-13 11:50:53 -08001460 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001461 main.log.error( self.name + ": Error in adding Optical intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001462 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001463 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001464 main.log.info( "Optical intent installed between " +
1465 str( ingressDevice ) + " and " +
1466 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001467 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001468 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001469 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001470 else:
1471 main.log.error( "Error, intent ID not found" )
1472 return None
Jon Hallc6793552016-01-19 14:18:37 -08001473 except AssertionError:
1474 main.log.exception( "" )
1475 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001476 except TypeError:
1477 main.log.exception( self.name + ": Object not as expected" )
1478 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001479 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001480 main.log.error( self.name + ": EOF exception found" )
1481 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001482 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001483 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001484 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001485 main.cleanAndExit()
andrewonlab7b31d232014-10-24 13:31:47 -04001486
kelvin-onlabd3b64892015-01-20 13:26:24 -08001487 def addPointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001488 self,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001489 ingressDevice,
1490 egressDevice,
1491 portIngress="",
1492 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001493 ethType="",
1494 ethSrc="",
1495 ethDst="",
1496 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001497 lambdaAlloc=False,
alisonda157272016-12-22 01:13:21 -08001498 protected=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001499 ipProto="",
1500 ipSrc="",
1501 ipDst="",
1502 tcpSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001503 tcpDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001504 vlanId="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001505 setVlan="",
1506 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001507 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001508 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001509 * ingressDevice: device id of ingress device
1510 * egressDevice: device id of egress device
andrewonlab289e4b72014-10-21 21:24:18 -04001511 Optional:
1512 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001513 * ethSrc: specify ethSrc ( i.e. src mac addr )
1514 * ethDst: specify ethDst ( i.e. dst mac addr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001515 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001516 * lambdaAlloc: if True, intent will allocate lambda
andrewonlab40ccd8b2014-11-06 16:23:34 -05001517 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001518 * ipProto: specify ip protocol
andrewonlabf77e0cb2014-11-11 17:17:59 -05001519 * ipSrc: specify ip source address
1520 * ipDst: specify ip destination address
1521 * tcpSrc: specify tcp source port
1522 * tcpDst: specify tcp destination port
Jeremy Songster832f9e92016-05-05 14:30:49 -07001523 * vlanId: specify vlan ID
Jeremy Songsterff553672016-05-12 17:06:23 -07001524 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001525 * encap: specify an Encapsulation type to use
andrewonlab4dbb4d82014-10-17 18:22:31 -04001526 Description:
kelvin8ec71442015-01-15 16:57:00 -08001527 Adds a point-to-point intent ( uni-directional ) by
andrewonlab289e4b72014-10-21 21:24:18 -04001528 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001529 Returns:
1530 A string of the intent id or None on error
andrewonlab289e4b72014-10-21 21:24:18 -04001531
Jon Halle3f39ff2015-01-13 11:50:53 -08001532 NOTE: This function may change depending on the
andrewonlab4dbb4d82014-10-17 18:22:31 -04001533 options developers provide for point-to-point
1534 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001535 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001536 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001537 cmd = "add-point-intent"
andrewonlab36af3822014-11-18 17:48:18 -05001538
Jeremy Songsterff553672016-05-12 17:06:23 -07001539 if ethType:
1540 cmd += " --ethType " + str( ethType )
1541 if ethSrc:
1542 cmd += " --ethSrc " + str( ethSrc )
1543 if ethDst:
1544 cmd += " --ethDst " + str( ethDst )
1545 if bandwidth:
1546 cmd += " --bandwidth " + str( bandwidth )
1547 if lambdaAlloc:
1548 cmd += " --lambda "
1549 if ipProto:
1550 cmd += " --ipProto " + str( ipProto )
1551 if ipSrc:
1552 cmd += " --ipSrc " + str( ipSrc )
1553 if ipDst:
1554 cmd += " --ipDst " + str( ipDst )
1555 if tcpSrc:
1556 cmd += " --tcpSrc " + str( tcpSrc )
1557 if tcpDst:
1558 cmd += " --tcpDst " + str( tcpDst )
1559 if vlanId:
1560 cmd += " -v " + str( vlanId )
1561 if setVlan:
1562 cmd += " --setVlan " + str( setVlan )
Jeremy Songsterc032f162016-08-04 17:14:49 -07001563 if encap:
1564 cmd += " --encapsulation " + str( encap )
alisonda157272016-12-22 01:13:21 -08001565 if protected:
1566 cmd += " --protect "
andrewonlab289e4b72014-10-21 21:24:18 -04001567
kelvin8ec71442015-01-15 16:57:00 -08001568 # Check whether the user appended the port
1569 # or provided it as an input
kelvin-onlabd3b64892015-01-20 13:26:24 -08001570 if "/" in ingressDevice:
1571 cmd += " " + str( ingressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001572 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001573 if not portIngress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001574 main.log.error( "You must specify the ingress port" )
kelvin8ec71442015-01-15 16:57:00 -08001575 # TODO: perhaps more meaningful return
kelvin-onlabfb521662015-02-27 09:52:40 -08001576 # Would it make sense to throw an exception and exit
1577 # the test?
1578 return None
andrewonlab36af3822014-11-18 17:48:18 -05001579
kelvin8ec71442015-01-15 16:57:00 -08001580 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001581 str( ingressDevice ) + "/" +\
1582 str( portIngress ) + " "
andrewonlab36af3822014-11-18 17:48:18 -05001583
kelvin-onlabd3b64892015-01-20 13:26:24 -08001584 if "/" in egressDevice:
1585 cmd += " " + str( egressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001586 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001587 if not portEgress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001588 main.log.error( "You must specify the egress port" )
1589 return None
Jon Halle3f39ff2015-01-13 11:50:53 -08001590
kelvin8ec71442015-01-15 16:57:00 -08001591 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001592 str( egressDevice ) + "/" +\
1593 str( portEgress )
kelvin8ec71442015-01-15 16:57:00 -08001594
kelvin-onlab898a6c62015-01-16 14:13:53 -08001595 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001596 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001597 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001598 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001599 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001600 main.log.error( self.name + ": Error in adding point-to-point intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001601 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001602 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001603 # TODO: print out all the options in this message?
1604 main.log.info( "Point-to-point intent installed between " +
1605 str( ingressDevice ) + " and " +
1606 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001607 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001608 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001609 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001610 else:
1611 main.log.error( "Error, intent ID not found" )
1612 return None
Jon Hallc6793552016-01-19 14:18:37 -08001613 except AssertionError:
1614 main.log.exception( "" )
1615 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001616 except TypeError:
1617 main.log.exception( self.name + ": Object not as expected" )
1618 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001619 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001620 main.log.error( self.name + ": EOF exception found" )
1621 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001622 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001623 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001624 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001625 main.cleanAndExit()
andrewonlab4dbb4d82014-10-17 18:22:31 -04001626
kelvin-onlabd3b64892015-01-20 13:26:24 -08001627 def addMultipointToSinglepointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001628 self,
shahshreyac2f97072015-03-19 17:04:29 -07001629 ingressDeviceList,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001630 egressDevice,
shahshreyac2f97072015-03-19 17:04:29 -07001631 portIngressList=None,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001632 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001633 ethType="",
1634 ethSrc="",
1635 ethDst="",
1636 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001637 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001638 ipProto="",
1639 ipSrc="",
1640 ipDst="",
1641 tcpSrc="",
1642 tcpDst="",
1643 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001644 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001645 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001646 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001647 partial=False,
1648 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001649 """
shahshreyad0c80432014-12-04 16:56:05 -08001650 Note:
shahshreya70622b12015-03-19 17:19:00 -07001651 This function assumes the format of all ingress devices
Jon Hallbe379602015-03-24 13:39:32 -07001652 is same. That is, all ingress devices include port numbers
1653 with a "/" or all ingress devices could specify device
1654 ids and port numbers seperately.
shahshreyad0c80432014-12-04 16:56:05 -08001655 Required:
Jon Hallbe379602015-03-24 13:39:32 -07001656 * ingressDeviceList: List of device ids of ingress device
shahshreyac2f97072015-03-19 17:04:29 -07001657 ( Atleast 2 ingress devices required in the list )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001658 * egressDevice: device id of egress device
shahshreyad0c80432014-12-04 16:56:05 -08001659 Optional:
1660 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001661 * ethSrc: specify ethSrc ( i.e. src mac addr )
1662 * ethDst: specify ethDst ( i.e. dst mac addr )
shahshreyad0c80432014-12-04 16:56:05 -08001663 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001664 * lambdaAlloc: if True, intent will allocate lambda
shahshreyad0c80432014-12-04 16:56:05 -08001665 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001666 * ipProto: specify ip protocol
shahshreyad0c80432014-12-04 16:56:05 -08001667 * ipSrc: specify ip source address
1668 * ipDst: specify ip destination address
1669 * tcpSrc: specify tcp source port
1670 * tcpDst: specify tcp destination port
1671 * setEthSrc: action to Rewrite Source MAC Address
1672 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001673 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001674 * setVlan: specify VLAN Id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001675 * encap: specify a type of encapsulation
shahshreyad0c80432014-12-04 16:56:05 -08001676 Description:
kelvin8ec71442015-01-15 16:57:00 -08001677 Adds a multipoint-to-singlepoint intent ( uni-directional ) by
shahshreyad0c80432014-12-04 16:56:05 -08001678 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001679 Returns:
1680 A string of the intent id or None on error
shahshreyad0c80432014-12-04 16:56:05 -08001681
Jon Halle3f39ff2015-01-13 11:50:53 -08001682 NOTE: This function may change depending on the
Jon Hallefbd9792015-03-05 16:11:36 -08001683 options developers provide for multipoint-to-singlepoint
shahshreyad0c80432014-12-04 16:56:05 -08001684 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001685 """
shahshreyad0c80432014-12-04 16:56:05 -08001686 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001687 cmd = "add-multi-to-single-intent"
shahshreyad0c80432014-12-04 16:56:05 -08001688
Jeremy Songsterff553672016-05-12 17:06:23 -07001689 if ethType:
1690 cmd += " --ethType " + str( ethType )
1691 if ethSrc:
1692 cmd += " --ethSrc " + str( ethSrc )
1693 if ethDst:
1694 cmd += " --ethDst " + str( ethDst )
1695 if bandwidth:
1696 cmd += " --bandwidth " + str( bandwidth )
1697 if lambdaAlloc:
1698 cmd += " --lambda "
1699 if ipProto:
1700 cmd += " --ipProto " + str( ipProto )
1701 if ipSrc:
1702 cmd += " --ipSrc " + str( ipSrc )
1703 if ipDst:
1704 cmd += " --ipDst " + str( ipDst )
1705 if tcpSrc:
1706 cmd += " --tcpSrc " + str( tcpSrc )
1707 if tcpDst:
1708 cmd += " --tcpDst " + str( tcpDst )
1709 if setEthSrc:
1710 cmd += " --setEthSrc " + str( setEthSrc )
1711 if setEthDst:
1712 cmd += " --setEthDst " + str( setEthDst )
1713 if vlanId:
1714 cmd += " -v " + str( vlanId )
1715 if setVlan:
1716 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001717 if partial:
1718 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001719 if encap:
1720 cmd += " --encapsulation " + str( encap )
shahshreyad0c80432014-12-04 16:56:05 -08001721
kelvin8ec71442015-01-15 16:57:00 -08001722 # Check whether the user appended the port
1723 # or provided it as an input
shahshreyac2f97072015-03-19 17:04:29 -07001724
1725 if portIngressList is None:
1726 for ingressDevice in ingressDeviceList:
1727 if "/" in ingressDevice:
1728 cmd += " " + str( ingressDevice )
1729 else:
1730 main.log.error( "You must specify " +
Jon Hallbe379602015-03-24 13:39:32 -07001731 "the ingress port" )
shahshreyac2f97072015-03-19 17:04:29 -07001732 # TODO: perhaps more meaningful return
1733 return main.FALSE
shahshreyad0c80432014-12-04 16:56:05 -08001734 else:
Jon Hall71ce4e72015-03-23 14:05:58 -07001735 if len( ingressDeviceList ) == len( portIngressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001736 for ingressDevice, portIngress in zip( ingressDeviceList,
1737 portIngressList ):
shahshreya70622b12015-03-19 17:19:00 -07001738 cmd += " " + \
1739 str( ingressDevice ) + "/" +\
1740 str( portIngress ) + " "
kelvin-onlab38143812015-04-01 15:03:01 -07001741 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001742 main.log.error( "Device list and port list does not " +
1743 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001744 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001745 if "/" in egressDevice:
1746 cmd += " " + str( egressDevice )
shahshreyad0c80432014-12-04 16:56:05 -08001747 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001748 if not portEgress:
kelvin8ec71442015-01-15 16:57:00 -08001749 main.log.error( "You must specify " +
1750 "the egress port" )
shahshreyad0c80432014-12-04 16:56:05 -08001751 return main.FALSE
Jon Halle3f39ff2015-01-13 11:50:53 -08001752
kelvin8ec71442015-01-15 16:57:00 -08001753 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001754 str( egressDevice ) + "/" +\
1755 str( portEgress )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001756 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001757 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001758 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001759 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001760 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001761 main.log.error( self.name + ": Error in adding multipoint-to-singlepoint " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001762 "intent" )
1763 return None
shahshreyad0c80432014-12-04 16:56:05 -08001764 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001765 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001766 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001767 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001768 else:
1769 main.log.error( "Error, intent ID not found" )
1770 return None
Jon Hallc6793552016-01-19 14:18:37 -08001771 except AssertionError:
1772 main.log.exception( "" )
1773 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001774 except TypeError:
1775 main.log.exception( self.name + ": Object not as expected" )
1776 return None
1777 except pexpect.EOF:
1778 main.log.error( self.name + ": EOF exception found" )
1779 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001780 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001781 except Exception:
1782 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001783 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001784
1785 def addSinglepointToMultipointIntent(
1786 self,
1787 ingressDevice,
1788 egressDeviceList,
1789 portIngress="",
1790 portEgressList=None,
1791 ethType="",
1792 ethSrc="",
1793 ethDst="",
1794 bandwidth="",
1795 lambdaAlloc=False,
1796 ipProto="",
1797 ipSrc="",
1798 ipDst="",
1799 tcpSrc="",
1800 tcpDst="",
1801 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001802 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001803 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001804 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001805 partial=False,
1806 encap="" ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001807 """
1808 Note:
1809 This function assumes the format of all egress devices
1810 is same. That is, all egress devices include port numbers
1811 with a "/" or all egress devices could specify device
1812 ids and port numbers seperately.
1813 Required:
1814 * EgressDeviceList: List of device ids of egress device
1815 ( Atleast 2 eress devices required in the list )
1816 * ingressDevice: device id of ingress device
1817 Optional:
1818 * ethType: specify ethType
1819 * ethSrc: specify ethSrc ( i.e. src mac addr )
1820 * ethDst: specify ethDst ( i.e. dst mac addr )
1821 * bandwidth: specify bandwidth capacity of link
1822 * lambdaAlloc: if True, intent will allocate lambda
1823 for the specified intent
1824 * ipProto: specify ip protocol
1825 * ipSrc: specify ip source address
1826 * ipDst: specify ip destination address
1827 * tcpSrc: specify tcp source port
1828 * tcpDst: specify tcp destination port
1829 * setEthSrc: action to Rewrite Source MAC Address
1830 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001831 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001832 * setVlan: specify VLAN ID treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001833 * encap: specify an encapsulation type
kelvin-onlabb9408212015-04-01 13:34:04 -07001834 Description:
1835 Adds a singlepoint-to-multipoint intent ( uni-directional ) by
1836 specifying device id's and optional fields
1837 Returns:
1838 A string of the intent id or None on error
1839
1840 NOTE: This function may change depending on the
1841 options developers provide for singlepoint-to-multipoint
1842 intent via cli
1843 """
1844 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001845 cmd = "add-single-to-multi-intent"
kelvin-onlabb9408212015-04-01 13:34:04 -07001846
Jeremy Songsterff553672016-05-12 17:06:23 -07001847 if ethType:
1848 cmd += " --ethType " + str( ethType )
1849 if ethSrc:
1850 cmd += " --ethSrc " + str( ethSrc )
1851 if ethDst:
1852 cmd += " --ethDst " + str( ethDst )
1853 if bandwidth:
1854 cmd += " --bandwidth " + str( bandwidth )
1855 if lambdaAlloc:
1856 cmd += " --lambda "
1857 if ipProto:
1858 cmd += " --ipProto " + str( ipProto )
1859 if ipSrc:
1860 cmd += " --ipSrc " + str( ipSrc )
1861 if ipDst:
1862 cmd += " --ipDst " + str( ipDst )
1863 if tcpSrc:
1864 cmd += " --tcpSrc " + str( tcpSrc )
1865 if tcpDst:
1866 cmd += " --tcpDst " + str( tcpDst )
1867 if setEthSrc:
1868 cmd += " --setEthSrc " + str( setEthSrc )
1869 if setEthDst:
1870 cmd += " --setEthDst " + str( setEthDst )
1871 if vlanId:
1872 cmd += " -v " + str( vlanId )
1873 if setVlan:
1874 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001875 if partial:
1876 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001877 if encap:
1878 cmd += " --encapsulation " + str( encap )
kelvin-onlabb9408212015-04-01 13:34:04 -07001879
1880 # Check whether the user appended the port
1881 # or provided it as an input
Jon Hall08f61bc2015-04-13 16:00:30 -07001882
kelvin-onlabb9408212015-04-01 13:34:04 -07001883 if "/" in ingressDevice:
1884 cmd += " " + str( ingressDevice )
1885 else:
1886 if not portIngress:
1887 main.log.error( "You must specify " +
1888 "the Ingress port" )
1889 return main.FALSE
1890
1891 cmd += " " +\
1892 str( ingressDevice ) + "/" +\
1893 str( portIngress )
1894
1895 if portEgressList is None:
1896 for egressDevice in egressDeviceList:
1897 if "/" in egressDevice:
1898 cmd += " " + str( egressDevice )
1899 else:
1900 main.log.error( "You must specify " +
1901 "the egress port" )
1902 # TODO: perhaps more meaningful return
1903 return main.FALSE
1904 else:
1905 if len( egressDeviceList ) == len( portEgressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001906 for egressDevice, portEgress in zip( egressDeviceList,
1907 portEgressList ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001908 cmd += " " + \
1909 str( egressDevice ) + "/" +\
1910 str( portEgress )
kelvin-onlab38143812015-04-01 15:03:01 -07001911 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001912 main.log.error( "Device list and port list does not " +
1913 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001914 return main.FALSE
kelvin-onlabb9408212015-04-01 13:34:04 -07001915 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001916 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001917 assert "Command not found:" not in handle, handle
kelvin-onlabb9408212015-04-01 13:34:04 -07001918 # If error, return error message
1919 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001920 main.log.error( self.name + ": Error in adding singlepoint-to-multipoint " +
kelvin-onlabb9408212015-04-01 13:34:04 -07001921 "intent" )
shahshreyac2f97072015-03-19 17:04:29 -07001922 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001923 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001924 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001925 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001926 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001927 else:
1928 main.log.error( "Error, intent ID not found" )
1929 return None
Jon Hallc6793552016-01-19 14:18:37 -08001930 except AssertionError:
1931 main.log.exception( "" )
1932 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001933 except TypeError:
1934 main.log.exception( self.name + ": Object not as expected" )
1935 return None
shahshreyad0c80432014-12-04 16:56:05 -08001936 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001937 main.log.error( self.name + ": EOF exception found" )
1938 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001939 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001940 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001941 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001942 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001943
Hari Krishna9e232602015-04-13 17:29:08 -07001944 def addMplsIntent(
1945 self,
1946 ingressDevice,
1947 egressDevice,
Hari Krishna87a17f12015-04-13 17:42:23 -07001948 ingressPort="",
1949 egressPort="",
Hari Krishna9e232602015-04-13 17:29:08 -07001950 ethType="",
1951 ethSrc="",
1952 ethDst="",
1953 bandwidth="",
1954 lambdaAlloc=False,
1955 ipProto="",
1956 ipSrc="",
1957 ipDst="",
1958 tcpSrc="",
1959 tcpDst="",
Hari Krishna87a17f12015-04-13 17:42:23 -07001960 ingressLabel="",
Hari Krishnadfff6672015-04-13 17:53:27 -07001961 egressLabel="",
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001962 priority="" ):
Hari Krishna9e232602015-04-13 17:29:08 -07001963 """
1964 Required:
1965 * ingressDevice: device id of ingress device
1966 * egressDevice: device id of egress device
1967 Optional:
1968 * ethType: specify ethType
1969 * ethSrc: specify ethSrc ( i.e. src mac addr )
1970 * ethDst: specify ethDst ( i.e. dst mac addr )
1971 * bandwidth: specify bandwidth capacity of link
1972 * lambdaAlloc: if True, intent will allocate lambda
1973 for the specified intent
1974 * ipProto: specify ip protocol
1975 * ipSrc: specify ip source address
1976 * ipDst: specify ip destination address
1977 * tcpSrc: specify tcp source port
1978 * tcpDst: specify tcp destination port
1979 * ingressLabel: Ingress MPLS label
1980 * egressLabel: Egress MPLS label
1981 Description:
1982 Adds MPLS intent by
1983 specifying device id's and optional fields
1984 Returns:
1985 A string of the intent id or None on error
1986
1987 NOTE: This function may change depending on the
1988 options developers provide for MPLS
1989 intent via cli
1990 """
1991 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001992 cmd = "add-mpls-intent"
Hari Krishna9e232602015-04-13 17:29:08 -07001993
Jeremy Songsterff553672016-05-12 17:06:23 -07001994 if ethType:
1995 cmd += " --ethType " + str( ethType )
1996 if ethSrc:
1997 cmd += " --ethSrc " + str( ethSrc )
1998 if ethDst:
1999 cmd += " --ethDst " + str( ethDst )
2000 if bandwidth:
2001 cmd += " --bandwidth " + str( bandwidth )
2002 if lambdaAlloc:
2003 cmd += " --lambda "
2004 if ipProto:
2005 cmd += " --ipProto " + str( ipProto )
2006 if ipSrc:
2007 cmd += " --ipSrc " + str( ipSrc )
2008 if ipDst:
2009 cmd += " --ipDst " + str( ipDst )
2010 if tcpSrc:
2011 cmd += " --tcpSrc " + str( tcpSrc )
2012 if tcpDst:
2013 cmd += " --tcpDst " + str( tcpDst )
2014 if ingressLabel:
2015 cmd += " --ingressLabel " + str( ingressLabel )
2016 if egressLabel:
2017 cmd += " --egressLabel " + str( egressLabel )
2018 if priority:
2019 cmd += " --priority " + str( priority )
Hari Krishna9e232602015-04-13 17:29:08 -07002020
2021 # Check whether the user appended the port
2022 # or provided it as an input
2023 if "/" in ingressDevice:
2024 cmd += " " + str( ingressDevice )
2025 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002026 if not ingressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002027 main.log.error( "You must specify the ingress port" )
2028 return None
2029
2030 cmd += " " + \
2031 str( ingressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002032 str( ingressPort ) + " "
Hari Krishna9e232602015-04-13 17:29:08 -07002033
2034 if "/" in egressDevice:
2035 cmd += " " + str( egressDevice )
2036 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002037 if not egressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002038 main.log.error( "You must specify the egress port" )
2039 return None
2040
2041 cmd += " " +\
2042 str( egressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002043 str( egressPort )
Hari Krishna9e232602015-04-13 17:29:08 -07002044
2045 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08002046 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002047 assert "Command not found:" not in handle, handle
Hari Krishna9e232602015-04-13 17:29:08 -07002048 # If error, return error message
2049 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002050 main.log.error( self.name + ": Error in adding mpls intent" )
Hari Krishna9e232602015-04-13 17:29:08 -07002051 return None
2052 else:
2053 # TODO: print out all the options in this message?
2054 main.log.info( "MPLS intent installed between " +
2055 str( ingressDevice ) + " and " +
2056 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002057 match = re.search( 'id=0x([\da-f]+),', handle )
Hari Krishna9e232602015-04-13 17:29:08 -07002058 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002059 return match.group()[ 3:-1 ]
Hari Krishna9e232602015-04-13 17:29:08 -07002060 else:
2061 main.log.error( "Error, intent ID not found" )
2062 return None
Jon Hallc6793552016-01-19 14:18:37 -08002063 except AssertionError:
2064 main.log.exception( "" )
2065 return None
Hari Krishna9e232602015-04-13 17:29:08 -07002066 except TypeError:
2067 main.log.exception( self.name + ": Object not as expected" )
2068 return None
2069 except pexpect.EOF:
2070 main.log.error( self.name + ": EOF exception found" )
2071 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002072 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002073 except Exception:
2074 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002075 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002076
Jon Hallefbd9792015-03-05 16:11:36 -08002077 def removeIntent( self, intentId, app='org.onosproject.cli',
2078 purge=False, sync=False ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002079 """
shahshreya1c818fc2015-02-26 13:44:08 -08002080 Remove intent for specified application id and intent id
Jon Hall61282e32015-03-19 11:34:11 -07002081 Optional args:-
shahshreya1c818fc2015-02-26 13:44:08 -08002082 -s or --sync: Waits for the removal before returning
Jon Hall61282e32015-03-19 11:34:11 -07002083 -p or --purge: Purge the intent from the store after removal
2084
Jon Halle3f39ff2015-01-13 11:50:53 -08002085 Returns:
Jon Hall6509dbf2016-06-21 17:01:17 -07002086 main.FALSE on error and
Jon Halle3f39ff2015-01-13 11:50:53 -08002087 cli output otherwise
kelvin-onlab898a6c62015-01-16 14:13:53 -08002088 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002089 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002090 cmdStr = "remove-intent"
shahshreya1c818fc2015-02-26 13:44:08 -08002091 if purge:
2092 cmdStr += " -p"
2093 if sync:
2094 cmdStr += " -s"
2095
2096 cmdStr += " " + app + " " + str( intentId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002097 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002098 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002099 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08002100 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002101 main.log.error( self.name + ": Error in removing intent" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002102 return main.FALSE
andrewonlab9a50dfe2014-10-17 17:22:31 -04002103 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002104 # TODO: Should this be main.TRUE
2105 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002106 except AssertionError:
2107 main.log.exception( "" )
2108 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002109 except TypeError:
2110 main.log.exception( self.name + ": Object not as expected" )
2111 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002112 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002113 main.log.error( self.name + ": EOF exception found" )
2114 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002115 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002116 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002117 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002118 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04002119
YPZhangfebf7302016-05-24 16:45:56 -07002120 def removeAllIntents( self, purge=False, sync=False, app='org.onosproject.cli', timeout=30 ):
Jeremy42df2e72016-02-23 16:37:46 -08002121 """
2122 Description:
2123 Remove all the intents
2124 Optional args:-
2125 -s or --sync: Waits for the removal before returning
2126 -p or --purge: Purge the intent from the store after removal
2127 Returns:
2128 Returns main.TRUE if all intents are removed, otherwise returns
2129 main.FALSE; Returns None for exception
2130 """
2131 try:
2132 cmdStr = "remove-intent"
2133 if purge:
2134 cmdStr += " -p"
2135 if sync:
2136 cmdStr += " -s"
2137
2138 cmdStr += " " + app
YPZhangfebf7302016-05-24 16:45:56 -07002139 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08002140 assert handle is not None, "Error in sendline"
Jeremy42df2e72016-02-23 16:37:46 -08002141 assert "Command not found:" not in handle, handle
2142 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002143 main.log.error( self.name + ": Error in removing intent" )
Jeremy42df2e72016-02-23 16:37:46 -08002144 return main.FALSE
2145 else:
2146 return main.TRUE
2147 except AssertionError:
2148 main.log.exception( "" )
2149 return None
2150 except TypeError:
2151 main.log.exception( self.name + ": Object not as expected" )
2152 return None
2153 except pexpect.EOF:
2154 main.log.error( self.name + ": EOF exception found" )
2155 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002156 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002157 except Exception:
2158 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002159 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002160
Hari Krishnaacabd5a2015-07-01 17:10:19 -07002161 def purgeWithdrawnIntents( self ):
Hari Krishna0ce0e152015-06-23 09:55:29 -07002162 """
2163 Purges all WITHDRAWN Intents
2164 """
2165 try:
2166 cmdStr = "purge-intents"
2167 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002168 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002169 assert "Command not found:" not in handle, handle
Hari Krishna0ce0e152015-06-23 09:55:29 -07002170 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002171 main.log.error( self.name + ": Error in purging intents" )
Hari Krishna0ce0e152015-06-23 09:55:29 -07002172 return main.FALSE
2173 else:
2174 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002175 except AssertionError:
2176 main.log.exception( "" )
2177 return None
Hari Krishna0ce0e152015-06-23 09:55:29 -07002178 except TypeError:
2179 main.log.exception( self.name + ": Object not as expected" )
2180 return None
2181 except pexpect.EOF:
2182 main.log.error( self.name + ": EOF exception found" )
2183 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002184 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002185 except Exception:
2186 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002187 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002188
Devin Lime6fe3c42017-10-18 16:28:40 -07002189 def wipeout( self ):
2190 """
2191 Wipe out the flows,intents,links,devices,hosts, and groups from the ONOS.
2192 """
2193 try:
2194 cmdStr = "wipe-out please"
2195 handle = self.sendline( cmdStr, timeout=60 )
2196 assert handle is not None, "Error in sendline"
2197 assert "Command not found:" not in handle, handle
2198 return main.TRUE
2199 except AssertionError:
2200 main.log.exception( "" )
2201 return None
2202 except TypeError:
2203 main.log.exception( self.name + ": Object not as expected" )
2204 return None
2205 except pexpect.EOF:
2206 main.log.error( self.name + ": EOF exception found" )
2207 main.log.error( self.name + ": " + self.handle.before )
2208 main.cleanAndExit()
2209 except Exception:
2210 main.log.exception( self.name + ": Uncaught exception!" )
2211 main.cleanAndExit()
2212
kelvin-onlabd3b64892015-01-20 13:26:24 -08002213 def routes( self, jsonFormat=False ):
kelvin8ec71442015-01-15 16:57:00 -08002214 """
kelvin-onlab898a6c62015-01-16 14:13:53 -08002215 NOTE: This method should be used after installing application:
2216 onos-app-sdnip
pingping-lin8b306ac2014-11-17 18:13:51 -08002217 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002218 * jsonFormat: enable output formatting in json
pingping-lin8b306ac2014-11-17 18:13:51 -08002219 Description:
2220 Obtain all routes in the system
kelvin8ec71442015-01-15 16:57:00 -08002221 """
pingping-lin8b306ac2014-11-17 18:13:51 -08002222 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002223 cmdStr = "routes"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002224 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002225 cmdStr += " -j"
2226 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002227 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002228 assert "Command not found:" not in handle, handle
pingping-lin8b306ac2014-11-17 18:13:51 -08002229 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002230 except AssertionError:
2231 main.log.exception( "" )
2232 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002233 except TypeError:
2234 main.log.exception( self.name + ": Object not as expected" )
2235 return None
pingping-lin8b306ac2014-11-17 18:13:51 -08002236 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002237 main.log.error( self.name + ": EOF exception found" )
2238 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002239 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002240 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002241 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002242 main.cleanAndExit()
pingping-lin8b306ac2014-11-17 18:13:51 -08002243
pingping-lin54b03372015-08-13 14:43:10 -07002244 def ipv4RouteNumber( self ):
2245 """
2246 NOTE: This method should be used after installing application:
2247 onos-app-sdnip
2248 Description:
2249 Obtain the total IPv4 routes number in the system
2250 """
2251 try:
Pratik Parab57963572017-05-09 11:37:54 -07002252 cmdStr = "routes -j"
pingping-lin54b03372015-08-13 14:43:10 -07002253 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002254 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002255 assert "Command not found:" not in handle, handle
pingping-lin54b03372015-08-13 14:43:10 -07002256 jsonResult = json.loads( handle )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002257 return len( jsonResult[ 'routes4' ] )
Jon Hallc6793552016-01-19 14:18:37 -08002258 except AssertionError:
2259 main.log.exception( "" )
2260 return None
2261 except ( TypeError, ValueError ):
2262 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002263 return None
2264 except pexpect.EOF:
2265 main.log.error( self.name + ": EOF exception found" )
2266 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002267 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002268 except Exception:
2269 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002270 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002271
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002272 # =============Function to check Bandwidth allocation========
Jon Hall0e240372018-05-02 11:21:57 -07002273 def allocations( self, jsonFormat = True ):
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002274 """
2275 Description:
2276 Obtain Bandwidth Allocation Information from ONOS cli.
2277 """
2278 try:
2279 cmdStr = "allocations"
2280 if jsonFormat:
2281 cmdStr += " -j"
Jon Hall0e240372018-05-02 11:21:57 -07002282 handle = self.sendline( cmdStr, timeout=300 )
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002283 assert handle is not None, "Error in sendline"
2284 assert "Command not found:" not in handle, handle
2285 return handle
2286 except AssertionError:
2287 main.log.exception( "" )
2288 return None
2289 except ( TypeError, ValueError ):
2290 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
2291 return None
2292 except pexpect.EOF:
2293 main.log.error( self.name + ": EOF exception found" )
2294 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002295 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002296 except Exception:
2297 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002298 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002299
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002300 def intents( self, jsonFormat = True, summary = False, **intentargs ):
kelvin8ec71442015-01-15 16:57:00 -08002301 """
andrewonlabe6745342014-10-17 14:29:13 -04002302 Description:
Jon Hallff566d52016-01-15 14:45:36 -08002303 Obtain intents from the ONOS cli.
2304 Optional:
2305 * jsonFormat: Enable output formatting in json, default to True
2306 * summary: Whether only output the intent summary, defaults to False
2307 * type: Only output a certain type of intent. This options is valid
2308 only when jsonFormat is True and summary is True.
kelvin-onlab898a6c62015-01-16 14:13:53 -08002309 """
andrewonlabe6745342014-10-17 14:29:13 -04002310 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002311 cmdStr = "intents"
pingping-lin8244a3b2015-09-16 13:36:56 -07002312 if summary:
2313 cmdStr += " -s"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002314 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002315 cmdStr += " -j"
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002316 handle = self.sendline( cmdStr, timeout=300 )
You Wangb5a55f72017-03-03 12:51:05 -08002317 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002318 assert "Command not found:" not in handle, handle
pingping-lin8244a3b2015-09-16 13:36:56 -07002319 args = utilities.parse_args( [ "TYPE" ], **intentargs )
acsmars5b5fbaf2015-09-18 10:38:20 -07002320 if "TYPE" in args.keys():
Jon Hallff566d52016-01-15 14:45:36 -08002321 intentType = args[ "TYPE" ]
acsmars5b5fbaf2015-09-18 10:38:20 -07002322 else:
Jon Hallff566d52016-01-15 14:45:36 -08002323 intentType = ""
2324 # IF we want the summary of a specific intent type
2325 if jsonFormat and summary and ( intentType != "" ):
pingping-lin8244a3b2015-09-16 13:36:56 -07002326 jsonResult = json.loads( handle )
Jon Hallff566d52016-01-15 14:45:36 -08002327 if intentType in jsonResult.keys():
2328 return jsonResult[ intentType ]
pingping-lin8244a3b2015-09-16 13:36:56 -07002329 else:
Jon Hallff566d52016-01-15 14:45:36 -08002330 main.log.error( "unknown TYPE, returning all types of intents" )
pingping-lin8244a3b2015-09-16 13:36:56 -07002331 return handle
2332 else:
2333 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002334 except AssertionError:
2335 main.log.exception( "" )
2336 return None
2337 except ( TypeError, ValueError ):
2338 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002339 return None
2340 except pexpect.EOF:
2341 main.log.error( self.name + ": EOF exception found" )
2342 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002343 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002344 except Exception:
2345 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002346 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002347
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002348 def getIntentState( self, intentsId, intentsJson=None ):
kelvin-onlab54400a92015-02-26 18:05:51 -08002349 """
You Wangfdcbfc42016-05-16 12:16:53 -07002350 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002351 Gets intent state. Accepts a single intent ID (string type) or a
You Wangfdcbfc42016-05-16 12:16:53 -07002352 list of intent IDs.
2353 Parameters:
2354 intentsId: intent ID, both string type and list type are acceptable
kelvin-onlab54400a92015-02-26 18:05:51 -08002355 intentsJson: parsed json object from the onos:intents api
You Wangfdcbfc42016-05-16 12:16:53 -07002356 Returns:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002357 Returns the state (string type) of the ID if a single intent ID is
You Wangfdcbfc42016-05-16 12:16:53 -07002358 accepted.
2359 Returns a list of dictionaries if a list of intent IDs is accepted,
2360 and each dictionary maps 'id' to the Intent ID and 'state' to
2361 corresponding intent state.
kelvin-onlab54400a92015-02-26 18:05:51 -08002362 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002363
kelvin-onlab54400a92015-02-26 18:05:51 -08002364 try:
2365 state = "State is Undefined"
2366 if not intentsJson:
Jon Hallc6793552016-01-19 14:18:37 -08002367 rawJson = self.intents()
kelvin-onlab54400a92015-02-26 18:05:51 -08002368 else:
Jon Hallc6793552016-01-19 14:18:37 -08002369 rawJson = intentsJson
2370 parsedIntentsJson = json.loads( rawJson )
Jon Hallefbd9792015-03-05 16:11:36 -08002371 if isinstance( intentsId, types.StringType ):
Jon Hallc6793552016-01-19 14:18:37 -08002372 for intent in parsedIntentsJson:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002373 if intentsId == intent[ 'id' ]:
2374 state = intent[ 'state' ]
kelvin-onlab54400a92015-02-26 18:05:51 -08002375 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002376 main.log.info( "Cannot find intent ID" + str( intentsId ) +
Jon Hall53158082017-05-18 11:17:00 -07002377 " in the list" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002378 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002379 elif isinstance( intentsId, types.ListType ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002380 dictList = []
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002381 for i in xrange( len( intentsId ) ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002382 stateDict = {}
Jon Hall53158082017-05-18 11:17:00 -07002383 for intent in parsedIntentsJson:
2384 if intentsId[ i ] == intent[ 'id' ]:
2385 stateDict[ 'state' ] = intent[ 'state' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002386 stateDict[ 'id' ] = intentsId[ i ]
Jon Hallefbd9792015-03-05 16:11:36 -08002387 dictList.append( stateDict )
kelvin-onlab54400a92015-02-26 18:05:51 -08002388 break
Jon Hallefbd9792015-03-05 16:11:36 -08002389 if len( intentsId ) != len( dictList ):
Jon Hall53158082017-05-18 11:17:00 -07002390 main.log.warn( "Could not find all intents in ONOS output" )
2391 main.log.debug( "expected ids: {} \n ONOS intents: {}".format( intentsId, parsedIntentsJson ) )
kelvin-onlab07dbd012015-03-04 16:29:39 -08002392 return dictList
kelvin-onlab54400a92015-02-26 18:05:51 -08002393 else:
Jon Hall53158082017-05-18 11:17:00 -07002394 main.log.info( "Invalid type for intentsId argument" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002395 return None
Jon Hallc6793552016-01-19 14:18:37 -08002396 except ( TypeError, ValueError ):
2397 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
kelvin-onlab54400a92015-02-26 18:05:51 -08002398 return None
2399 except pexpect.EOF:
2400 main.log.error( self.name + ": EOF exception found" )
2401 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002402 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002403 except Exception:
kelvin-onlab54400a92015-02-26 18:05:51 -08002404 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002405 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07002406
Jon Hallf539eb92017-05-22 17:18:42 -07002407 def checkIntentState( self, intentsId, expectedState='INSTALLED' ):
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002408 """
2409 Description:
2410 Check intents state
2411 Required:
2412 intentsId - List of intents ID to be checked
2413 Optional:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002414 expectedState - Check the expected state(s) of each intents
kelvin-onlabf512e942015-06-08 19:42:59 -07002415 state in the list.
2416 *NOTE: You can pass in a list of expected state,
2417 Eg: expectedState = [ 'INSTALLED' , 'INSTALLING' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002418 Return:
Jon Hall53158082017-05-18 11:17:00 -07002419 Returns main.TRUE only if all intent are the same as expected states,
2420 otherwise returns main.FALSE.
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002421 """
2422 try:
kelvin-onlabf512e942015-06-08 19:42:59 -07002423 returnValue = main.TRUE
Jon Hallf539eb92017-05-22 17:18:42 -07002424 # Generating a dictionary: intent id as a key and state as value
Devin Lim752dd7b2017-06-27 14:40:03 -07002425
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002426 # intentsDict = self.getIntentState( intentsId )
Devin Lim752dd7b2017-06-27 14:40:03 -07002427 intentsDict = []
2428 for intent in json.loads( self.intents() ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002429 if isinstance( intentsId, types.StringType ) \
2430 and intent.get( 'id' ) == intentsId:
2431 intentsDict.append( intent )
2432 elif isinstance( intentsId, types.ListType ) \
Devin Lim752dd7b2017-06-27 14:40:03 -07002433 and any( intent.get( 'id' ) == ids for ids in intentsId ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002434 intentsDict.append( intent )
Devin Lim752dd7b2017-06-27 14:40:03 -07002435
2436 if not intentsDict:
Jon Hallae04e622016-01-27 10:38:05 -08002437 main.log.info( self.name + ": There is something wrong " +
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002438 "getting intents state" )
2439 return main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002440
2441 if isinstance( expectedState, types.StringType ):
2442 for intents in intentsDict:
2443 if intents.get( 'state' ) != expectedState:
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002444 main.log.debug( self.name + " : Intent ID - " +
2445 intents.get( 'id' ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002446 " actual state = " +
2447 intents.get( 'state' )
2448 + " does not equal expected state = "
2449 + expectedState )
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002450 returnValue = main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002451 elif isinstance( expectedState, types.ListType ):
2452 for intents in intentsDict:
2453 if not any( state == intents.get( 'state' ) for state in
2454 expectedState ):
2455 main.log.debug( self.name + " : Intent ID - " +
2456 intents.get( 'id' ) +
2457 " actual state = " +
2458 intents.get( 'state' ) +
2459 " does not equal expected states = "
2460 + str( expectedState ) )
2461 returnValue = main.FALSE
2462
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002463 if returnValue == main.TRUE:
2464 main.log.info( self.name + ": All " +
2465 str( len( intentsDict ) ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002466 " intents are in " + str( expectedState ) +
2467 " state" )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002468 return returnValue
2469 except TypeError:
2470 main.log.exception( self.name + ": Object not as expected" )
2471 return None
2472 except pexpect.EOF:
2473 main.log.error( self.name + ": EOF exception found" )
2474 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002475 main.cleanAndExit()
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002476 except Exception:
2477 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002478 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04002479
Jon Hallf539eb92017-05-22 17:18:42 -07002480 def compareBandwidthAllocations( self, expectedAllocations ):
2481 """
2482 Description:
2483 Compare the allocated bandwidth with the given allocations
2484 Required:
2485 expectedAllocations - The expected ONOS output of the allocations command
2486 Return:
2487 Returns main.TRUE only if all intent are the same as expected states,
2488 otherwise returns main.FALSE.
2489 """
2490 # FIXME: Convert these string comparisons to object comparisons
2491 try:
2492 returnValue = main.TRUE
2493 bandwidthFailed = False
2494 rawAlloc = self.allocations()
2495 expectedFormat = StringIO( expectedAllocations )
2496 ONOSOutput = StringIO( rawAlloc )
2497 main.log.debug( "ONOSOutput: {}\nexpected output: {}".format( str( ONOSOutput ),
2498 str( expectedFormat ) ) )
2499
2500 for actual, expected in izip( ONOSOutput, expectedFormat ):
2501 actual = actual.rstrip()
2502 expected = expected.rstrip()
2503 main.log.debug( "Expect: {}\nactual: {}".format( expected, actual ) )
2504 if actual != expected and 'allocated' in actual and 'allocated' in expected:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002505 marker1 = actual.find( 'allocated' )
2506 m1 = actual[ :marker1 ]
2507 marker2 = expected.find( 'allocated' )
2508 m2 = expected[ :marker2 ]
Jon Hallf539eb92017-05-22 17:18:42 -07002509 if m1 != m2:
2510 bandwidthFailed = True
2511 elif actual != expected and 'allocated' not in actual and 'allocated' not in expected:
2512 bandwidthFailed = True
2513 expectedFormat.close()
2514 ONOSOutput.close()
2515
2516 if bandwidthFailed:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002517 main.log.error( "Bandwidth not allocated correctly using Intents!!" )
Jon Hallf539eb92017-05-22 17:18:42 -07002518 returnValue = main.FALSE
2519 return returnValue
2520 except TypeError:
2521 main.log.exception( self.name + ": Object not as expected" )
2522 return None
2523 except pexpect.EOF:
2524 main.log.error( self.name + ": EOF exception found" )
2525 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002526 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002527 except Exception:
2528 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002529 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002530
You Wang66518af2016-05-16 15:32:59 -07002531 def compareIntent( self, intentDict ):
2532 """
2533 Description:
2534 Compare the intent ids and states provided in the argument with all intents in ONOS
2535 Return:
2536 Returns main.TRUE if the two sets of intents match exactly, otherwise main.FALSE
2537 Arguments:
2538 intentDict: a dictionary which maps intent ids to intent states
2539 """
2540 try:
2541 intentsRaw = self.intents()
2542 intentsJson = json.loads( intentsRaw )
2543 intentDictONOS = {}
2544 for intent in intentsJson:
2545 intentDictONOS[ intent[ 'id' ] ] = intent[ 'state' ]
You Wang58d04452016-09-21 15:13:05 -07002546 returnValue = main.TRUE
You Wang66518af2016-05-16 15:32:59 -07002547 if len( intentDict ) != len( intentDictONOS ):
You Wang58d04452016-09-21 15:13:05 -07002548 main.log.warn( self.name + ": expected intent count does not match that in ONOS, " +
You Wang66518af2016-05-16 15:32:59 -07002549 str( len( intentDict ) ) + " expected and " +
2550 str( len( intentDictONOS ) ) + " actual" )
You Wang58d04452016-09-21 15:13:05 -07002551 returnValue = main.FALSE
You Wang66518af2016-05-16 15:32:59 -07002552 for intentID in intentDict.keys():
Jon Halle0f0b342017-04-18 11:43:47 -07002553 if intentID not in intentDictONOS.keys():
You Wang66518af2016-05-16 15:32:59 -07002554 main.log.debug( self.name + ": intent ID - " + intentID + " is not in ONOS" )
2555 returnValue = main.FALSE
You Wang58d04452016-09-21 15:13:05 -07002556 else:
2557 if intentDict[ intentID ] != intentDictONOS[ intentID ]:
2558 main.log.debug( self.name + ": intent ID - " + intentID +
2559 " expected state is " + intentDict[ intentID ] +
2560 " but actual state is " + intentDictONOS[ intentID ] )
2561 returnValue = main.FALSE
2562 intentDictONOS.pop( intentID )
2563 if len( intentDictONOS ) > 0:
2564 returnValue = main.FALSE
2565 for intentID in intentDictONOS.keys():
2566 main.log.debug( self.name + ": find extra intent in ONOS: intent ID " + intentID )
You Wang66518af2016-05-16 15:32:59 -07002567 if returnValue == main.TRUE:
2568 main.log.info( self.name + ": all intent IDs and states match that in ONOS" )
2569 return returnValue
You Wang1be9a512016-05-26 16:54:17 -07002570 except KeyError:
2571 main.log.exception( self.name + ": KeyError exception found" )
2572 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002573 except ( TypeError, ValueError ):
2574 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intentsRaw ) )
You Wang85560372016-05-18 10:44:33 -07002575 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002576 except pexpect.EOF:
2577 main.log.error( self.name + ": EOF exception found" )
2578 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002579 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002580 except Exception:
2581 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002582 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002583
YPZhang14a4aa92016-07-15 13:37:15 -07002584 def checkIntentSummary( self, timeout=60, noExit=True ):
GlennRCed771242016-01-13 17:02:47 -08002585 """
2586 Description:
2587 Check the number of installed intents.
2588 Optional:
2589 timeout - the timeout for pexcept
YPZhang14a4aa92016-07-15 13:37:15 -07002590 noExit - If noExit, TestON will not exit if any except.
GlennRCed771242016-01-13 17:02:47 -08002591 Return:
2592 Returns main.TRUE only if the number of all installed intents are the same as total intents number
2593 , otherwise, returns main.FALSE.
2594 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002595
GlennRCed771242016-01-13 17:02:47 -08002596 try:
2597 cmd = "intents -s -j"
2598
2599 # Check response if something wrong
YPZhang14a4aa92016-07-15 13:37:15 -07002600 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002601 if response is None:
YPZhang0584d432016-06-21 15:20:13 -07002602 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002603 response = json.loads( response )
2604
2605 # get total and installed number, see if they are match
2606 allState = response.get( 'all' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002607 if allState.get( 'total' ) == allState.get( 'installed' ):
Jon Halla478b852017-12-04 15:00:15 -08002608 main.log.info( 'Total Intents: {} Installed Intents: {}'.format(
2609 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002610 return main.TRUE
Jon Halla478b852017-12-04 15:00:15 -08002611 main.log.info( 'Verified Intents failed Expected intents: {} installed intents: {}'.format(
2612 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002613 return main.FALSE
2614
Jon Hallc6793552016-01-19 14:18:37 -08002615 except ( TypeError, ValueError ):
2616 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
GlennRCed771242016-01-13 17:02:47 -08002617 return None
2618 except pexpect.EOF:
2619 main.log.error( self.name + ": EOF exception found" )
2620 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002621 if noExit:
2622 return main.FALSE
2623 else:
Devin Lim44075962017-08-11 10:56:37 -07002624 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07002625 except pexpect.TIMEOUT:
2626 main.log.error( self.name + ": ONOS timeout" )
2627 return None
GlennRCed771242016-01-13 17:02:47 -08002628 except Exception:
2629 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002630 if noExit:
2631 return main.FALSE
2632 else:
Devin Lim44075962017-08-11 10:56:37 -07002633 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002634
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002635 def flows( self, state="any", jsonFormat=True, timeout=60, noExit=False, noCore=False, device=""):
kelvin8ec71442015-01-15 16:57:00 -08002636 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002637 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002638 * jsonFormat: enable output formatting in json
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002639 * noCore: suppress core flows
Shreya Shah0f01c812014-10-26 20:15:28 -04002640 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002641 Obtain flows currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08002642 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002643 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002644 cmdStr = "flows"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002645 if jsonFormat:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002646 cmdStr += " -j"
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002647 if noCore:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002648 cmdStr += " -n"
2649 cmdStr += " " + state
2650 cmdStr += " " + device
YPZhangebf9eb52016-05-12 15:20:24 -07002651 handle = self.sendline( cmdStr, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002652 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002653 assert "Command not found:" not in handle, handle
2654 if re.search( "Error:", handle ):
2655 main.log.error( self.name + ": flows() response: " +
2656 str( handle ) )
2657 return handle
2658 except AssertionError:
2659 main.log.exception( "" )
GlennRCed771242016-01-13 17:02:47 -08002660 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002661 except TypeError:
2662 main.log.exception( self.name + ": Object not as expected" )
2663 return None
Jon Hallc6793552016-01-19 14:18:37 -08002664 except pexpect.TIMEOUT:
2665 main.log.error( self.name + ": ONOS timeout" )
2666 return None
Shreya Shah0f01c812014-10-26 20:15:28 -04002667 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002668 main.log.error( self.name + ": EOF exception found" )
2669 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002670 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002671 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002672 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002673 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002674
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002675 def checkFlowCount( self, min=0, timeout=60 ):
Flavio Castroa1286fe2016-07-25 14:48:51 -07002676 count = self.getTotalFlowsNum( timeout=timeout )
Jon Halle0f0b342017-04-18 11:43:47 -07002677 count = int( count ) if count else 0
steven30801eccfe212019-01-24 13:00:42 +08002678 main.log.debug( "found {} flows".format( count ) )
Jon Halle0f0b342017-04-18 11:43:47 -07002679 return count if ( count > min ) else False
GlennRCed771242016-01-13 17:02:47 -08002680
Jon Halle0f0b342017-04-18 11:43:47 -07002681 def checkFlowsState( self, isPENDING=True, timeout=60, noExit=False ):
kelvin-onlab4df89f22015-04-13 18:10:23 -07002682 """
2683 Description:
GlennRCed771242016-01-13 17:02:47 -08002684 Check the if all the current flows are in ADDED state
Jon Hallc6793552016-01-19 14:18:37 -08002685 We check PENDING_ADD, PENDING_REMOVE, REMOVED, and FAILED flows,
2686 if the count of those states is 0, which means all current flows
2687 are in ADDED state, and return main.TRUE otherwise return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002688 Optional:
GlennRCed771242016-01-13 17:02:47 -08002689 * isPENDING: whether the PENDING_ADD is also a correct status
kelvin-onlab4df89f22015-04-13 18:10:23 -07002690 Return:
2691 returnValue - Returns main.TRUE only if all flows are in
Jon Hallc6793552016-01-19 14:18:37 -08002692 ADDED state or PENDING_ADD if the isPENDING
pingping-linbab7f8a2015-09-21 17:33:36 -07002693 parameter is set true, return main.FALSE otherwise.
kelvin-onlab4df89f22015-04-13 18:10:23 -07002694 """
2695 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002696 states = [ "PENDING_ADD", "PENDING_REMOVE", "REMOVED", "FAILED" ]
GlennRCed771242016-01-13 17:02:47 -08002697 checkedStates = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002698 statesCount = [ 0, 0, 0, 0 ]
GlennRCed771242016-01-13 17:02:47 -08002699 for s in states:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002700 rawFlows = self.flows( state=s, timeout = timeout )
YPZhang240842b2016-05-17 12:00:50 -07002701 if rawFlows:
2702 # if we didn't get flows or flows function return None, we should return
2703 # main.Flase
2704 checkedStates.append( json.loads( rawFlows ) )
2705 else:
2706 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002707 for i in range( len( states ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002708 for c in checkedStates[ i ]:
Jon Hallc6793552016-01-19 14:18:37 -08002709 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002710 statesCount[ i ] += int( c.get( "flowCount" ) )
Jon Hallc6793552016-01-19 14:18:37 -08002711 except TypeError:
2712 main.log.exception( "Json object not as expected" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002713 main.log.info( states[ i ] + " flows: " + str( statesCount[ i ] ) )
kelvin-onlabf2ec6e02015-05-27 14:15:28 -07002714
GlennRCed771242016-01-13 17:02:47 -08002715 # We want to count PENDING_ADD if isPENDING is true
2716 if isPENDING:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002717 if statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002718 return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002719 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002720 if statesCount[ 0 ] + statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002721 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002722 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002723 except ( TypeError, ValueError ):
2724 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawFlows ) )
kelvin-onlab4df89f22015-04-13 18:10:23 -07002725 return None
Jeremy Songster9385d412016-06-02 17:57:36 -07002726
YPZhang240842b2016-05-17 12:00:50 -07002727 except AssertionError:
2728 main.log.exception( "" )
2729 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002730 except pexpect.TIMEOUT:
2731 main.log.error( self.name + ": ONOS timeout" )
2732 return None
kelvin-onlab4df89f22015-04-13 18:10:23 -07002733 except pexpect.EOF:
2734 main.log.error( self.name + ": EOF exception found" )
2735 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002736 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002737 except Exception:
2738 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002739 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002740
GlennRCed771242016-01-13 17:02:47 -08002741 def pushTestIntents( self, ingress, egress, batchSize, offset="",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002742 options="", timeout=10, background = False, noExit=False, getResponse=False ):
kelvin8ec71442015-01-15 16:57:00 -08002743 """
andrewonlab87852b02014-11-19 18:44:19 -05002744 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002745 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05002746 a specific point-to-point intent definition
2747 Required:
GlennRCed771242016-01-13 17:02:47 -08002748 * ingress: specify source dpid
2749 * egress: specify destination dpid
2750 * batchSize: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05002751 Optional:
GlennRCed771242016-01-13 17:02:47 -08002752 * offset: the keyOffset is where the next batch of intents
2753 will be installed
YPZhangb34b7e12016-06-14 14:28:19 -07002754 * noExit: If set to True, TestON will not exit if any error when issus command
2755 * getResponse: If set to True, function will return ONOS response.
2756
GlennRCed771242016-01-13 17:02:47 -08002757 Returns: If failed to push test intents, it will returen None,
2758 if successful, return true.
2759 Timeout expection will return None,
2760 TypeError will return false
2761 other expections will exit()
kelvin8ec71442015-01-15 16:57:00 -08002762 """
andrewonlab87852b02014-11-19 18:44:19 -05002763 try:
GlennRCed771242016-01-13 17:02:47 -08002764 if background:
2765 back = "&"
andrewonlab87852b02014-11-19 18:44:19 -05002766 else:
GlennRCed771242016-01-13 17:02:47 -08002767 back = ""
2768 cmd = "push-test-intents {} {} {} {} {} {}".format( options,
Jon Hallc6793552016-01-19 14:18:37 -08002769 ingress,
2770 egress,
2771 batchSize,
2772 offset,
2773 back )
YPZhangebf9eb52016-05-12 15:20:24 -07002774 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002775 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002776 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08002777 main.log.info( response )
YPZhangb34b7e12016-06-14 14:28:19 -07002778 if getResponse:
2779 return response
2780
GlennRCed771242016-01-13 17:02:47 -08002781 # TODO: We should handle if there is failure in installation
2782 return main.TRUE
2783
Jon Hallc6793552016-01-19 14:18:37 -08002784 except AssertionError:
2785 main.log.exception( "" )
2786 return None
GlennRCed771242016-01-13 17:02:47 -08002787 except pexpect.TIMEOUT:
2788 main.log.error( self.name + ": ONOS timeout" )
Jon Halld4d4b372015-01-28 16:02:41 -08002789 return None
andrewonlab87852b02014-11-19 18:44:19 -05002790 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002791 main.log.error( self.name + ": EOF exception found" )
2792 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002793 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002794 except TypeError:
2795 main.log.exception( self.name + ": Object not as expected" )
Jon Hallc6793552016-01-19 14:18:37 -08002796 return None
Jon Hallfebb1c72015-03-05 13:30:09 -08002797 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002798 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002799 main.cleanAndExit()
andrewonlab87852b02014-11-19 18:44:19 -05002800
YPZhangebf9eb52016-05-12 15:20:24 -07002801 def getTotalFlowsNum( self, timeout=60, noExit=False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002802 """
2803 Description:
YPZhangf6f14a02016-01-28 15:17:31 -08002804 Get the number of ADDED flows.
YPZhangb5d3f832016-01-23 22:54:26 -08002805 Return:
YPZhangf6f14a02016-01-28 15:17:31 -08002806 The number of ADDED flows
YPZhang14a4aa92016-07-15 13:37:15 -07002807 Or return None if any exceptions
YPZhangb5d3f832016-01-23 22:54:26 -08002808 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002809
YPZhangb5d3f832016-01-23 22:54:26 -08002810 try:
YPZhange3109a72016-02-02 11:25:37 -08002811 # get total added flows number
YPZhang14a4aa92016-07-15 13:37:15 -07002812 cmd = "flows -c added"
2813 rawFlows = self.sendline( cmd, timeout=timeout, noExit=noExit )
2814 if rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002815 rawFlows = rawFlows.split( "\n" )
YPZhange3109a72016-02-02 11:25:37 -08002816 totalFlows = 0
YPZhang14a4aa92016-07-15 13:37:15 -07002817 for l in rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002818 totalFlows += int( l.split( "Count=" )[ 1 ] )
YPZhang14a4aa92016-07-15 13:37:15 -07002819 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002820 main.log.error( "Response not as expected!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002821 return None
2822 return totalFlows
YPZhange3109a72016-02-02 11:25:37 -08002823
You Wangd3097f72018-12-12 11:56:03 -08002824 except IndexError:
2825 main.log.exception( "{}: Object not as expected!".format( self.name ) )
2826 main.log.debug( "rawFlows: {}".format( rawFlows ) )
2827 return None
You Wangd3cb2ce2016-05-16 14:01:24 -07002828 except ( TypeError, ValueError ):
YPZhang14a4aa92016-07-15 13:37:15 -07002829 main.log.exception( "{}: Object not as expected!".format( self.name ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002830 return None
2831 except pexpect.EOF:
2832 main.log.error( self.name + ": EOF exception found" )
2833 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002834 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002835 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002836 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002837 except pexpect.TIMEOUT:
2838 main.log.error( self.name + ": ONOS timeout" )
2839 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002840 except Exception:
2841 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002842 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002843 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002844 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002845
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002846 def getTotalIntentsNum( self, timeout=60, noExit = False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002847 """
2848 Description:
2849 Get the total number of intents, include every states.
YPZhang14a4aa92016-07-15 13:37:15 -07002850 Optional:
2851 noExit - If noExit, TestON will not exit if any except.
YPZhangb5d3f832016-01-23 22:54:26 -08002852 Return:
2853 The number of intents
2854 """
2855 try:
2856 cmd = "summary -j"
YPZhang14a4aa92016-07-15 13:37:15 -07002857 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002858 if response is None:
2859 return -1
YPZhangb5d3f832016-01-23 22:54:26 -08002860 response = json.loads( response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002861 return int( response.get( "intents" ) )
You Wangd3cb2ce2016-05-16 14:01:24 -07002862 except ( TypeError, ValueError ):
2863 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002864 return None
2865 except pexpect.EOF:
2866 main.log.error( self.name + ": EOF exception found" )
2867 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002868 if noExit:
2869 return -1
2870 else:
Devin Lim44075962017-08-11 10:56:37 -07002871 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002872 except Exception:
2873 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002874 if noExit:
2875 return -1
2876 else:
Devin Lim44075962017-08-11 10:56:37 -07002877 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002878
kelvin-onlabd3b64892015-01-20 13:26:24 -08002879 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002880 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002881 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002882 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002883 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002884 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002885 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002886 cmdStr = "intents-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002887 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002888 cmdStr += " -j"
2889 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002890 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002891 assert "Command not found:" not in handle, handle
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002892 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002893 except AssertionError:
2894 main.log.exception( "" )
2895 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002896 except TypeError:
2897 main.log.exception( self.name + ": Object not as expected" )
2898 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002899 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002900 main.log.error( self.name + ": EOF exception found" )
2901 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002902 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002903 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002904 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002905 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002906
kelvin-onlabd3b64892015-01-20 13:26:24 -08002907 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002908 """
2909 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04002910 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002911 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002912 """
andrewonlab867212a2014-10-22 20:13:38 -04002913 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002914 cmdStr = "topology-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002915 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002916 cmdStr += " -j"
2917 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002918 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002919 assert "Command not found:" not in handle, handle
jenkins7ead5a82015-03-13 10:28:21 -07002920 if handle:
2921 return handle
Jon Hallc6358dd2015-04-10 12:44:28 -07002922 elif jsonFormat:
Jon Hallbe379602015-03-24 13:39:32 -07002923 # Return empty json
jenkins7ead5a82015-03-13 10:28:21 -07002924 return '{}'
Jon Hallc6358dd2015-04-10 12:44:28 -07002925 else:
2926 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002927 except AssertionError:
2928 main.log.exception( "" )
2929 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002930 except TypeError:
2931 main.log.exception( self.name + ": Object not as expected" )
2932 return None
andrewonlab867212a2014-10-22 20:13:38 -04002933 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002934 main.log.error( self.name + ": EOF exception found" )
2935 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002936 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002937 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002938 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002939 main.cleanAndExit()
andrewonlab867212a2014-10-22 20:13:38 -04002940
kelvin8ec71442015-01-15 16:57:00 -08002941 # Wrapper functions ****************
2942 # Wrapper functions use existing driver
2943 # functions and extends their use case.
2944 # For example, we may use the output of
2945 # a normal driver function, and parse it
2946 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04002947
kelvin-onlabd3b64892015-01-20 13:26:24 -08002948 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002949 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002950 Description:
2951 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08002952 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002953 try:
kelvin8ec71442015-01-15 16:57:00 -08002954 # Obtain output of intents function
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002955 intentsStr = self.intents( jsonFormat=True )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07002956 if intentsStr is None:
2957 raise TypeError
Jon Hall6021e062017-01-30 11:10:06 -08002958 # Convert to a dictionary
2959 intents = json.loads( intentsStr )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002960 intentIdList = []
Jon Hall6021e062017-01-30 11:10:06 -08002961 for intent in intents:
2962 intentIdList.append( intent[ 'id' ] )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002963 return intentIdList
Jon Halld4d4b372015-01-28 16:02:41 -08002964 except TypeError:
2965 main.log.exception( self.name + ": Object not as expected" )
2966 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002967 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002968 main.log.error( self.name + ": EOF exception found" )
2969 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002970 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002971 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002972 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002973 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04002974
You Wang3c276252016-09-21 15:21:36 -07002975 def flowAddedCount( self, deviceId, core=False ):
Jon Hall30b82fa2015-03-04 17:15:43 -08002976 """
2977 Determine the number of flow rules for the given device id that are
2978 in the added state
You Wang3c276252016-09-21 15:21:36 -07002979 Params:
2980 core: if True, only return the number of core flows added
Jon Hall30b82fa2015-03-04 17:15:43 -08002981 """
2982 try:
You Wang3c276252016-09-21 15:21:36 -07002983 if core:
2984 cmdStr = "flows any " + str( deviceId ) + " | " +\
2985 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
2986 else:
2987 cmdStr = "flows any " + str( deviceId ) + " | " +\
2988 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08002989 handle = self.lineCount( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002990 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002991 assert "Command not found:" not in handle, handle
Jon Hall30b82fa2015-03-04 17:15:43 -08002992 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002993 except AssertionError:
2994 main.log.exception( "" )
2995 return None
Jon Hall30b82fa2015-03-04 17:15:43 -08002996 except pexpect.EOF:
2997 main.log.error( self.name + ": EOF exception found" )
2998 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002999 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003000 except Exception:
Jon Hall30b82fa2015-03-04 17:15:43 -08003001 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003002 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -04003003
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003004 def groupAddedCount( self, deviceId, core=False ):
3005 """
3006 Determine the number of group rules for the given device id that are
3007 in the added state
3008 Params:
3009 core: if True, only return the number of core groups added
3010 """
3011 try:
3012 if core:
3013 cmdStr = "groups any " + str( deviceId ) + " | " +\
3014 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
3015 else:
3016 cmdStr = "groups any " + str( deviceId ) + " | " +\
3017 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003018 handle = self.lineCount( cmdStr )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003019 assert handle is not None, "Error in sendline"
3020 assert "Command not found:" not in handle, handle
3021 return handle
3022 except AssertionError:
3023 main.log.exception( "" )
3024 return None
3025 except pexpect.EOF:
3026 main.log.error( self.name + ": EOF exception found" )
3027 main.log.error( self.name + ": " + self.handle.before )
3028 main.cleanAndExit()
3029 except Exception:
3030 main.log.exception( self.name + ": Uncaught exception!" )
3031 main.cleanAndExit()
3032
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003033 def addStaticRoute( self, subnet, intf):
3034 """
3035 Adds a static route to onos.
3036 Params:
3037 subnet: The subnet reaching through this route
3038 intf: The interface this route is reachable through
3039 """
3040 try:
3041 cmdStr = "route-add " + subnet + " " + intf
3042 handle = self.sendline( cmdStr )
3043 assert handle is not None, "Error in sendline"
3044 assert "Command not found:" not in handle, handle
3045 return handle
3046 except AssertionError:
3047 main.log.exception( "" )
3048 return None
3049 except pexpect.EOF:
3050 main.log.error( self.name + ": EOF exception found" )
3051 main.log.error( self.name + ": " + self.handle.before )
3052 main.cleanAndExit()
3053 except Exception:
3054 main.log.exception( self.name + ": Uncaught exception!" )
3055 main.cleanAndExit()
3056
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003057 def checkGroupAddedCount( self, deviceId, expectedGroupCount=0, core=False, comparison=0):
3058 """
3059 Description:
3060 Check whether the number of groups for the given device id that
3061 are in ADDED state is bigger than minGroupCount.
3062 Required:
3063 * deviceId: device id to check the number of added group rules
3064 Optional:
3065 * minGroupCount: the number of groups to compare
3066 * core: if True, only check the number of core groups added
3067 * comparison: if 0, compare with greater than minFlowCount
3068 * if 1, compare with equal to minFlowCount
3069 Return:
3070 Returns the number of groups if it is bigger than minGroupCount,
3071 returns main.FALSE otherwise.
3072 """
3073 count = self.groupAddedCount( deviceId, core )
3074 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003075 main.log.debug( "found {} groups".format( count ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003076 return count if ((count > expectedGroupCount) if (comparison == 0) else (count == expectedGroupCount)) else main.FALSE
3077
You Wangc02f3be2018-05-18 12:14:23 -07003078 def getGroups( self, deviceId, groupType="any" ):
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003079 """
3080 Retrieve groups from a specific device.
You Wangc02f3be2018-05-18 12:14:23 -07003081 deviceId: Id of the device from which we retrieve groups
3082 groupType: Type of group
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003083 """
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003084 try:
You Wangc02f3be2018-05-18 12:14:23 -07003085 groupCmd = "groups -t {0} any {1}".format( groupType, deviceId )
3086 handle = self.sendline( groupCmd )
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003087 assert handle is not None, "Error in sendline"
3088 assert "Command not found:" not in handle, handle
3089 return handle
3090 except AssertionError:
3091 main.log.exception( "" )
3092 return None
3093 except TypeError:
3094 main.log.exception( self.name + ": Object not as expected" )
3095 return None
3096 except pexpect.EOF:
3097 main.log.error( self.name + ": EOF exception found" )
3098 main.log.error( self.name + ": " + self.handle.before )
3099 main.cleanAndExit()
3100 except Exception:
3101 main.log.exception( self.name + ": Uncaught exception!" )
3102 main.cleanAndExit()
3103
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003104 def checkFlowAddedCount( self, deviceId, expectedFlowCount=0, core=False, comparison=0):
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003105 """
3106 Description:
3107 Check whether the number of flow rules for the given device id that
3108 are in ADDED state is bigger than minFlowCount.
3109 Required:
3110 * deviceId: device id to check the number of added flow rules
3111 Optional:
3112 * minFlowCount: the number of flow rules to compare
3113 * core: if True, only check the number of core flows added
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003114 * comparison: if 0, compare with greater than minFlowCount
3115 * if 1, compare with equal to minFlowCount
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003116 Return:
3117 Returns the number of flow rules if it is bigger than minFlowCount,
3118 returns main.FALSE otherwise.
3119 """
3120 count = self.flowAddedCount( deviceId, core )
3121 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003122 main.log.debug( "found {} flows".format( count ) )
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003123 return count if ((count > expectedFlowCount) if (comparison == 0) else (count == expectedFlowCount)) else main.FALSE
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003124
kelvin-onlabd3b64892015-01-20 13:26:24 -08003125 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003126 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003127 Use 'devices' function to obtain list of all devices
3128 and parse the result to obtain a list of all device
3129 id's. Returns this list. Returns empty list if no
3130 devices exist
kelvin8ec71442015-01-15 16:57:00 -08003131 List is ordered sequentially
3132
andrewonlab3e15ead2014-10-15 14:21:34 -04003133 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08003134 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04003135 the ids. By obtaining the list of device ids on the fly,
3136 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08003137 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003138 try:
kelvin8ec71442015-01-15 16:57:00 -08003139 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08003140 devicesStr = self.devices( jsonFormat=False )
3141 idList = []
kelvin8ec71442015-01-15 16:57:00 -08003142
kelvin-onlabd3b64892015-01-20 13:26:24 -08003143 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08003144 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003145 return idList
kelvin8ec71442015-01-15 16:57:00 -08003146
3147 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08003148 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08003149 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08003150 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08003151 # Split list further into arguments before and after string
3152 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08003153 # append to idList
3154 for arg in tempList:
3155 idList.append( arg.split( "id=" )[ 1 ] )
3156 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04003157
Jon Halld4d4b372015-01-28 16:02:41 -08003158 except TypeError:
3159 main.log.exception( self.name + ": Object not as expected" )
3160 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04003161 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003162 main.log.error( self.name + ": EOF exception found" )
3163 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003164 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003165 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003166 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003167 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003168
kelvin-onlabd3b64892015-01-20 13:26:24 -08003169 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003170 """
andrewonlab7c211572014-10-15 16:45:20 -04003171 Uses 'nodes' function to obtain list of all nodes
3172 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08003173 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04003174 Returns:
3175 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08003176 """
andrewonlab7c211572014-10-15 16:45:20 -04003177 try:
Jon Hall5aa168b2015-03-23 14:23:09 -07003178 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003179 idList = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003180 # Sample nodesStr output
Jon Hallbd182782016-03-28 16:42:22 -07003181 # id=local, address=127.0.0.1:9876, state=READY *
kelvin-onlabd3b64892015-01-20 13:26:24 -08003182 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08003183 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003184 return idList
Jon Hall5aa168b2015-03-23 14:23:09 -07003185 nodesJson = json.loads( nodesStr )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003186 idList = [ node.get( 'id' ) for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08003187 return idList
Jon Hallc6793552016-01-19 14:18:37 -08003188 except ( TypeError, ValueError ):
3189 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, nodesStr ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003190 return None
andrewonlab7c211572014-10-15 16:45:20 -04003191 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003192 main.log.error( self.name + ": EOF exception found" )
3193 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003194 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003195 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003196 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003197 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003198
kelvin-onlabd3b64892015-01-20 13:26:24 -08003199 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08003200 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003201 Return the first device from the devices api whose 'id' contains 'dpid'
3202 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08003203 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003204 try:
kelvin8ec71442015-01-15 16:57:00 -08003205 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04003206 return None
3207 else:
kelvin8ec71442015-01-15 16:57:00 -08003208 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003209 rawDevices = self.devices()
3210 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08003211 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08003212 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08003213 # print "%s in %s?" % ( dpid, device[ 'id' ] )
3214 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04003215 return device
3216 return None
Jon Hallc6793552016-01-19 14:18:37 -08003217 except ( TypeError, ValueError ):
3218 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawDevices ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003219 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04003220 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003221 main.log.error( self.name + ": EOF exception found" )
3222 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003223 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003224 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003225 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003226 main.cleanAndExit()
Jon Halla91c4dc2014-10-22 12:57:04 -04003227
You Wang24139872016-05-03 11:48:47 -07003228 def getTopology( self, topologyOutput ):
3229 """
3230 Definition:
3231 Loads a json topology output
3232 Return:
3233 topology = current ONOS topology
3234 """
3235 import json
3236 try:
3237 # either onos:topology or 'topology' will work in CLI
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003238 topology = json.loads( topologyOutput )
Jeremy Songsterbc2d8ac2016-05-04 11:25:42 -07003239 main.log.debug( topology )
You Wang24139872016-05-03 11:48:47 -07003240 return topology
You Wangd3cb2ce2016-05-16 14:01:24 -07003241 except ( TypeError, ValueError ):
3242 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, topologyOutput ) )
3243 return None
You Wang24139872016-05-03 11:48:47 -07003244 except pexpect.EOF:
3245 main.log.error( self.name + ": EOF exception found" )
3246 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003247 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003248 except Exception:
3249 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003250 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003251
Pier6a0c4de2018-03-18 16:01:30 -07003252 def checkStatus( self, numoswitch, numolink = -1, numoctrl = -1, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08003253 """
Jon Hallefbd9792015-03-05 16:11:36 -08003254 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08003255 supplied values. By default this will report to main.log, but the
You Wang24139872016-05-03 11:48:47 -07003256 log level can be specific.
kelvin8ec71442015-01-15 16:57:00 -08003257
Flavio Castro82ee2f62016-06-07 15:04:12 -07003258 Params: numoswitch = expected number of switches
Jon Hallefbd9792015-03-05 16:11:36 -08003259 numolink = expected number of links
Flavio Castro82ee2f62016-06-07 15:04:12 -07003260 numoctrl = expected number of controllers
You Wang24139872016-05-03 11:48:47 -07003261 logLevel = level to log to.
3262 Currently accepts 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04003263
Jon Hallefbd9792015-03-05 16:11:36 -08003264 Returns: main.TRUE if the number of switches and links are correct,
3265 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04003266 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08003267 """
Flavio Castro82ee2f62016-06-07 15:04:12 -07003268 import json
Jon Hall42db6dc2014-10-24 19:03:48 -04003269 try:
You Wang13310252016-07-31 10:56:14 -07003270 summary = self.summary()
3271 summary = json.loads( summary )
Flavio Castrof5b3f872016-06-23 17:52:31 -07003272 except ( TypeError, ValueError ):
3273 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summary ) )
3274 return main.ERROR
3275 try:
3276 topology = self.getTopology( self.topology() )
Jon Halle0f0b342017-04-18 11:43:47 -07003277 if topology == {} or topology is None or summary == {} or summary is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04003278 return main.ERROR
3279 output = ""
kelvin8ec71442015-01-15 16:57:00 -08003280 # Is the number of switches is what we expected
3281 devices = topology.get( 'devices', False )
3282 links = topology.get( 'links', False )
Flavio Castro82ee2f62016-06-07 15:04:12 -07003283 nodes = summary.get( 'nodes', False )
3284 if devices is False or links is False or nodes is False:
Jon Hall42db6dc2014-10-24 19:03:48 -04003285 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08003286 switchCheck = ( int( devices ) == int( numoswitch ) )
kelvin8ec71442015-01-15 16:57:00 -08003287 # Is the number of links is what we expected
Pier6a0c4de2018-03-18 16:01:30 -07003288 linkCheck = ( int( links ) == int( numolink ) ) or int( numolink ) == -1
Flavio Castro82ee2f62016-06-07 15:04:12 -07003289 nodeCheck = ( int( nodes ) == int( numoctrl ) ) or int( numoctrl ) == -1
3290 if switchCheck and linkCheck and nodeCheck:
kelvin8ec71442015-01-15 16:57:00 -08003291 # We expected the correct numbers
You Wang24139872016-05-03 11:48:47 -07003292 output = output + "The number of links and switches match "\
3293 + "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003294 result = main.TRUE
3295 else:
You Wang24139872016-05-03 11:48:47 -07003296 output = output + \
3297 "The number of links and switches does not match " + \
3298 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003299 result = main.FALSE
You Wang24139872016-05-03 11:48:47 -07003300 output = output + "\n ONOS sees %i devices" % int( devices )
3301 output = output + " (%i expected) " % int( numoswitch )
Pier6a0c4de2018-03-18 16:01:30 -07003302 if int( numolink ) > 0:
3303 output = output + "and %i links " % int( links )
3304 output = output + "(%i expected)" % int( numolink )
YPZhangd7e4b6e2016-06-17 16:07:55 -07003305 if int( numoctrl ) > 0:
Flavio Castro82ee2f62016-06-07 15:04:12 -07003306 output = output + "and %i controllers " % int( nodes )
3307 output = output + "(%i expected)" % int( numoctrl )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003308 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08003309 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003310 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08003311 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04003312 else:
You Wang24139872016-05-03 11:48:47 -07003313 main.log.info( output )
kelvin8ec71442015-01-15 16:57:00 -08003314 return result
Jon Hall42db6dc2014-10-24 19:03:48 -04003315 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003316 main.log.error( self.name + ": EOF exception found" )
3317 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003318 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003319 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003320 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003321 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003322
kelvin-onlabd3b64892015-01-20 13:26:24 -08003323 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08003324 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003325 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08003326 deviceId must be the id of a device as seen in the onos devices command
3327 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04003328 role must be either master, standby, or none
3329
Jon Halle3f39ff2015-01-13 11:50:53 -08003330 Returns:
3331 main.TRUE or main.FALSE based on argument verification and
3332 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003333 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003334 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003335 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04003336 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08003337 cmdStr = "device-role " +\
3338 str( deviceId ) + " " +\
3339 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003340 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003341 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003342 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003343 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08003344 if re.search( "Error", handle ):
3345 # end color output to escape any colours
3346 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08003347 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003348 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08003349 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08003350 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04003351 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003352 main.log.error( "Invalid 'role' given to device_role(). " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003353 "Value was '" + str( role ) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04003354 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003355 except AssertionError:
3356 main.log.exception( "" )
3357 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003358 except TypeError:
3359 main.log.exception( self.name + ": Object not as expected" )
3360 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04003361 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003362 main.log.error( self.name + ": EOF exception found" )
3363 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003364 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003365 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003366 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003367 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003368
kelvin-onlabd3b64892015-01-20 13:26:24 -08003369 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08003370 """
Jon Hall0dd09952018-04-19 09:59:11 -07003371 Lists all topology clusters
Jon Hallffb386d2014-11-21 13:43:38 -08003372 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003373 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08003374 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08003375 try:
Jon Hall0dd09952018-04-19 09:59:11 -07003376 cmdStr = "topo-clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003377 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003378 cmdStr += " -j"
3379 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003380 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003381 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07003382 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003383 except AssertionError:
3384 main.log.exception( "" )
3385 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003386 except TypeError:
3387 main.log.exception( self.name + ": Object not as expected" )
3388 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08003389 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003390 main.log.error( self.name + ": EOF exception found" )
3391 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003392 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003393 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003394 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003395 main.cleanAndExit()
Jon Hall73cf9cc2014-11-20 22:28:38 -08003396
kelvin-onlabd3b64892015-01-20 13:26:24 -08003397 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003398 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003399 CLI command to get the current leader for the Election test application
3400 NOTE: Requires installation of the onos-app-election feature
3401 Returns: Node IP of the leader if one exists
3402 None if none exists
3403 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003404 """
Jon Hall94fd0472014-12-08 11:52:42 -08003405 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003406 cmdStr = "election-test-leader"
3407 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003408 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003409 assert "Command not found:" not in response, response
Jon Halle3f39ff2015-01-13 11:50:53 -08003410 # Leader
3411 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003412 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08003413 nodeSearch = re.search( leaderPattern, response )
3414 if nodeSearch:
3415 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08003416 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003417 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08003418 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08003419 # no leader
3420 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003421 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003422 nullSearch = re.search( nullPattern, response )
3423 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08003424 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003425 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08003426 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08003427 # error
Jon Hall0e240372018-05-02 11:21:57 -07003428 main.log.error( self.name + ": Error in electionTestLeader on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003429 ": " + "unexpected response" )
3430 main.log.error( repr( response ) )
3431 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003432 except AssertionError:
3433 main.log.exception( "" )
3434 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003435 except TypeError:
3436 main.log.exception( self.name + ": Object not as expected" )
3437 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003438 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003439 main.log.error( self.name + ": EOF exception found" )
3440 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003441 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003442 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003443 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003444 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003445
kelvin-onlabd3b64892015-01-20 13:26:24 -08003446 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003447 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003448 CLI command to run for leadership of the Election test application.
3449 NOTE: Requires installation of the onos-app-election feature
3450 Returns: Main.TRUE on success
3451 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003452 """
Jon Hall94fd0472014-12-08 11:52:42 -08003453 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003454 cmdStr = "election-test-run"
3455 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003456 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003457 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003458 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003459 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003460 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003461 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08003462 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08003463 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003464 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003465 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003466 # error
Jon Hall0e240372018-05-02 11:21:57 -07003467 main.log.error( self.name + ": Error in electionTestRun on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003468 ": " + "unexpected response" )
3469 main.log.error( repr( response ) )
3470 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003471 except AssertionError:
3472 main.log.exception( "" )
3473 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003474 except TypeError:
3475 main.log.exception( self.name + ": Object not as expected" )
3476 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003477 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003478 main.log.error( self.name + ": EOF exception found" )
3479 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003480 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003481 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003482 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003483 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003484
kelvin-onlabd3b64892015-01-20 13:26:24 -08003485 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08003486 """
Jon Hall94fd0472014-12-08 11:52:42 -08003487 * CLI command to withdraw the local node from leadership election for
3488 * the Election test application.
3489 #NOTE: Requires installation of the onos-app-election feature
3490 Returns: Main.TRUE on success
3491 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08003492 """
Jon Hall94fd0472014-12-08 11:52:42 -08003493 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003494 cmdStr = "election-test-withdraw"
3495 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003496 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003497 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003498 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003499 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003500 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003501 if re.search( successPattern, response ):
3502 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003503 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003504 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003505 # error
Jon Hall0e240372018-05-02 11:21:57 -07003506 main.log.error( self.name + ": Error in electionTestWithdraw on " +
Jon Hall97cf84a2016-06-20 13:35:58 -07003507 self.name + ": " + "unexpected response" )
3508 main.log.error( repr( response ) )
3509 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003510 except AssertionError:
3511 main.log.exception( "" )
3512 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003513 except TypeError:
3514 main.log.exception( self.name + ": Object not as expected" )
3515 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003516 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003517 main.log.error( self.name + ": EOF exception found" )
3518 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003519 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003520 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003521 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003522 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003523
kelvin8ec71442015-01-15 16:57:00 -08003524 def getDevicePortsEnabledCount( self, dpid ):
3525 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003526 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003527 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003528 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003529 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003530 cmdStr = "onos:ports -e " + dpid + " | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003531 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003532 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003533 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003534 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003535 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003536 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003537 return output
Jon Hallc6793552016-01-19 14:18:37 -08003538 except AssertionError:
3539 main.log.exception( "" )
3540 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003541 except TypeError:
3542 main.log.exception( self.name + ": Object not as expected" )
3543 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003544 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003545 main.log.error( self.name + ": EOF exception found" )
3546 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003547 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003548 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003549 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003550 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003551
kelvin8ec71442015-01-15 16:57:00 -08003552 def getDeviceLinksActiveCount( self, dpid ):
3553 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003554 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003555 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003556 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003557 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003558 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003559 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003560 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003561 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003562 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003563 main.log.error( self.name + ": Error in getting ports " )
kelvin-onlab898a6c62015-01-16 14:13:53 -08003564 return ( output, "Error " )
Jon Halla495f562016-05-16 18:03:26 -07003565 return output
Jon Hallc6793552016-01-19 14:18:37 -08003566 except AssertionError:
3567 main.log.exception( "" )
3568 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003569 except TypeError:
3570 main.log.exception( self.name + ": Object not as expected" )
3571 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003572 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003573 main.log.error( self.name + ": EOF exception found" )
3574 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003575 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003576 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003577 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003578 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003579
kelvin8ec71442015-01-15 16:57:00 -08003580 def getAllIntentIds( self ):
3581 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003582 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08003583 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003584 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003585 cmdStr = "onos:intents | grep id="
3586 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003587 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003588 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003589 if re.search( "Error", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003590 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003591 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003592 return output
Jon Hallc6793552016-01-19 14:18:37 -08003593 except AssertionError:
3594 main.log.exception( "" )
3595 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003596 except TypeError:
3597 main.log.exception( self.name + ": Object not as expected" )
3598 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003599 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003600 main.log.error( self.name + ": EOF exception found" )
3601 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003602 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003603 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003604 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003605 main.cleanAndExit()
Jon Halld4d4b372015-01-28 16:02:41 -08003606
Jon Hall73509952015-02-24 16:42:56 -08003607 def intentSummary( self ):
3608 """
Jon Hallefbd9792015-03-05 16:11:36 -08003609 Returns a dictionary containing the current intent states and the count
Jon Hall73509952015-02-24 16:42:56 -08003610 """
3611 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003612 intents = self.intents( )
Jon Hall08f61bc2015-04-13 16:00:30 -07003613 states = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003614 for intent in json.loads( intents ):
Jon Hall08f61bc2015-04-13 16:00:30 -07003615 states.append( intent.get( 'state', None ) )
3616 out = [ ( i, states.count( i ) ) for i in set( states ) ]
Jon Hall63604932015-02-26 17:09:50 -08003617 main.log.info( dict( out ) )
Jon Hall73509952015-02-24 16:42:56 -08003618 return dict( out )
Jon Hallc6793552016-01-19 14:18:37 -08003619 except ( TypeError, ValueError ):
3620 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intents ) )
Jon Hall73509952015-02-24 16:42:56 -08003621 return None
3622 except pexpect.EOF:
3623 main.log.error( self.name + ": EOF exception found" )
3624 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003625 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003626 except Exception:
Jon Hall73509952015-02-24 16:42:56 -08003627 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003628 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003629
Jon Hall61282e32015-03-19 11:34:11 -07003630 def leaders( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003631 """
3632 Returns the output of the leaders command.
Jon Hall61282e32015-03-19 11:34:11 -07003633 Optional argument:
3634 * jsonFormat - boolean indicating if you want output in json
Jon Hall63604932015-02-26 17:09:50 -08003635 """
Jon Hall63604932015-02-26 17:09:50 -08003636 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003637 cmdStr = "onos:leaders"
Jon Hall61282e32015-03-19 11:34:11 -07003638 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003639 cmdStr += " -j"
3640 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003641 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003642 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003643 return output
Jon Hallc6793552016-01-19 14:18:37 -08003644 except AssertionError:
3645 main.log.exception( "" )
3646 return None
Jon Hall63604932015-02-26 17:09:50 -08003647 except TypeError:
3648 main.log.exception( self.name + ": Object not as expected" )
3649 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003650 except pexpect.EOF:
3651 main.log.error( self.name + ": EOF exception found" )
3652 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003653 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003654 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003655 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003656 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003657
acsmarsa4a4d1e2015-07-10 16:01:24 -07003658 def leaderCandidates( self, jsonFormat=True ):
3659 """
3660 Returns the output of the leaders -c command.
3661 Optional argument:
3662 * jsonFormat - boolean indicating if you want output in json
3663 """
3664 try:
3665 cmdStr = "onos:leaders -c"
3666 if jsonFormat:
3667 cmdStr += " -j"
3668 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003669 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003670 assert "Command not found:" not in output, output
acsmarsa4a4d1e2015-07-10 16:01:24 -07003671 return output
Jon Hallc6793552016-01-19 14:18:37 -08003672 except AssertionError:
3673 main.log.exception( "" )
3674 return None
acsmarsa4a4d1e2015-07-10 16:01:24 -07003675 except TypeError:
3676 main.log.exception( self.name + ": Object not as expected" )
3677 return None
3678 except pexpect.EOF:
3679 main.log.error( self.name + ": EOF exception found" )
3680 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003681 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003682 except Exception:
3683 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003684 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003685
Jon Hallc6793552016-01-19 14:18:37 -08003686 def specificLeaderCandidate( self, topic ):
acsmarsa4a4d1e2015-07-10 16:01:24 -07003687 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003688 Returns a list in format [leader,candidate1,candidate2,...] for a given
acsmarsa4a4d1e2015-07-10 16:01:24 -07003689 topic parameter and an empty list if the topic doesn't exist
3690 If no leader is elected leader in the returned list will be "none"
3691 Returns None if there is a type error processing the json object
3692 """
3693 try:
Jon Hall6e709752016-02-01 13:38:46 -08003694 cmdStr = "onos:leaders -j"
Jon Hallc6793552016-01-19 14:18:37 -08003695 rawOutput = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003696 assert rawOutput is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003697 assert "Command not found:" not in rawOutput, rawOutput
3698 output = json.loads( rawOutput )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003699 results = []
3700 for dict in output:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003701 if dict[ "topic" ] == topic:
3702 leader = dict[ "leader" ]
3703 candidates = re.split( ", ", dict[ "candidates" ][ 1:-1 ] )
Jon Hallc6793552016-01-19 14:18:37 -08003704 results.append( leader )
3705 results.extend( candidates )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003706 return results
Jon Hallc6793552016-01-19 14:18:37 -08003707 except AssertionError:
3708 main.log.exception( "" )
3709 return None
3710 except ( TypeError, ValueError ):
3711 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawOutput ) )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003712 return None
3713 except pexpect.EOF:
3714 main.log.error( self.name + ": EOF exception found" )
3715 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003716 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003717 except Exception:
3718 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003719 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003720
Jon Hall61282e32015-03-19 11:34:11 -07003721 def pendingMap( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003722 """
3723 Returns the output of the intent Pending map.
3724 """
Jon Hall63604932015-02-26 17:09:50 -08003725 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003726 cmdStr = "onos:intents -p"
Jon Hall61282e32015-03-19 11:34:11 -07003727 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003728 cmdStr += " -j"
3729 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003730 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003731 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003732 return output
Jon Hallc6793552016-01-19 14:18:37 -08003733 except AssertionError:
3734 main.log.exception( "" )
3735 return None
Jon Hall63604932015-02-26 17:09:50 -08003736 except TypeError:
3737 main.log.exception( self.name + ": Object not as expected" )
3738 return None
3739 except pexpect.EOF:
3740 main.log.error( self.name + ": EOF exception found" )
3741 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003742 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003743 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003744 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003745 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003746
Jon Hall2c8959e2016-12-16 12:17:34 -08003747 def partitions( self, candidates=False, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003748 """
3749 Returns the output of the raft partitions command for ONOS.
3750 """
Jon Hall61282e32015-03-19 11:34:11 -07003751 # Sample JSON
3752 # {
3753 # "leader": "tcp://10.128.30.11:7238",
3754 # "members": [
3755 # "tcp://10.128.30.11:7238",
3756 # "tcp://10.128.30.17:7238",
3757 # "tcp://10.128.30.13:7238",
3758 # ],
3759 # "name": "p1",
3760 # "term": 3
3761 # },
Jon Hall63604932015-02-26 17:09:50 -08003762 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003763 cmdStr = "onos:partitions"
Jon Hall2c8959e2016-12-16 12:17:34 -08003764 if candidates:
3765 cmdStr += " -c"
Jon Hall61282e32015-03-19 11:34:11 -07003766 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003767 cmdStr += " -j"
3768 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003769 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003770 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003771 return output
Jon Hallc6793552016-01-19 14:18:37 -08003772 except AssertionError:
3773 main.log.exception( "" )
3774 return None
Jon Hall63604932015-02-26 17:09:50 -08003775 except TypeError:
3776 main.log.exception( self.name + ": Object not as expected" )
3777 return None
3778 except pexpect.EOF:
3779 main.log.error( self.name + ": EOF exception found" )
3780 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003781 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003782 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003783 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003784 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003785
Jon Halle9f909e2016-09-23 10:43:12 -07003786 def apps( self, summary=False, active=False, jsonFormat=True ):
Jon Hallbe379602015-03-24 13:39:32 -07003787 """
3788 Returns the output of the apps command for ONOS. This command lists
3789 information about installed ONOS applications
3790 """
3791 # Sample JSON object
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003792 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
Jon Hallbe379602015-03-24 13:39:32 -07003793 # "description":"ONOS OpenFlow protocol southbound providers",
3794 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003795 # "features":"[onos-openflow]","state":"ACTIVE"}]
Jon Hallbe379602015-03-24 13:39:32 -07003796 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003797 cmdStr = "onos:apps"
Jon Hallf03ae762019-01-22 13:25:27 -08003798 expectJson = False
Jon Halle9f909e2016-09-23 10:43:12 -07003799 if summary:
3800 cmdStr += " -s"
3801 if active:
3802 cmdStr += " -a"
Jon Hallbe379602015-03-24 13:39:32 -07003803 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003804 cmdStr += " -j"
Jon Hallf03ae762019-01-22 13:25:27 -08003805 expectJson = True
3806 output = self.sendline( cmdStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07003807 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003808 assert "Command not found:" not in output, output
3809 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003810 return output
Jon Hallbe379602015-03-24 13:39:32 -07003811 # FIXME: look at specific exceptions/Errors
3812 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07003813 main.log.exception( self.name + ": Error in processing onos:app command." )
Jon Hallbe379602015-03-24 13:39:32 -07003814 return None
3815 except TypeError:
3816 main.log.exception( self.name + ": Object not as expected" )
3817 return None
3818 except pexpect.EOF:
3819 main.log.error( self.name + ": EOF exception found" )
3820 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003821 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003822 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003823 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003824 main.cleanAndExit()
Jon Hallbe379602015-03-24 13:39:32 -07003825
You Wangcdc51fe2018-08-12 17:14:56 -07003826 def appStatus( self, appName ):
Jon Hall146f1522015-03-24 15:33:24 -07003827 """
3828 Uses the onos:apps cli command to return the status of an application.
3829 Returns:
3830 "ACTIVE" - If app is installed and activated
3831 "INSTALLED" - If app is installed and deactivated
3832 "UNINSTALLED" - If app is not installed
3833 None - on error
3834 """
Jon Hall146f1522015-03-24 15:33:24 -07003835 try:
3836 if not isinstance( appName, types.StringType ):
3837 main.log.error( self.name + ".appStatus(): appName must be" +
3838 " a string" )
3839 return None
3840 output = self.apps( jsonFormat=True )
3841 appsJson = json.loads( output )
3842 state = None
3843 for app in appsJson:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003844 if appName == app.get( 'name' ):
3845 state = app.get( 'state' )
Jon Hall146f1522015-03-24 15:33:24 -07003846 break
3847 if state == "ACTIVE" or state == "INSTALLED":
3848 return state
3849 elif state is None:
You Wang0d9f2c02018-08-10 14:56:32 -07003850 main.log.warn( "{} app not found".format( appName ) )
Jon Hall146f1522015-03-24 15:33:24 -07003851 return "UNINSTALLED"
3852 elif state:
3853 main.log.error( "Unexpected state from 'onos:apps': " +
3854 str( state ) )
3855 return state
Jon Hallc6793552016-01-19 14:18:37 -08003856 except ( TypeError, ValueError ):
3857 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003858 return None
3859 except pexpect.EOF:
3860 main.log.error( self.name + ": EOF exception found" )
3861 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003862 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003863 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003864 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003865 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003866
Jon Hallbe379602015-03-24 13:39:32 -07003867 def app( self, appName, option ):
3868 """
3869 Interacts with the app command for ONOS. This command manages
3870 application inventory.
3871 """
Jon Hallbe379602015-03-24 13:39:32 -07003872 try:
Jon Hallbd16b922015-03-26 17:53:15 -07003873 # Validate argument types
3874 valid = True
3875 if not isinstance( appName, types.StringType ):
3876 main.log.error( self.name + ".app(): appName must be a " +
3877 "string" )
3878 valid = False
3879 if not isinstance( option, types.StringType ):
3880 main.log.error( self.name + ".app(): option must be a string" )
3881 valid = False
3882 if not valid:
3883 return main.FALSE
3884 # Validate Option
3885 option = option.lower()
3886 # NOTE: Install may become a valid option
3887 if option == "activate":
3888 pass
3889 elif option == "deactivate":
3890 pass
3891 elif option == "uninstall":
3892 pass
3893 else:
3894 # Invalid option
3895 main.log.error( "The ONOS app command argument only takes " +
3896 "the values: (activate|deactivate|uninstall)" +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003897 "; was given '" + option + "'" )
Jon Hallbd16b922015-03-26 17:53:15 -07003898 return main.FALSE
Jon Hall146f1522015-03-24 15:33:24 -07003899 cmdStr = "onos:app " + option + " " + appName
Jon Hallbe379602015-03-24 13:39:32 -07003900 output = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003901 assert output is not None, "Error in sendline"
3902 assert "Command not found:" not in output, output
Jon Hallbe379602015-03-24 13:39:32 -07003903 if "Error executing command" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003904 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hallbe379602015-03-24 13:39:32 -07003905 str( output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003906 return main.FALSE
Jon Hallbe379602015-03-24 13:39:32 -07003907 elif "No such application" in output:
3908 main.log.error( "The application '" + appName +
3909 "' is not installed in ONOS" )
Jon Hall146f1522015-03-24 15:33:24 -07003910 return main.FALSE
3911 elif "Command not found:" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003912 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hall146f1522015-03-24 15:33:24 -07003913 str( output ) )
3914 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003915 elif "Unsupported command:" in output:
3916 main.log.error( "Incorrect command given to 'app': " +
3917 str( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003918 # NOTE: we may need to add more checks here
Jon Hallbd16b922015-03-26 17:53:15 -07003919 # else: Command was successful
Jon Hall08f61bc2015-04-13 16:00:30 -07003920 # main.log.debug( "app response: " + repr( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003921 return main.TRUE
You Wangb5a55f72017-03-03 12:51:05 -08003922 except AssertionError:
3923 main.log.exception( self.name + ": AssertionError exception found" )
3924 return main.ERROR
Jon Hallbe379602015-03-24 13:39:32 -07003925 except TypeError:
3926 main.log.exception( self.name + ": Object not as expected" )
3927 return main.ERROR
3928 except pexpect.EOF:
3929 main.log.error( self.name + ": EOF exception found" )
3930 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003931 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003932 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003933 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003934 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003935
Jon Hallbd16b922015-03-26 17:53:15 -07003936 def activateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003937 """
3938 Activate an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003939 appName is the hierarchical app name, not the feature name
3940 If check is True, method will check the status of the app after the
3941 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003942 Returns main.TRUE if the command was successfully sent
3943 main.FALSE if the cli responded with an error or given
3944 incorrect input
3945 """
3946 try:
3947 if not isinstance( appName, types.StringType ):
3948 main.log.error( self.name + ".activateApp(): appName must be" +
3949 " a string" )
3950 return main.FALSE
3951 status = self.appStatus( appName )
3952 if status == "INSTALLED":
3953 response = self.app( appName, "activate" )
Jon Hallbd16b922015-03-26 17:53:15 -07003954 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003955 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07003956 status = self.appStatus( appName )
3957 if status == "ACTIVE":
3958 return main.TRUE
3959 else:
Jon Hall050e1bd2015-03-30 13:33:02 -07003960 main.log.debug( "The state of application " +
3961 appName + " is " + status )
Jon Hallbd16b922015-03-26 17:53:15 -07003962 time.sleep( 1 )
3963 return main.FALSE
3964 else: # not 'check' or command didn't succeed
3965 return response
Jon Hall146f1522015-03-24 15:33:24 -07003966 elif status == "ACTIVE":
3967 return main.TRUE
3968 elif status == "UNINSTALLED":
3969 main.log.error( self.name + ": Tried to activate the " +
3970 "application '" + appName + "' which is not " +
3971 "installed." )
3972 else:
3973 main.log.error( "Unexpected return value from appStatus: " +
3974 str( status ) )
3975 return main.ERROR
3976 except TypeError:
3977 main.log.exception( self.name + ": Object not as expected" )
3978 return main.ERROR
3979 except pexpect.EOF:
3980 main.log.error( self.name + ": EOF exception found" )
3981 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003982 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003983 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003984 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003985 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003986
Jon Hallbd16b922015-03-26 17:53:15 -07003987 def deactivateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003988 """
3989 Deactivate an app that is already activated in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003990 appName is the hierarchical app name, not the feature name
3991 If check is True, method will check the status of the app after the
3992 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003993 Returns main.TRUE if the command was successfully sent
3994 main.FALSE if the cli responded with an error or given
3995 incorrect input
3996 """
3997 try:
3998 if not isinstance( appName, types.StringType ):
3999 main.log.error( self.name + ".deactivateApp(): appName must " +
4000 "be a string" )
4001 return main.FALSE
4002 status = self.appStatus( appName )
4003 if status == "INSTALLED":
4004 return main.TRUE
4005 elif status == "ACTIVE":
4006 response = self.app( appName, "deactivate" )
Jon Hallbd16b922015-03-26 17:53:15 -07004007 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004008 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004009 status = self.appStatus( appName )
4010 if status == "INSTALLED":
4011 return main.TRUE
4012 else:
4013 time.sleep( 1 )
4014 return main.FALSE
4015 else: # not check or command didn't succeed
4016 return response
Jon Hall146f1522015-03-24 15:33:24 -07004017 elif status == "UNINSTALLED":
4018 main.log.warn( self.name + ": Tried to deactivate the " +
4019 "application '" + appName + "' which is not " +
4020 "installed." )
4021 return main.TRUE
4022 else:
4023 main.log.error( "Unexpected return value from appStatus: " +
4024 str( status ) )
4025 return main.ERROR
4026 except TypeError:
4027 main.log.exception( self.name + ": Object not as expected" )
4028 return main.ERROR
4029 except pexpect.EOF:
4030 main.log.error( self.name + ": EOF exception found" )
4031 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004032 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004033 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004034 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004035 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004036
Jon Hallbd16b922015-03-26 17:53:15 -07004037 def uninstallApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004038 """
4039 Uninstall an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004040 appName is the hierarchical app name, not the feature name
4041 If check is True, method will check the status of the app after the
4042 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004043 Returns main.TRUE if the command was successfully sent
4044 main.FALSE if the cli responded with an error or given
4045 incorrect input
4046 """
4047 # TODO: check with Thomas about the state machine for apps
4048 try:
4049 if not isinstance( appName, types.StringType ):
4050 main.log.error( self.name + ".uninstallApp(): appName must " +
4051 "be a string" )
4052 return main.FALSE
4053 status = self.appStatus( appName )
4054 if status == "INSTALLED":
4055 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004056 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004057 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004058 status = self.appStatus( appName )
4059 if status == "UNINSTALLED":
4060 return main.TRUE
4061 else:
4062 time.sleep( 1 )
4063 return main.FALSE
4064 else: # not check or command didn't succeed
4065 return response
Jon Hall146f1522015-03-24 15:33:24 -07004066 elif status == "ACTIVE":
4067 main.log.warn( self.name + ": Tried to uninstall the " +
4068 "application '" + appName + "' which is " +
4069 "currently active." )
4070 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004071 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004072 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004073 status = self.appStatus( appName )
4074 if status == "UNINSTALLED":
4075 return main.TRUE
4076 else:
4077 time.sleep( 1 )
4078 return main.FALSE
4079 else: # not check or command didn't succeed
4080 return response
Jon Hall146f1522015-03-24 15:33:24 -07004081 elif status == "UNINSTALLED":
4082 return main.TRUE
4083 else:
4084 main.log.error( "Unexpected return value from appStatus: " +
4085 str( status ) )
4086 return main.ERROR
4087 except TypeError:
4088 main.log.exception( self.name + ": Object not as expected" )
4089 return main.ERROR
4090 except pexpect.EOF:
4091 main.log.error( self.name + ": EOF exception found" )
4092 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004093 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004094 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004095 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004096 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004097
4098 def appIDs( self, jsonFormat=True ):
4099 """
4100 Show the mappings between app id and app names given by the 'app-ids'
4101 cli command
4102 """
4103 try:
4104 cmdStr = "app-ids"
4105 if jsonFormat:
4106 cmdStr += " -j"
Jon Hallc6358dd2015-04-10 12:44:28 -07004107 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004108 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004109 assert "Command not found:" not in output, output
4110 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07004111 return output
Jon Hallbd16b922015-03-26 17:53:15 -07004112 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004113 main.log.exception( self.name + ": Error in processing onos:app-ids command." )
Jon Hallbd16b922015-03-26 17:53:15 -07004114 return None
4115 except TypeError:
4116 main.log.exception( self.name + ": Object not as expected" )
4117 return None
4118 except pexpect.EOF:
4119 main.log.error( self.name + ": EOF exception found" )
4120 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004121 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004122 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004123 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004124 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004125
4126 def appToIDCheck( self ):
4127 """
4128 This method will check that each application's ID listed in 'apps' is
4129 the same as the ID listed in 'app-ids'. The check will also check that
4130 there are no duplicate IDs issued. Note that an app ID should be
4131 a globaly unique numerical identifier for app/app-like features. Once
4132 an ID is registered, the ID is never freed up so that if an app is
4133 reinstalled it will have the same ID.
4134
4135 Returns: main.TRUE if the check passes and
4136 main.FALSE if the check fails or
4137 main.ERROR if there is some error in processing the test
4138 """
4139 try:
Jon Hall0e240372018-05-02 11:21:57 -07004140 # Grab IDs
Jon Hallc6793552016-01-19 14:18:37 -08004141 rawJson = self.appIDs( jsonFormat=True )
4142 if rawJson:
4143 ids = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004144 else:
Jon Hall0e240372018-05-02 11:21:57 -07004145 main.log.error( "app-ids returned nothing: " + repr( rawJson ) )
4146 return main.FALSE
4147
4148 # Grab Apps
Jon Hallc6793552016-01-19 14:18:37 -08004149 rawJson = self.apps( jsonFormat=True )
4150 if rawJson:
4151 apps = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004152 else:
Jon Hallc6793552016-01-19 14:18:37 -08004153 main.log.error( "apps returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07004154 return main.FALSE
Jon Hall0e240372018-05-02 11:21:57 -07004155
Jon Hallbd16b922015-03-26 17:53:15 -07004156 result = main.TRUE
4157 for app in apps:
4158 appID = app.get( 'id' )
4159 if appID is None:
4160 main.log.error( "Error parsing app: " + str( app ) )
4161 result = main.FALSE
4162 appName = app.get( 'name' )
4163 if appName is None:
4164 main.log.error( "Error parsing app: " + str( app ) )
4165 result = main.FALSE
4166 # get the entry in ids that has the same appID
Jon Hall390696c2015-05-05 17:13:41 -07004167 current = filter( lambda item: item[ 'id' ] == appID, ids )
Jon Hallbd16b922015-03-26 17:53:15 -07004168 if not current: # if ids doesn't have this id
4169 result = main.FALSE
4170 main.log.error( "'app-ids' does not have the ID for " +
4171 str( appName ) + " that apps does." )
Jon Hallb9d381e2018-02-05 12:02:10 -08004172 main.log.debug( "apps command returned: " + str( app ) +
4173 "; app-ids has: " + str( ids ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004174 elif len( current ) > 1:
4175 # there is more than one app with this ID
4176 result = main.FALSE
4177 # We will log this later in the method
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004178 elif not current[ 0 ][ 'name' ] == appName:
4179 currentName = current[ 0 ][ 'name' ]
Jon Hallbd16b922015-03-26 17:53:15 -07004180 result = main.FALSE
4181 main.log.error( "'app-ids' has " + str( currentName ) +
4182 " registered under id:" + str( appID ) +
4183 " but 'apps' has " + str( appName ) )
4184 else:
4185 pass # id and name match!
Jon Hall0e240372018-05-02 11:21:57 -07004186
Jon Hallbd16b922015-03-26 17:53:15 -07004187 # now make sure that app-ids has no duplicates
4188 idsList = []
4189 namesList = []
4190 for item in ids:
4191 idsList.append( item[ 'id' ] )
4192 namesList.append( item[ 'name' ] )
4193 if len( idsList ) != len( set( idsList ) ) or\
4194 len( namesList ) != len( set( namesList ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004195 main.log.error( "'app-ids' has some duplicate entries: \n"
4196 + json.dumps( ids,
4197 sort_keys=True,
4198 indent=4,
4199 separators=( ',', ': ' ) ) )
4200 result = main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07004201 return result
Jon Hallc6793552016-01-19 14:18:37 -08004202 except ( TypeError, ValueError ):
4203 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004204 return main.ERROR
4205 except pexpect.EOF:
4206 main.log.error( self.name + ": EOF exception found" )
4207 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004208 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004209 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004210 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004211 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004212
Jon Hallfb760a02015-04-13 15:35:03 -07004213 def getCfg( self, component=None, propName=None, short=False,
4214 jsonFormat=True ):
4215 """
4216 Get configuration settings from onos cli
4217 Optional arguments:
4218 component - Optionally only list configurations for a specific
4219 component. If None, all components with configurations
4220 are displayed. Case Sensitive string.
4221 propName - If component is specified, propName option will show
4222 only this specific configuration from that component.
4223 Case Sensitive string.
4224 jsonFormat - Returns output as json. Note that this will override
4225 the short option
4226 short - Short, less verbose, version of configurations.
4227 This is overridden by the json option
4228 returns:
4229 Output from cli as a string or None on error
4230 """
4231 try:
4232 baseStr = "cfg"
4233 cmdStr = " get"
4234 componentStr = ""
4235 if component:
4236 componentStr += " " + component
4237 if propName:
4238 componentStr += " " + propName
4239 if jsonFormat:
4240 baseStr += " -j"
Jon Hall22e94ce2019-01-15 14:52:17 -08004241 expectJson = True
Jon Hallfb760a02015-04-13 15:35:03 -07004242 elif short:
4243 baseStr += " -s"
Jon Hall22e94ce2019-01-15 14:52:17 -08004244 expectJson = False
4245 output = self.sendline( baseStr + cmdStr + componentStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07004246 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004247 assert "Command not found:" not in output, output
4248 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004249 return output
4250 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004251 main.log.exception( self.name + ": Error in processing 'cfg get' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004252 return None
4253 except TypeError:
4254 main.log.exception( self.name + ": Object not as expected" )
4255 return None
4256 except pexpect.EOF:
4257 main.log.error( self.name + ": EOF exception found" )
4258 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004259 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004260 except Exception:
4261 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004262 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004263
4264 def setCfg( self, component, propName, value=None, check=True ):
4265 """
4266 Set/Unset configuration settings from ONOS cli
Jon Hall390696c2015-05-05 17:13:41 -07004267 Required arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004268 component - The case sensitive name of the component whose
4269 property is to be set
4270 propName - The case sensitive name of the property to be set/unset
Jon Hall390696c2015-05-05 17:13:41 -07004271 Optional arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004272 value - The value to set the property to. If None, will unset the
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004273 property and revert it to it's default value(if applicable)
Jon Hallfb760a02015-04-13 15:35:03 -07004274 check - Boolean, Check whether the option was successfully set this
4275 only applies when a value is given.
4276 returns:
4277 main.TRUE on success or main.FALSE on failure. If check is False,
4278 will return main.TRUE unless there is an error
4279 """
4280 try:
4281 baseStr = "cfg"
4282 cmdStr = " set " + str( component ) + " " + str( propName )
4283 if value is not None:
4284 cmdStr += " " + str( value )
4285 output = self.sendline( baseStr + cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004286 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004287 assert "Command not found:" not in output, output
4288 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004289 if value and check:
4290 results = self.getCfg( component=str( component ),
4291 propName=str( propName ),
4292 jsonFormat=True )
4293 # Check if current value is what we just set
4294 try:
4295 jsonOutput = json.loads( results )
4296 current = jsonOutput[ 'value' ]
Jon Hallc6793552016-01-19 14:18:37 -08004297 except ( TypeError, ValueError ):
Jon Hallfb760a02015-04-13 15:35:03 -07004298 main.log.exception( "Error parsing cfg output" )
4299 main.log.error( "output:" + repr( results ) )
4300 return main.FALSE
4301 if current == str( value ):
4302 return main.TRUE
4303 return main.FALSE
4304 return main.TRUE
4305 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004306 main.log.exception( self.name + ": Error in processing 'cfg set' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004307 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08004308 except ( TypeError, ValueError ):
4309 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, results ) )
Jon Hallfb760a02015-04-13 15:35:03 -07004310 return main.FALSE
4311 except pexpect.EOF:
4312 main.log.error( self.name + ": EOF exception found" )
4313 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004314 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004315 except Exception:
4316 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004317 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004318
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004319 def distPrimitivesSend( self, cmd ):
4320 """
4321 Function to handle sending cli commands for the distributed primitives test app
4322
4323 This command will catch some exceptions and retry the command on some
4324 specific store exceptions.
4325
4326 Required arguments:
4327 cmd - The command to send to the cli
4328 returns:
4329 string containing the cli output
4330 None on Error
4331 """
4332 try:
4333 output = self.sendline( cmd )
4334 try:
4335 assert output is not None, "Error in sendline"
4336 # TODO: Maybe make this less hardcoded
4337 # ConsistentMap Exceptions
4338 assert "org.onosproject.store.service" not in output
4339 # Node not leader
4340 assert "java.lang.IllegalStateException" not in output
4341 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004342 main.log.error( self.name + ": Error in processing '" + cmd + "' " +
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004343 "command: " + str( output ) )
4344 retryTime = 30 # Conservative time, given by Madan
4345 main.log.info( "Waiting " + str( retryTime ) +
4346 "seconds before retrying." )
4347 time.sleep( retryTime ) # Due to change in mastership
4348 output = self.sendline( cmd )
4349 assert output is not None, "Error in sendline"
4350 assert "Command not found:" not in output, output
4351 assert "Error executing command" not in output, output
4352 main.log.info( self.name + ": " + output )
4353 return output
4354 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004355 main.log.exception( self.name + ": Error in processing '" + cmd + "' command." )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004356 return None
4357 except TypeError:
4358 main.log.exception( self.name + ": Object not as expected" )
4359 return None
4360 except pexpect.EOF:
4361 main.log.error( self.name + ": EOF exception found" )
4362 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004363 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004364 except Exception:
4365 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004366 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004367
Jon Hall390696c2015-05-05 17:13:41 -07004368 def setTestAdd( self, setName, values ):
4369 """
4370 CLI command to add elements to a distributed set.
4371 Arguments:
4372 setName - The name of the set to add to.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004373 values - The value(s) to add to the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004374 Example usages:
4375 setTestAdd( "set1", "a b c" )
4376 setTestAdd( "set2", "1" )
4377 returns:
4378 main.TRUE on success OR
4379 main.FALSE if elements were already in the set OR
4380 main.ERROR on error
4381 """
4382 try:
4383 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004384 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004385 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
4386 negativeMatch = "\[(.*)\] was already in set " + str( setName )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004387 if re.search( positiveMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004388 return main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004389 elif re.search( negativeMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004390 return main.FALSE
4391 else:
4392 main.log.error( self.name + ": setTestAdd did not" +
4393 " match expected output" )
Jon Hall390696c2015-05-05 17:13:41 -07004394 main.log.debug( self.name + " actual: " + repr( output ) )
4395 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004396 except TypeError:
4397 main.log.exception( self.name + ": Object not as expected" )
4398 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004399 except Exception:
4400 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004401 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004402
4403 def setTestRemove( self, setName, values, clear=False, retain=False ):
4404 """
4405 CLI command to remove elements from a distributed set.
4406 Required arguments:
4407 setName - The name of the set to remove from.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004408 values - The value(s) to remove from the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004409 Optional arguments:
4410 clear - Clear all elements from the set
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004411 retain - Retain only the given values. (intersection of the
4412 original set and the given set)
Jon Hall390696c2015-05-05 17:13:41 -07004413 returns:
4414 main.TRUE on success OR
4415 main.FALSE if the set was not changed OR
4416 main.ERROR on error
4417 """
4418 try:
4419 cmdStr = "set-test-remove "
4420 if clear:
4421 cmdStr += "-c " + str( setName )
4422 elif retain:
4423 cmdStr += "-r " + str( setName ) + " " + str( values )
4424 else:
4425 cmdStr += str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004426 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004427 if clear:
4428 pattern = "Set " + str( setName ) + " cleared"
4429 if re.search( pattern, output ):
4430 return main.TRUE
4431 elif retain:
4432 positivePattern = str( setName ) + " was pruned to contain " +\
4433 "only elements of set \[(.*)\]"
4434 negativePattern = str( setName ) + " was not changed by " +\
4435 "retaining only elements of the set " +\
4436 "\[(.*)\]"
4437 if re.search( positivePattern, output ):
4438 return main.TRUE
4439 elif re.search( negativePattern, output ):
4440 return main.FALSE
4441 else:
4442 positivePattern = "\[(.*)\] was removed from the set " +\
4443 str( setName )
4444 if ( len( values.split() ) == 1 ):
4445 negativePattern = "\[(.*)\] was not in set " +\
4446 str( setName )
4447 else:
4448 negativePattern = "No element of \[(.*)\] was in set " +\
4449 str( setName )
4450 if re.search( positivePattern, output ):
4451 return main.TRUE
4452 elif re.search( negativePattern, output ):
4453 return main.FALSE
4454 main.log.error( self.name + ": setTestRemove did not" +
4455 " match expected output" )
4456 main.log.debug( self.name + " expected: " + pattern )
4457 main.log.debug( self.name + " actual: " + repr( output ) )
4458 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004459 except TypeError:
4460 main.log.exception( self.name + ": Object not as expected" )
4461 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004462 except Exception:
4463 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004464 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004465
4466 def setTestGet( self, setName, values="" ):
4467 """
4468 CLI command to get the elements in a distributed set.
4469 Required arguments:
4470 setName - The name of the set to remove from.
4471 Optional arguments:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004472 values - The value(s) to check if in the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004473 returns:
4474 main.ERROR on error OR
4475 A list of elements in the set if no optional arguments are
4476 supplied OR
4477 A tuple containing the list then:
4478 main.FALSE if the given values are not in the set OR
4479 main.TRUE if the given values are in the set OR
4480 """
4481 try:
4482 values = str( values ).strip()
4483 setName = str( setName ).strip()
4484 length = len( values.split() )
4485 containsCheck = None
4486 # Patterns to match
4487 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004488 pattern = "Items in set " + setName + ":\r\n" + setPattern
Jon Hall390696c2015-05-05 17:13:41 -07004489 containsTrue = "Set " + setName + " contains the value " + values
4490 containsFalse = "Set " + setName + " did not contain the value " +\
4491 values
4492 containsAllTrue = "Set " + setName + " contains the the subset " +\
4493 setPattern
4494 containsAllFalse = "Set " + setName + " did not contain the the" +\
4495 " subset " + setPattern
4496
4497 cmdStr = "set-test-get "
4498 cmdStr += setName + " " + values
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004499 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004500 if length == 0:
4501 match = re.search( pattern, output )
4502 else: # if given values
4503 if length == 1: # Contains output
Jon Hall54b994f2016-12-05 10:48:59 -08004504 patternTrue = pattern + "\r\n" + containsTrue
4505 patternFalse = pattern + "\r\n" + containsFalse
Jon Hall390696c2015-05-05 17:13:41 -07004506 else: # ContainsAll output
Jon Hall54b994f2016-12-05 10:48:59 -08004507 patternTrue = pattern + "\r\n" + containsAllTrue
4508 patternFalse = pattern + "\r\n" + containsAllFalse
Jon Hall390696c2015-05-05 17:13:41 -07004509 matchTrue = re.search( patternTrue, output )
4510 matchFalse = re.search( patternFalse, output )
4511 if matchTrue:
4512 containsCheck = main.TRUE
4513 match = matchTrue
4514 elif matchFalse:
4515 containsCheck = main.FALSE
4516 match = matchFalse
4517 else:
Jon Halle0f0b342017-04-18 11:43:47 -07004518 main.log.error( self.name + " setTestGet did not match " +
Jon Hall390696c2015-05-05 17:13:41 -07004519 "expected output" )
4520 main.log.debug( self.name + " expected: " + pattern )
4521 main.log.debug( self.name + " actual: " + repr( output ) )
4522 match = None
4523 if match:
4524 setMatch = match.group( 1 )
4525 if setMatch == '':
4526 setList = []
4527 else:
4528 setList = setMatch.split( ", " )
4529 if length > 0:
4530 return ( setList, containsCheck )
4531 else:
4532 return setList
4533 else: # no match
4534 main.log.error( self.name + ": setTestGet did not" +
4535 " match expected output" )
4536 main.log.debug( self.name + " expected: " + pattern )
4537 main.log.debug( self.name + " actual: " + repr( output ) )
4538 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004539 except TypeError:
4540 main.log.exception( self.name + ": Object not as expected" )
4541 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004542 except Exception:
4543 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004544 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004545
4546 def setTestSize( self, setName ):
4547 """
4548 CLI command to get the elements in a distributed set.
4549 Required arguments:
4550 setName - The name of the set to remove from.
4551 returns:
Jon Hallfeff3082015-05-19 10:23:26 -07004552 The integer value of the size returned or
Jon Hall390696c2015-05-05 17:13:41 -07004553 None on error
4554 """
4555 try:
4556 # TODO: Should this check against the number of elements returned
4557 # and then return true/false based on that?
4558 setName = str( setName ).strip()
4559 # Patterns to match
4560 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004561 pattern = "There are (\d+) items in set " + setName + ":\r\n" +\
Jon Hall390696c2015-05-05 17:13:41 -07004562 setPattern
4563 cmdStr = "set-test-get -s "
4564 cmdStr += setName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004565 output = self.distPrimitivesSend( cmdStr )
Jon Hall0e240372018-05-02 11:21:57 -07004566 if output:
4567 match = re.search( pattern, output )
4568 if match:
4569 setSize = int( match.group( 1 ) )
4570 setMatch = match.group( 2 )
4571 if len( setMatch.split() ) == setSize:
4572 main.log.info( "The size returned by " + self.name +
4573 " matches the number of elements in " +
4574 "the returned set" )
4575 else:
4576 main.log.error( "The size returned by " + self.name +
4577 " does not match the number of " +
4578 "elements in the returned set." )
4579 return setSize
Jon Hall390696c2015-05-05 17:13:41 -07004580 else: # no match
4581 main.log.error( self.name + ": setTestGet did not" +
4582 " match expected output" )
4583 main.log.debug( self.name + " expected: " + pattern )
4584 main.log.debug( self.name + " actual: " + repr( output ) )
4585 return None
Jon Hall390696c2015-05-05 17:13:41 -07004586 except TypeError:
4587 main.log.exception( self.name + ": Object not as expected" )
4588 return None
Jon Hall390696c2015-05-05 17:13:41 -07004589 except Exception:
4590 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004591 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004592
Jon Hall80daded2015-05-27 16:07:00 -07004593 def counters( self, jsonFormat=True ):
Jon Hall390696c2015-05-05 17:13:41 -07004594 """
4595 Command to list the various counters in the system.
4596 returns:
Jon Hall80daded2015-05-27 16:07:00 -07004597 if jsonFormat, a string of the json object returned by the cli
4598 command
4599 if not jsonFormat, the normal string output of the cli command
Jon Hall390696c2015-05-05 17:13:41 -07004600 None on error
4601 """
Jon Hall390696c2015-05-05 17:13:41 -07004602 try:
Jon Hall390696c2015-05-05 17:13:41 -07004603 cmdStr = "counters"
Jon Hall80daded2015-05-27 16:07:00 -07004604 if jsonFormat:
4605 cmdStr += " -j"
Jon Hall390696c2015-05-05 17:13:41 -07004606 output = self.sendline( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004607 main.log.debug( self.name + ": Counters unparsed: " + output )
4608 output = output.split( "\r\n" )[ -1 ]
4609 main.log.debug( self.name + ": Counters parsed: " + output )
Jon Halla495f562016-05-16 18:03:26 -07004610 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004611 assert "Command not found:" not in output, output
4612 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004613 main.log.info( self.name + ": " + output )
Jon Hall80daded2015-05-27 16:07:00 -07004614 return output
Jon Hall390696c2015-05-05 17:13:41 -07004615 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004616 main.log.exception( self.name + ": Error in processing 'counters' command." )
Jon Hall80daded2015-05-27 16:07:00 -07004617 return None
Jon Hall390696c2015-05-05 17:13:41 -07004618 except TypeError:
4619 main.log.exception( self.name + ": Object not as expected" )
Jon Hall80daded2015-05-27 16:07:00 -07004620 return None
Jon Hall390696c2015-05-05 17:13:41 -07004621 except pexpect.EOF:
4622 main.log.error( self.name + ": EOF exception found" )
4623 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004624 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004625 except Exception:
4626 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004627 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004628
Jon Hall935db192016-04-19 00:22:04 -07004629 def counterTestAddAndGet( self, counter, delta=1 ):
Jon Hall390696c2015-05-05 17:13:41 -07004630 """
Jon Halle1a3b752015-07-22 13:02:46 -07004631 CLI command to add a delta to then get a distributed counter.
Jon Hall390696c2015-05-05 17:13:41 -07004632 Required arguments:
4633 counter - The name of the counter to increment.
4634 Optional arguments:
Jon Halle1a3b752015-07-22 13:02:46 -07004635 delta - The long to add to the counter
Jon Hall390696c2015-05-05 17:13:41 -07004636 returns:
4637 integer value of the counter or
4638 None on Error
4639 """
4640 try:
4641 counter = str( counter )
Jon Halle1a3b752015-07-22 13:02:46 -07004642 delta = int( delta )
Jon Hall390696c2015-05-05 17:13:41 -07004643 cmdStr = "counter-test-increment "
Jon Hall390696c2015-05-05 17:13:41 -07004644 cmdStr += counter
Jon Halle1a3b752015-07-22 13:02:46 -07004645 if delta != 1:
4646 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004647 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004648 pattern = counter + " was updated to (-?\d+)"
Jon Hall390696c2015-05-05 17:13:41 -07004649 match = re.search( pattern, output )
4650 if match:
4651 return int( match.group( 1 ) )
4652 else:
Jon Halle1a3b752015-07-22 13:02:46 -07004653 main.log.error( self.name + ": counterTestAddAndGet did not" +
Jon Hall390696c2015-05-05 17:13:41 -07004654 " match expected output." )
4655 main.log.debug( self.name + " expected: " + pattern )
4656 main.log.debug( self.name + " actual: " + repr( output ) )
4657 return None
Jon Hall390696c2015-05-05 17:13:41 -07004658 except TypeError:
4659 main.log.exception( self.name + ": Object not as expected" )
4660 return None
Jon Hall390696c2015-05-05 17:13:41 -07004661 except Exception:
4662 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004663 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004664
Jon Hall935db192016-04-19 00:22:04 -07004665 def counterTestGetAndAdd( self, counter, delta=1 ):
Jon Halle1a3b752015-07-22 13:02:46 -07004666 """
4667 CLI command to get a distributed counter then add a delta to it.
4668 Required arguments:
4669 counter - The name of the counter to increment.
4670 Optional arguments:
4671 delta - The long to add to the counter
Jon Halle1a3b752015-07-22 13:02:46 -07004672 returns:
4673 integer value of the counter or
4674 None on Error
4675 """
4676 try:
4677 counter = str( counter )
4678 delta = int( delta )
4679 cmdStr = "counter-test-increment -g "
Jon Halle1a3b752015-07-22 13:02:46 -07004680 cmdStr += counter
4681 if delta != 1:
4682 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004683 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004684 pattern = counter + " was updated to (-?\d+)"
4685 match = re.search( pattern, output )
4686 if match:
4687 return int( match.group( 1 ) )
4688 else:
4689 main.log.error( self.name + ": counterTestGetAndAdd did not" +
4690 " match expected output." )
4691 main.log.debug( self.name + " expected: " + pattern )
4692 main.log.debug( self.name + " actual: " + repr( output ) )
4693 return None
Jon Halle1a3b752015-07-22 13:02:46 -07004694 except TypeError:
4695 main.log.exception( self.name + ": Object not as expected" )
4696 return None
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004697 except Exception:
4698 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004699 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004700
4701 def valueTestGet( self, valueName ):
4702 """
4703 CLI command to get the value of an atomic value.
4704 Required arguments:
4705 valueName - The name of the value to get.
4706 returns:
4707 string value of the value or
4708 None on Error
4709 """
4710 try:
4711 valueName = str( valueName )
4712 cmdStr = "value-test "
4713 operation = "get"
4714 cmdStr = "value-test {} {}".format( valueName,
4715 operation )
4716 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004717 main.log.debug( self.name + ": value test unparsed: " + output )
4718 output = output.split( "\r\n" )[ -1 ]
4719 main.log.debug( self.name + ": value test parsed: " + output )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004720 pattern = "(\w+)"
4721 match = re.search( pattern, output )
4722 if match:
4723 return match.group( 1 )
4724 else:
4725 main.log.error( self.name + ": valueTestGet did not" +
4726 " match expected output." )
4727 main.log.debug( self.name + " expected: " + pattern )
4728 main.log.debug( self.name + " actual: " + repr( output ) )
4729 return None
4730 except TypeError:
4731 main.log.exception( self.name + ": Object not as expected" )
4732 return None
4733 except Exception:
4734 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004735 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004736
4737 def valueTestSet( self, valueName, newValue ):
4738 """
4739 CLI command to set the value of an atomic value.
4740 Required arguments:
4741 valueName - The name of the value to set.
4742 newValue - The value to assign to the given value.
4743 returns:
4744 main.TRUE on success or
4745 main.ERROR on Error
4746 """
4747 try:
4748 valueName = str( valueName )
4749 newValue = str( newValue )
4750 operation = "set"
4751 cmdStr = "value-test {} {} {}".format( valueName,
4752 operation,
4753 newValue )
4754 output = self.distPrimitivesSend( cmdStr )
4755 if output is not None:
4756 return main.TRUE
4757 else:
4758 return main.ERROR
4759 except TypeError:
4760 main.log.exception( self.name + ": Object not as expected" )
4761 return main.ERROR
4762 except Exception:
4763 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004764 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004765
4766 def valueTestCompareAndSet( self, valueName, oldValue, newValue ):
4767 """
4768 CLI command to compareAndSet the value of an atomic value.
4769 Required arguments:
4770 valueName - The name of the value.
4771 oldValue - Compare the current value of the atomic value to this
4772 newValue - If the value equals oldValue, set the value to newValue
4773 returns:
4774 main.TRUE on success or
4775 main.FALSE on failure or
4776 main.ERROR on Error
4777 """
4778 try:
4779 valueName = str( valueName )
4780 oldValue = str( oldValue )
4781 newValue = str( newValue )
4782 operation = "compareAndSet"
4783 cmdStr = "value-test {} {} {} {}".format( valueName,
4784 operation,
4785 oldValue,
4786 newValue )
4787 output = self.distPrimitivesSend( cmdStr )
4788 pattern = "(\w+)"
4789 match = re.search( pattern, output )
4790 if match:
4791 result = match.group( 1 )
4792 if result == "true":
4793 return main.TRUE
4794 elif result == "false":
4795 return main.FALSE
4796 else:
4797 main.log.error( self.name + ": valueTestCompareAndSet did not" +
4798 " match expected output." )
4799 main.log.debug( self.name + " expected: " + pattern )
4800 main.log.debug( self.name + " actual: " + repr( output ) )
4801 return main.ERROR
4802 except TypeError:
4803 main.log.exception( self.name + ": Object not as expected" )
4804 return main.ERROR
4805 except Exception:
4806 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004807 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004808
4809 def valueTestGetAndSet( self, valueName, newValue ):
4810 """
4811 CLI command to getAndSet the value of an atomic value.
4812 Required arguments:
4813 valueName - The name of the value to get.
4814 newValue - The value to assign to the given value
4815 returns:
4816 string value of the value or
4817 None on Error
4818 """
4819 try:
4820 valueName = str( valueName )
4821 cmdStr = "value-test "
4822 operation = "getAndSet"
4823 cmdStr += valueName + " " + operation
4824 cmdStr = "value-test {} {} {}".format( valueName,
4825 operation,
4826 newValue )
4827 output = self.distPrimitivesSend( cmdStr )
4828 pattern = "(\w+)"
4829 match = re.search( pattern, output )
4830 if match:
4831 return match.group( 1 )
4832 else:
4833 main.log.error( self.name + ": valueTestGetAndSet did not" +
4834 " match expected output." )
4835 main.log.debug( self.name + " expected: " + pattern )
4836 main.log.debug( self.name + " actual: " + repr( output ) )
4837 return None
4838 except TypeError:
4839 main.log.exception( self.name + ": Object not as expected" )
4840 return None
4841 except Exception:
4842 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004843 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004844
4845 def valueTestDestroy( self, valueName ):
4846 """
4847 CLI command to destroy an atomic value.
4848 Required arguments:
4849 valueName - The name of the value to destroy.
4850 returns:
4851 main.TRUE on success or
4852 main.ERROR on Error
4853 """
4854 try:
4855 valueName = str( valueName )
4856 cmdStr = "value-test "
4857 operation = "destroy"
4858 cmdStr += valueName + " " + operation
4859 output = self.distPrimitivesSend( cmdStr )
4860 if output is not None:
4861 return main.TRUE
4862 else:
4863 return main.ERROR
4864 except TypeError:
4865 main.log.exception( self.name + ": Object not as expected" )
4866 return main.ERROR
Jon Halle1a3b752015-07-22 13:02:46 -07004867 except Exception:
4868 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004869 main.cleanAndExit()
Jon Halle1a3b752015-07-22 13:02:46 -07004870
YPZhangfebf7302016-05-24 16:45:56 -07004871 def summary( self, jsonFormat=True, timeout=30 ):
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004872 """
4873 Description: Execute summary command in onos
4874 Returns: json object ( summary -j ), returns main.FALSE if there is
4875 no output
4876
4877 """
4878 try:
4879 cmdStr = "summary"
4880 if jsonFormat:
4881 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07004882 handle = self.sendline( cmdStr, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07004883 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004884 assert "Command not found:" not in handle, handle
Jon Hall6e709752016-02-01 13:38:46 -08004885 assert "Error:" not in handle, handle
Devin Lima7cfdbd2017-09-29 15:02:22 -07004886 assert "Error executing" not in handle, handle
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004887 if not handle:
4888 main.log.error( self.name + ": There is no output in " +
4889 "summary command" )
4890 return main.FALSE
4891 return handle
Jon Hallc6793552016-01-19 14:18:37 -08004892 except AssertionError:
Jon Hall6e709752016-02-01 13:38:46 -08004893 main.log.exception( "{} Error in summary output:".format( self.name ) )
Jon Hallc6793552016-01-19 14:18:37 -08004894 return None
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004895 except TypeError:
4896 main.log.exception( self.name + ": Object not as expected" )
4897 return None
4898 except pexpect.EOF:
4899 main.log.error( self.name + ": EOF exception found" )
4900 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004901 main.cleanAndExit()
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004902 except Exception:
4903 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004904 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004905
Jon Hall935db192016-04-19 00:22:04 -07004906 def transactionalMapGet( self, keyName ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004907 """
4908 CLI command to get the value of a key in a consistent map using
4909 transactions. This a test function and can only get keys from the
4910 test map hard coded into the cli command
4911 Required arguments:
4912 keyName - The name of the key to get
Jon Hall2a5002c2015-08-21 16:49:11 -07004913 returns:
4914 The string value of the key or
4915 None on Error
4916 """
4917 try:
4918 keyName = str( keyName )
4919 cmdStr = "transactional-map-test-get "
Jon Hall2a5002c2015-08-21 16:49:11 -07004920 cmdStr += keyName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004921 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07004922 pattern = "Key-value pair \(" + keyName + ", (?P<value>.+)\) found."
4923 if "Key " + keyName + " not found." in output:
Jon Hall9bfadd22016-05-11 14:48:07 -07004924 main.log.warn( output )
Jon Hall2a5002c2015-08-21 16:49:11 -07004925 return None
4926 else:
4927 match = re.search( pattern, output )
4928 if match:
4929 return match.groupdict()[ 'value' ]
4930 else:
4931 main.log.error( self.name + ": transactionlMapGet did not" +
4932 " match expected output." )
4933 main.log.debug( self.name + " expected: " + pattern )
4934 main.log.debug( self.name + " actual: " + repr( output ) )
4935 return None
4936 except TypeError:
4937 main.log.exception( self.name + ": Object not as expected" )
4938 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004939 except Exception:
4940 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004941 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004942
Jon Hall935db192016-04-19 00:22:04 -07004943 def transactionalMapPut( self, numKeys, value ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004944 """
4945 CLI command to put a value into 'numKeys' number of keys in a
4946 consistent map using transactions. This a test function and can only
4947 put into keys named 'Key#' of the test map hard coded into the cli command
4948 Required arguments:
4949 numKeys - Number of keys to add the value to
4950 value - The string value to put into the keys
Jon Hall2a5002c2015-08-21 16:49:11 -07004951 returns:
4952 A dictionary whose keys are the name of the keys put into the map
4953 and the values of the keys are dictionaries whose key-values are
4954 'value': value put into map and optionaly
4955 'oldValue': Previous value in the key or
4956 None on Error
4957
4958 Example output
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004959 { 'Key1': {'oldValue': 'oldTestValue', 'value': 'Testing'},
4960 'Key2': {'value': 'Testing'} }
Jon Hall2a5002c2015-08-21 16:49:11 -07004961 """
4962 try:
4963 numKeys = str( numKeys )
4964 value = str( value )
4965 cmdStr = "transactional-map-test-put "
Jon Hall2a5002c2015-08-21 16:49:11 -07004966 cmdStr += numKeys + " " + value
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004967 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07004968 newPattern = 'Created Key (?P<key>(\w)+) with value (?P<value>(.)+)\.'
4969 updatedPattern = "Put (?P<value>(.)+) into key (?P<key>(\w)+)\. The old value was (?P<oldValue>(.)+)\."
4970 results = {}
4971 for line in output.splitlines():
4972 new = re.search( newPattern, line )
4973 updated = re.search( updatedPattern, line )
4974 if new:
4975 results[ new.groupdict()[ 'key' ] ] = { 'value': new.groupdict()[ 'value' ] }
4976 elif updated:
4977 results[ updated.groupdict()[ 'key' ] ] = { 'value': updated.groupdict()[ 'value' ],
Jon Hallc6793552016-01-19 14:18:37 -08004978 'oldValue': updated.groupdict()[ 'oldValue' ] }
Jon Hall2a5002c2015-08-21 16:49:11 -07004979 else:
4980 main.log.error( self.name + ": transactionlMapGet did not" +
4981 " match expected output." )
Jon Hallc6793552016-01-19 14:18:37 -08004982 main.log.debug( "{} expected: {!r} or {!r}".format( self.name,
4983 newPattern,
4984 updatedPattern ) )
Jon Hall2a5002c2015-08-21 16:49:11 -07004985 main.log.debug( self.name + " actual: " + repr( output ) )
4986 return results
Jon Hall0e240372018-05-02 11:21:57 -07004987 except ( TypeError, AttributeError ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004988 main.log.exception( self.name + ": Object not as expected" )
4989 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004990 except Exception:
4991 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004992 main.cleanAndExit()
Jon Hallc6793552016-01-19 14:18:37 -08004993
acsmarsdaea66c2015-09-03 11:44:06 -07004994 def maps( self, jsonFormat=True ):
4995 """
4996 Description: Returns result of onos:maps
4997 Optional:
4998 * jsonFormat: enable json formatting of output
4999 """
5000 try:
5001 cmdStr = "maps"
5002 if jsonFormat:
5003 cmdStr += " -j"
5004 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07005005 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005006 assert "Command not found:" not in handle, handle
acsmarsdaea66c2015-09-03 11:44:06 -07005007 return handle
Jon Hallc6793552016-01-19 14:18:37 -08005008 except AssertionError:
5009 main.log.exception( "" )
5010 return None
acsmarsdaea66c2015-09-03 11:44:06 -07005011 except TypeError:
5012 main.log.exception( self.name + ": Object not as expected" )
5013 return None
5014 except pexpect.EOF:
5015 main.log.error( self.name + ": EOF exception found" )
5016 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005017 main.cleanAndExit()
acsmarsdaea66c2015-09-03 11:44:06 -07005018 except Exception:
5019 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005020 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005021
5022 def getSwController( self, uri, jsonFormat=True ):
5023 """
5024 Descrition: Gets the controller information from the device
5025 """
5026 try:
5027 cmd = "device-controllers "
5028 if jsonFormat:
5029 cmd += "-j "
5030 response = self.sendline( cmd + uri )
Jon Halla495f562016-05-16 18:03:26 -07005031 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005032 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005033 return response
Jon Hallc6793552016-01-19 14:18:37 -08005034 except AssertionError:
5035 main.log.exception( "" )
5036 return None
GlennRC050596c2015-11-18 17:06:41 -08005037 except TypeError:
5038 main.log.exception( self.name + ": Object not as expected" )
5039 return None
5040 except pexpect.EOF:
5041 main.log.error( self.name + ": EOF exception found" )
5042 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005043 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005044 except Exception:
5045 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005046 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005047
5048 def setSwController( self, uri, ip, proto="tcp", port="6653", jsonFormat=True ):
5049 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005050 Descrition: sets the controller(s) for the specified device
GlennRC050596c2015-11-18 17:06:41 -08005051
5052 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005053 Required: uri - String: The uri of the device(switch).
GlennRC050596c2015-11-18 17:06:41 -08005054 ip - String or List: The ip address of the controller.
5055 This parameter can be formed in a couple of different ways.
5056 VALID:
5057 10.0.0.1 - just the ip address
5058 tcp:10.0.0.1 - the protocol and the ip address
5059 tcp:10.0.0.1:6653 - the protocol and port can be specified,
5060 so that you can add controllers with different
5061 protocols and ports
5062 INVALID:
5063 10.0.0.1:6653 - this is not supported by ONOS
5064
5065 Optional: proto - The type of connection e.g. tcp, ssl. If a list of ips are given
5066 port - The port number.
5067 jsonFormat - If set ONOS will output in json NOTE: This is currently not supported
5068
5069 Returns: main.TRUE if ONOS returns without any errors, otherwise returns main.FALSE
5070 """
5071 try:
5072 cmd = "device-setcontrollers"
5073
5074 if jsonFormat:
5075 cmd += " -j"
5076 cmd += " " + uri
5077 if isinstance( ip, str ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005078 ip = [ ip ]
GlennRC050596c2015-11-18 17:06:41 -08005079 for item in ip:
5080 if ":" in item:
5081 sitem = item.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005082 if len( sitem ) == 3:
GlennRC050596c2015-11-18 17:06:41 -08005083 cmd += " " + item
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005084 elif "." in sitem[ 1 ]:
5085 cmd += " {}:{}".format( item, port )
GlennRC050596c2015-11-18 17:06:41 -08005086 else:
5087 main.log.error( "Malformed entry: " + item )
5088 raise TypeError
5089 else:
5090 cmd += " {}:{}:{}".format( proto, item, port )
GlennRC050596c2015-11-18 17:06:41 -08005091 response = self.sendline( cmd )
Jon Halla495f562016-05-16 18:03:26 -07005092 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005093 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005094 if "Error" in response:
5095 main.log.error( response )
5096 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005097 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005098 except AssertionError:
5099 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005100 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005101 except TypeError:
5102 main.log.exception( self.name + ": Object not as expected" )
5103 return main.FALSE
5104 except pexpect.EOF:
5105 main.log.error( self.name + ": EOF exception found" )
5106 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005107 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005108 except Exception:
5109 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005110 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005111
5112 def removeDevice( self, device ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005113 '''
GlennRC20fc6522015-12-23 23:26:57 -08005114 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005115 Remove a device from ONOS by passing the uri of the device(s).
GlennRC20fc6522015-12-23 23:26:57 -08005116 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005117 device - (str or list) the id or uri of the device ex. "of:0000000000000001"
GlennRC20fc6522015-12-23 23:26:57 -08005118 Returns:
5119 Returns main.FALSE if an exception is thrown or an error is present
5120 in the response. Otherwise, returns main.TRUE.
5121 NOTE:
5122 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005123 '''
GlennRC20fc6522015-12-23 23:26:57 -08005124 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005125 if isinstance( device, str ):
You Wang823f5022016-08-18 15:24:41 -07005126 deviceStr = device
5127 device = []
5128 device.append( deviceStr )
GlennRC20fc6522015-12-23 23:26:57 -08005129
5130 for d in device:
5131 time.sleep( 1 )
5132 response = self.sendline( "device-remove {}".format( d ) )
Jon Halla495f562016-05-16 18:03:26 -07005133 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005134 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005135 if "Error" in response:
5136 main.log.warn( "Error for device: {}\nResponse: {}".format( d, response ) )
5137 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005138 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005139 except AssertionError:
5140 main.log.exception( "" )
5141 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005142 except TypeError:
5143 main.log.exception( self.name + ": Object not as expected" )
5144 return main.FALSE
5145 except pexpect.EOF:
5146 main.log.error( self.name + ": EOF exception found" )
5147 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005148 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005149 except Exception:
5150 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005151 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005152
5153 def removeHost( self, host ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005154 '''
GlennRC20fc6522015-12-23 23:26:57 -08005155 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005156 Remove a host from ONOS by passing the id of the host(s)
GlennRC20fc6522015-12-23 23:26:57 -08005157 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005158 hostId - (str or list) the id or mac of the host ex. "00:00:00:00:00:01"
GlennRC20fc6522015-12-23 23:26:57 -08005159 Returns:
5160 Returns main.FALSE if an exception is thrown or an error is present
5161 in the response. Otherwise, returns main.TRUE.
5162 NOTE:
5163 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005164 '''
GlennRC20fc6522015-12-23 23:26:57 -08005165 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005166 if isinstance( host, str ):
GlennRC20fc6522015-12-23 23:26:57 -08005167 host = list( host )
5168
5169 for h in host:
5170 time.sleep( 1 )
5171 response = self.sendline( "host-remove {}".format( h ) )
Jon Halla495f562016-05-16 18:03:26 -07005172 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005173 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005174 if "Error" in response:
5175 main.log.warn( "Error for host: {}\nResponse: {}".format( h, response ) )
5176 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005177 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005178 except AssertionError:
5179 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005180 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005181 except TypeError:
5182 main.log.exception( self.name + ": Object not as expected" )
5183 return main.FALSE
5184 except pexpect.EOF:
5185 main.log.error( self.name + ": EOF exception found" )
5186 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005187 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005188 except Exception:
5189 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005190 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005191
YPZhangfebf7302016-05-24 16:45:56 -07005192 def link( self, begin, end, state, timeout=30, showResponse=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005193 '''
GlennRCed771242016-01-13 17:02:47 -08005194 Description:
5195 Bring link down or up in the null-provider.
5196 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005197 begin - (string) One end of a device or switch.
5198 end - (string) the other end of the device or switch
GlennRCed771242016-01-13 17:02:47 -08005199 returns:
5200 main.TRUE if no exceptions were thrown and no Errors are
5201 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005202 '''
GlennRCed771242016-01-13 17:02:47 -08005203 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005204 cmd = "null-link null:{} null:{} {}".format( begin, end, state )
YPZhangfebf7302016-05-24 16:45:56 -07005205 response = self.sendline( cmd, showResponse=showResponse, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07005206 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005207 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08005208 if "Error" in response or "Failure" in response:
5209 main.log.error( response )
5210 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005211 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005212 except AssertionError:
5213 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005214 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005215 except TypeError:
5216 main.log.exception( self.name + ": Object not as expected" )
5217 return main.FALSE
5218 except pexpect.EOF:
5219 main.log.error( self.name + ": EOF exception found" )
5220 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005221 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005222 except Exception:
5223 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005224 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005225
Jon Hall2c8959e2016-12-16 12:17:34 -08005226 def portstate( self, dpid, port, state ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005227 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005228 Description:
5229 Changes the state of port in an OF switch by means of the
5230 PORTSTATUS OF messages.
5231 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005232 dpid - (string) Datapath ID of the device. Ex: 'of:0000000000000102'
5233 port - (string) target port in the device. Ex: '2'
5234 state - (string) target state (enable or disable)
Flavio Castro82ee2f62016-06-07 15:04:12 -07005235 returns:
5236 main.TRUE if no exceptions were thrown and no Errors are
5237 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005238 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005239 try:
Jon Hall2c8959e2016-12-16 12:17:34 -08005240 state = state.lower()
5241 assert state == 'enable' or state == 'disable', "Unknown state"
Jon Halle0f0b342017-04-18 11:43:47 -07005242 cmd = "portstate {} {} {}".format( dpid, port, state )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005243 response = self.sendline( cmd, showResponse=True )
5244 assert response is not None, "Error in sendline"
5245 assert "Command not found:" not in response, response
5246 if "Error" in response or "Failure" in response:
5247 main.log.error( response )
5248 return main.FALSE
5249 return main.TRUE
5250 except AssertionError:
5251 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005252 return main.FALSE
Flavio Castro82ee2f62016-06-07 15:04:12 -07005253 except TypeError:
5254 main.log.exception( self.name + ": Object not as expected" )
5255 return main.FALSE
5256 except pexpect.EOF:
5257 main.log.error( self.name + ": EOF exception found" )
5258 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005259 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005260 except Exception:
5261 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005262 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005263
5264 def logSet( self, level="INFO", app="org.onosproject" ):
5265 """
5266 Set the logging level to lvl for a specific app
5267 returns main.TRUE on success
5268 returns main.FALSE if Error occurred
5269 if noExit is True, TestON will not exit, but clean up
5270 Available level: DEBUG, TRACE, INFO, WARN, ERROR
5271 Level defaults to INFO
5272 """
5273 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005274 self.handle.sendline( "log:set %s %s" % ( level, app ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -08005275 self.handle.expect( self.karafPrompt )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005276
5277 response = self.handle.before
5278 if re.search( "Error", response ):
5279 return main.FALSE
5280 return main.TRUE
5281 except pexpect.TIMEOUT:
5282 main.log.exception( self.name + ": TIMEOUT exception found" )
Devin Lim44075962017-08-11 10:56:37 -07005283 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005284 except pexpect.EOF:
5285 main.log.error( self.name + ": EOF exception found" )
5286 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005287 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005288 except Exception:
5289 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005290 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07005291
5292 def getGraphDict( self, timeout=60, includeHost=False ):
5293 """
5294 Return a dictionary which describes the latest network topology data as a
5295 graph.
5296 An example of the dictionary:
5297 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
5298 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
5299 Each vertex should at least have an 'edges' attribute which describes the
5300 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005301 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07005302 list of attributes.
5303 An example of the edges dictionary:
5304 'edges': { vertex2: { 'port': ..., 'weight': ... },
5305 vertex3: { 'port': ..., 'weight': ... } }
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005306 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07005307 in topology data.
5308 """
5309 graphDict = {}
5310 try:
5311 links = self.links()
5312 links = json.loads( links )
5313 devices = self.devices()
5314 devices = json.loads( devices )
5315 idToDevice = {}
5316 for device in devices:
5317 idToDevice[ device[ 'id' ] ] = device
5318 if includeHost:
5319 hosts = self.hosts()
5320 # FIXME: support 'includeHost' argument
5321 for link in links:
5322 nodeA = link[ 'src' ][ 'device' ]
5323 nodeB = link[ 'dst' ][ 'device' ]
5324 assert idToDevice[ nodeA ][ 'available' ] and idToDevice[ nodeB ][ 'available' ]
Jon Halle0f0b342017-04-18 11:43:47 -07005325 if nodeA not in graphDict.keys():
5326 graphDict[ nodeA ] = { 'edges': {},
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005327 'dpid': idToDevice[ nodeA ][ 'id' ][ 3: ],
Jon Halle0f0b342017-04-18 11:43:47 -07005328 'type': idToDevice[ nodeA ][ 'type' ],
5329 'available': idToDevice[ nodeA ][ 'available' ],
5330 'role': idToDevice[ nodeA ][ 'role' ],
5331 'mfr': idToDevice[ nodeA ][ 'mfr' ],
5332 'hw': idToDevice[ nodeA ][ 'hw' ],
5333 'sw': idToDevice[ nodeA ][ 'sw' ],
5334 'serial': idToDevice[ nodeA ][ 'serial' ],
5335 'chassisId': idToDevice[ nodeA ][ 'chassisId' ],
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005336 'annotations': idToDevice[ nodeA ][ 'annotations' ]}
You Wangdb8cd0a2016-05-26 15:19:45 -07005337 else:
5338 # Assert nodeB is not connected to any current links of nodeA
You Wang7d14d642019-01-23 15:10:08 -08005339 # assert nodeB not in graphDict[ nodeA ][ 'edges' ].keys()
5340 pass
Jon Halle0f0b342017-04-18 11:43:47 -07005341 graphDict[ nodeA ][ 'edges' ][ nodeB ] = { 'port': link[ 'src' ][ 'port' ],
5342 'type': link[ 'type' ],
5343 'state': link[ 'state' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07005344 return graphDict
5345 except ( TypeError, ValueError ):
5346 main.log.exception( self.name + ": Object not as expected" )
5347 return None
5348 except KeyError:
5349 main.log.exception( self.name + ": KeyError exception found" )
5350 return None
5351 except AssertionError:
5352 main.log.exception( self.name + ": AssertionError exception found" )
5353 return None
5354 except pexpect.EOF:
5355 main.log.error( self.name + ": EOF exception found" )
5356 main.log.error( self.name + ": " + self.handle.before )
5357 return None
5358 except Exception:
5359 main.log.exception( self.name + ": Uncaught exception!" )
5360 return None
YPZhangcbc2a062016-07-11 10:55:44 -07005361
5362 def getIntentPerfSummary( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005363 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005364 Send command to check intent-perf summary
5365 Returns: dictionary for intent-perf summary
5366 if something wrong, function will return None
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005367 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005368 cmd = "intent-perf -s"
5369 respDic = {}
5370 resp = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08005371 assert resp is not None, "Error in sendline"
5372 assert "Command not found:" not in resp, resp
YPZhangcbc2a062016-07-11 10:55:44 -07005373 try:
5374 # Generate the dictionary to return
5375 for l in resp.split( "\n" ):
5376 # Delete any white space in line
5377 temp = re.sub( r'\s+', '', l )
5378 temp = temp.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005379 respDic[ temp[ 0 ] ] = temp[ 1 ]
YPZhangcbc2a062016-07-11 10:55:44 -07005380
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005381 except ( TypeError, ValueError ):
YPZhangcbc2a062016-07-11 10:55:44 -07005382 main.log.exception( self.name + ": Object not as expected" )
5383 return None
5384 except KeyError:
5385 main.log.exception( self.name + ": KeyError exception found" )
5386 return None
5387 except AssertionError:
5388 main.log.exception( self.name + ": AssertionError exception found" )
5389 return None
5390 except pexpect.EOF:
5391 main.log.error( self.name + ": EOF exception found" )
5392 main.log.error( self.name + ": " + self.handle.before )
5393 return None
5394 except Exception:
5395 main.log.exception( self.name + ": Uncaught exception!" )
5396 return None
5397 return respDic
5398
Chiyu Chengec63bde2016-11-17 18:11:36 -08005399 def logSearch( self, mode='all', searchTerm='', startLine='', logNum=1 ):
chengchiyu08303a02016-09-08 17:40:26 -07005400 """
5401 Searches the latest ONOS log file for the given search term and
5402 return a list that contains all the lines that have the search term.
YPZhangcbc2a062016-07-11 10:55:44 -07005403
chengchiyu08303a02016-09-08 17:40:26 -07005404 Arguments:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005405 searchTerm:
5406 The string to grep from the ONOS log.
5407 startLine:
5408 The term that decides which line is the start to search the searchTerm in
5409 the karaf log. For now, startTerm only works in 'first' mode.
5410 logNum:
5411 In some extreme cases, one karaf log is not big enough to contain all the
5412 information.Because of this, search mutiply logs is necessary to capture
5413 the right result. logNum is the number of karaf logs that we need to search
5414 the searchTerm.
chengchiyu08303a02016-09-08 17:40:26 -07005415 mode:
5416 all: return all the strings that contain the search term
5417 last: return the last string that contains the search term
5418 first: return the first string that contains the search term
Chiyu Chengec63bde2016-11-17 18:11:36 -08005419 num: return the number of times that the searchTerm appears in the log
5420 total: return how many lines in karaf log
chengchiyu08303a02016-09-08 17:40:26 -07005421 """
5422 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005423 assert isinstance( searchTerm, str )
Jon Halle0f0b342017-04-18 11:43:47 -07005424 # Build the log paths string
Chiyu Chengec63bde2016-11-17 18:11:36 -08005425 logPath = '/opt/onos/log/karaf.log.'
5426 logPaths = '/opt/onos/log/karaf.log'
5427 for i in range( 1, logNum ):
5428 logPaths = logPath + str( i ) + " " + logPaths
5429 cmd = "cat " + logPaths
You Wang6d301d42017-04-21 10:49:33 -07005430 if startLine:
Jon Halla478b852017-12-04 15:00:15 -08005431 # 100000000 is just a extreme large number to make sure this function can
5432 # grep all the lines after startLine
You Wang6d301d42017-04-21 10:49:33 -07005433 cmd = cmd + " | grep -A 100000000 \'" + startLine + "\'"
Chiyu Chengec63bde2016-11-17 18:11:36 -08005434 if mode == 'all':
5435 cmd = cmd + " | grep \'" + searchTerm + "\'"
You Wang6d301d42017-04-21 10:49:33 -07005436 elif mode == 'last':
Chiyu Chengec63bde2016-11-17 18:11:36 -08005437 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | tail -n 1"
You Wang6d301d42017-04-21 10:49:33 -07005438 elif mode == 'first':
5439 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | head -n 1"
5440 elif mode == 'num':
You Wangd91a70f2019-01-03 15:28:10 -08005441 cmd = cmd + " | grep \'" + searchTerm + "\' | wc -l"
5442 num = self.lineCount( cmd )
Chiyu Chengb8c2c842016-10-05 12:40:49 -07005443 return num
You Wang6d301d42017-04-21 10:49:33 -07005444 elif mode == 'total':
Jon Halld5a94fb2018-11-13 14:32:23 -08005445 totalLines = self.lineCount( "cat /opt/onos/log/karaf.log | wc -l" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005446 return int( totalLines )
You Wang6d301d42017-04-21 10:49:33 -07005447 else:
5448 main.log.error( self.name + " unsupported mode" )
5449 return main.ERROR
chengchiyu08303a02016-09-08 17:40:26 -07005450 before = self.sendline( cmd )
5451 before = before.splitlines()
5452 # make sure the returned list only contains the search term
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005453 returnLines = [ line for line in before if searchTerm in line ]
chengchiyu08303a02016-09-08 17:40:26 -07005454 return returnLines
5455 except AssertionError:
5456 main.log.error( self.name + " searchTerm is not string type" )
5457 return None
5458 except pexpect.EOF:
5459 main.log.error( self.name + ": EOF exception found" )
5460 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005461 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005462 except pexpect.TIMEOUT:
5463 main.log.error( self.name + ": TIMEOUT exception found" )
5464 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005465 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005466 except Exception:
5467 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005468 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005469
5470 def vplsShow( self, jsonFormat=True ):
5471 """
5472 Description: Returns result of onos:vpls show, which should list the
5473 configured VPLS networks and the assigned interfaces.
5474 Optional:
5475 * jsonFormat: enable json formatting of output
5476 Returns:
5477 The output of the command or None on error.
5478 """
5479 try:
5480 cmdStr = "vpls show"
5481 if jsonFormat:
5482 raise NotImplementedError
5483 cmdStr += " -j"
5484 handle = self.sendline( cmdStr )
5485 assert handle is not None, "Error in sendline"
5486 assert "Command not found:" not in handle, handle
5487 return handle
5488 except AssertionError:
5489 main.log.exception( "" )
5490 return None
5491 except TypeError:
5492 main.log.exception( self.name + ": Object not as expected" )
5493 return None
5494 except pexpect.EOF:
5495 main.log.error( self.name + ": EOF exception found" )
5496 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005497 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005498 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005499 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005500 return None
5501 except Exception:
5502 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005503 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005504
5505 def parseVplsShow( self ):
5506 """
5507 Parse the cli output of 'vpls show' into json output. This is required
5508 as there is currently no json output available.
5509 """
5510 try:
5511 output = []
5512 raw = self.vplsShow( jsonFormat=False )
5513 namePat = "VPLS name: (?P<name>\w+)"
5514 interfacesPat = "Associated interfaces: \[(?P<interfaces>.*)\]"
5515 encapPat = "Encapsulation: (?P<encap>\w+)"
5516 pattern = "\s+".join( [ namePat, interfacesPat, encapPat ] )
5517 mIter = re.finditer( pattern, raw )
5518 for match in mIter:
5519 item = {}
5520 item[ 'name' ] = match.group( 'name' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005521 ifaces = match.group( 'interfaces' ).split( ', ' )
Jon Hall2c8959e2016-12-16 12:17:34 -08005522 if ifaces == [ "" ]:
5523 ifaces = []
5524 item[ 'interfaces' ] = ifaces
5525 encap = match.group( 'encap' )
5526 if encap != 'NONE':
5527 item[ 'encapsulation' ] = encap.lower()
5528 output.append( item )
5529 return output
5530 except Exception:
5531 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005532 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005533
5534 def vplsList( self, jsonFormat=True ):
5535 """
5536 Description: Returns result of onos:vpls list, which should list the
5537 configured VPLS networks.
5538 Optional:
5539 * jsonFormat: enable json formatting of output
5540 """
5541 try:
5542 cmdStr = "vpls list"
5543 if jsonFormat:
5544 raise NotImplementedError
5545 cmdStr += " -j"
5546 handle = self.sendline( cmdStr )
5547 assert handle is not None, "Error in sendline"
5548 assert "Command not found:" not in handle, handle
5549 return handle
5550 except AssertionError:
5551 main.log.exception( "" )
5552 return None
5553 except TypeError:
5554 main.log.exception( self.name + ": Object not as expected" )
5555 return None
5556 except pexpect.EOF:
5557 main.log.error( self.name + ": EOF exception found" )
5558 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005559 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005560 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005561 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005562 return None
5563 except Exception:
5564 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005565 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005566
5567 def vplsCreate( self, network ):
5568 """
5569 CLI command to create a new VPLS network.
5570 Required arguments:
5571 network - String name of the network to create.
5572 returns:
5573 main.TRUE on success and main.FALSE on failure
5574 """
5575 try:
5576 network = str( network )
5577 cmdStr = "vpls create "
5578 cmdStr += network
5579 output = self.sendline( cmdStr )
5580 assert output is not None, "Error in sendline"
5581 assert "Command not found:" not in output, output
5582 assert "Error executing command" not in output, output
5583 assert "VPLS already exists:" not in output, output
5584 return main.TRUE
5585 except AssertionError:
5586 main.log.exception( "" )
5587 return main.FALSE
5588 except TypeError:
5589 main.log.exception( self.name + ": Object not as expected" )
5590 return main.FALSE
5591 except pexpect.EOF:
5592 main.log.error( self.name + ": EOF exception found" )
5593 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005594 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005595 except Exception:
5596 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005597 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005598
5599 def vplsDelete( self, network ):
5600 """
5601 CLI command to delete a VPLS network.
5602 Required arguments:
5603 network - Name of the network to delete.
5604 returns:
5605 main.TRUE on success and main.FALSE on failure
5606 """
5607 try:
5608 network = str( network )
5609 cmdStr = "vpls delete "
5610 cmdStr += network
5611 output = self.sendline( cmdStr )
5612 assert output is not None, "Error in sendline"
5613 assert "Command not found:" not in output, output
5614 assert "Error executing command" not in output, output
5615 assert " not found" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005616 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005617 return main.TRUE
5618 except AssertionError:
5619 main.log.exception( "" )
5620 return main.FALSE
5621 except TypeError:
5622 main.log.exception( self.name + ": Object not as expected" )
5623 return main.FALSE
5624 except pexpect.EOF:
5625 main.log.error( self.name + ": EOF exception found" )
5626 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005627 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005628 except Exception:
5629 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005630 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005631
5632 def vplsAddIface( self, network, iface ):
5633 """
5634 CLI command to add an interface to a VPLS network.
5635 Required arguments:
5636 network - Name of the network to add the interface to.
5637 iface - The ONOS name for an interface.
5638 returns:
5639 main.TRUE on success and main.FALSE on failure
5640 """
5641 try:
5642 network = str( network )
5643 iface = str( iface )
5644 cmdStr = "vpls add-if "
5645 cmdStr += network + " " + iface
5646 output = self.sendline( cmdStr )
5647 assert output is not None, "Error in sendline"
5648 assert "Command not found:" not in output, output
5649 assert "Error executing command" not in output, output
5650 assert "already associated to network" not in output, output
5651 assert "Interface cannot be added." not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005652 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005653 return main.TRUE
5654 except AssertionError:
5655 main.log.exception( "" )
5656 return main.FALSE
5657 except TypeError:
5658 main.log.exception( self.name + ": Object not as expected" )
5659 return main.FALSE
5660 except pexpect.EOF:
5661 main.log.error( self.name + ": EOF exception found" )
5662 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005663 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005664 except Exception:
5665 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005666 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005667
5668 def vplsRemIface( self, network, iface ):
5669 """
5670 CLI command to remove an interface from a VPLS network.
5671 Required arguments:
5672 network - Name of the network to remove the interface from.
5673 iface - Name of the interface to remove.
5674 returns:
5675 main.TRUE on success and main.FALSE on failure
5676 """
5677 try:
5678 iface = str( iface )
5679 cmdStr = "vpls rem-if "
5680 cmdStr += network + " " + iface
5681 output = self.sendline( cmdStr )
5682 assert output is not None, "Error in sendline"
5683 assert "Command not found:" not in output, output
5684 assert "Error executing command" not in output, output
5685 assert "is not configured" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005686 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005687 return main.TRUE
5688 except AssertionError:
5689 main.log.exception( "" )
5690 return main.FALSE
5691 except TypeError:
5692 main.log.exception( self.name + ": Object not as expected" )
5693 return main.FALSE
5694 except pexpect.EOF:
5695 main.log.error( self.name + ": EOF exception found" )
5696 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005697 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005698 except Exception:
5699 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005700 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005701
5702 def vplsClean( self ):
5703 """
5704 Description: Clears the VPLS app configuration.
5705 Returns: main.TRUE on success and main.FALSE on failure
5706 """
5707 try:
5708 cmdStr = "vpls clean"
5709 handle = self.sendline( cmdStr )
5710 assert handle is not None, "Error in sendline"
5711 assert "Command not found:" not in handle, handle
Jon Hallcf97cf12017-06-06 09:37:51 -07005712 assert "still updating" not in handle, handle
Jon Hall2c8959e2016-12-16 12:17:34 -08005713 return handle
5714 except AssertionError:
5715 main.log.exception( "" )
5716 return main.FALSE
5717 except TypeError:
5718 main.log.exception( self.name + ": Object not as expected" )
5719 return main.FALSE
5720 except pexpect.EOF:
5721 main.log.error( self.name + ": EOF exception found" )
5722 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005723 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005724 except Exception:
5725 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005726 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005727
5728 def vplsSetEncap( self, network, encapType ):
5729 """
5730 CLI command to add an interface to a VPLS network.
5731 Required arguments:
5732 network - Name of the network to create.
5733 encapType - Type of encapsulation.
5734 returns:
5735 main.TRUE on success and main.FALSE on failure
5736 """
5737 try:
5738 network = str( network )
5739 encapType = str( encapType ).upper()
5740 assert encapType in [ "MPLS", "VLAN", "NONE" ], "Incorrect type"
5741 cmdStr = "vpls set-encap "
5742 cmdStr += network + " " + encapType
5743 output = self.sendline( cmdStr )
5744 assert output is not None, "Error in sendline"
5745 assert "Command not found:" not in output, output
5746 assert "Error executing command" not in output, output
5747 assert "already associated to network" not in output, output
5748 assert "Encapsulation type " not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005749 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005750 return main.TRUE
5751 except AssertionError:
5752 main.log.exception( "" )
5753 return main.FALSE
5754 except TypeError:
5755 main.log.exception( self.name + ": Object not as expected" )
5756 return main.FALSE
5757 except pexpect.EOF:
5758 main.log.error( self.name + ": EOF exception found" )
5759 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005760 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005761 except Exception:
5762 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005763 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005764
5765 def interfaces( self, jsonFormat=True ):
5766 """
5767 Description: Returns result of interfaces command.
5768 Optional:
5769 * jsonFormat: enable json formatting of output
5770 Returns:
5771 The output of the command or None on error.
5772 """
5773 try:
5774 cmdStr = "interfaces"
5775 if jsonFormat:
Jon Halle0f0b342017-04-18 11:43:47 -07005776 raise NotImplementedError
Jon Hall2c8959e2016-12-16 12:17:34 -08005777 cmdStr += " -j"
5778 handle = self.sendline( cmdStr )
5779 assert handle is not None, "Error in sendline"
5780 assert "Command not found:" not in handle, handle
5781 return handle
5782 except AssertionError:
5783 main.log.exception( "" )
5784 return None
5785 except TypeError:
5786 main.log.exception( self.name + ": Object not as expected" )
5787 return None
5788 except pexpect.EOF:
5789 main.log.error( self.name + ": EOF exception found" )
5790 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005791 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005792 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005793 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005794 return None
5795 except Exception:
5796 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005797 main.cleanAndExit()
Chiyu Chengec63bde2016-11-17 18:11:36 -08005798
5799 def getTimeStampFromLog( self, mode, searchTerm, splitTerm_before, splitTerm_after, startLine='', logNum=1 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005800 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005801 Get the timestamp of searchTerm from karaf log.
5802
5803 Arguments:
5804 splitTerm_before and splitTerm_after:
5805
5806 The terms that split the string that contains the timeStamp of
5807 searchTerm. For example, if that string is "xxxxxxxcreationTime =
5808 1419510501xxxxxx", then the splitTerm_before is "CreationTime = "
5809 and the splitTerm_after is "x"
5810
5811 others:
Jon Halle0f0b342017-04-18 11:43:47 -07005812 Please look at the "logsearch" Function in onosclidriver.py
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005813 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005814 if logNum < 0:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005815 main.log.error( "Get wrong log number ")
Chiyu Chengec63bde2016-11-17 18:11:36 -08005816 return main.ERROR
5817 lines = self.logSearch( mode=mode, searchTerm=searchTerm, startLine=startLine, logNum=logNum )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005818 if len( lines ) == 0:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005819 main.log.warn( "Captured timestamp string is empty" )
5820 return main.ERROR
5821 lines = lines[ 0 ]
5822 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005823 assert isinstance( lines, str )
Chiyu Chengec63bde2016-11-17 18:11:36 -08005824 # get the target value
5825 line = lines.split( splitTerm_before )
5826 key = line[ 1 ].split( splitTerm_after )
5827 return int( key[ 0 ] )
5828 except IndexError:
5829 main.log.warn( "Index Error!" )
5830 return main.ERROR
5831 except AssertionError:
5832 main.log.warn( "Search Term Not Found " )
5833 return main.ERROR
Jon Halle0f0b342017-04-18 11:43:47 -07005834
5835 def workQueueAdd( self, queueName, value ):
5836 """
5837 CLI command to add a string to the specified Work Queue.
5838 This function uses the distributed primitives test app, which
5839 gives some cli access to distributed primitives for testing
5840 purposes only.
5841
5842 Required arguments:
5843 queueName - The name of the queue to add to
5844 value - The value to add to the queue
5845 returns:
5846 main.TRUE on success, main.FALSE on failure and
5847 main.ERROR on error.
5848 """
5849 try:
5850 queueName = str( queueName )
5851 value = str( value )
5852 prefix = "work-queue-test"
5853 operation = "add"
5854 cmdStr = " ".join( [ prefix, queueName, operation, value ] )
5855 output = self.distPrimitivesSend( cmdStr )
5856 if "Invalid operation name" in output:
5857 main.log.warn( output )
5858 return main.ERROR
5859 elif "Done" in output:
5860 return main.TRUE
5861 except TypeError:
5862 main.log.exception( self.name + ": Object not as expected" )
5863 return main.ERROR
5864 except Exception:
5865 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005866 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005867
5868 def workQueueAddMultiple( self, queueName, value1, value2 ):
5869 """
5870 CLI command to add two strings to the specified Work Queue.
5871 This function uses the distributed primitives test app, which
5872 gives some cli access to distributed primitives for testing
5873 purposes only.
5874
5875 Required arguments:
5876 queueName - The name of the queue to add to
5877 value1 - The first value to add to the queue
5878 value2 - The second value to add to the queue
5879 returns:
5880 main.TRUE on success, main.FALSE on failure and
5881 main.ERROR on error.
5882 """
5883 try:
5884 queueName = str( queueName )
5885 value1 = str( value1 )
5886 value2 = str( value2 )
5887 prefix = "work-queue-test"
5888 operation = "addMultiple"
5889 cmdStr = " ".join( [ prefix, queueName, operation, value1, value2 ] )
5890 output = self.distPrimitivesSend( cmdStr )
5891 if "Invalid operation name" in output:
5892 main.log.warn( output )
5893 return main.ERROR
5894 elif "Done" in output:
5895 return main.TRUE
5896 except TypeError:
5897 main.log.exception( self.name + ": Object not as expected" )
5898 return main.ERROR
5899 except Exception:
5900 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005901 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005902
5903 def workQueueTakeAndComplete( self, queueName, number=1 ):
5904 """
5905 CLI command to take a value from the specified Work Queue and compelte it.
5906 This function uses the distributed primitives test app, which
5907 gives some cli access to distributed primitives for testing
5908 purposes only.
5909
5910 Required arguments:
5911 queueName - The name of the queue to add to
5912 number - The number of items to take and complete
5913 returns:
5914 main.TRUE on success, main.FALSE on failure and
5915 main.ERROR on error.
5916 """
5917 try:
5918 queueName = str( queueName )
5919 number = str( int( number ) )
5920 prefix = "work-queue-test"
5921 operation = "takeAndComplete"
5922 cmdStr = " ".join( [ prefix, queueName, operation, number ] )
5923 output = self.distPrimitivesSend( cmdStr )
5924 if "Invalid operation name" in output:
5925 main.log.warn( output )
5926 return main.ERROR
5927 elif "Done" in output:
5928 return main.TRUE
5929 except TypeError:
5930 main.log.exception( self.name + ": Object not as expected" )
5931 return main.ERROR
5932 except Exception:
5933 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005934 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005935
5936 def workQueueDestroy( self, queueName ):
5937 """
5938 CLI command to destroy the specified Work Queue.
5939 This function uses the distributed primitives test app, which
5940 gives some cli access to distributed primitives for testing
5941 purposes only.
5942
5943 Required arguments:
5944 queueName - The name of the queue to add to
5945 returns:
5946 main.TRUE on success, main.FALSE on failure and
5947 main.ERROR on error.
5948 """
5949 try:
5950 queueName = str( queueName )
5951 prefix = "work-queue-test"
5952 operation = "destroy"
5953 cmdStr = " ".join( [ prefix, queueName, operation ] )
5954 output = self.distPrimitivesSend( cmdStr )
5955 if "Invalid operation name" in output:
5956 main.log.warn( output )
5957 return main.ERROR
5958 return main.TRUE
5959 except TypeError:
5960 main.log.exception( self.name + ": Object not as expected" )
5961 return main.ERROR
5962 except Exception:
5963 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005964 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005965
5966 def workQueueTotalPending( self, queueName ):
5967 """
5968 CLI command to get the Total Pending items of the specified Work Queue.
5969 This function uses the distributed primitives test app, which
5970 gives some cli access to distributed primitives for testing
5971 purposes only.
5972
5973 Required arguments:
5974 queueName - The name of the queue to add to
5975 returns:
5976 The number of Pending items in the specified work queue or
5977 None on error
5978 """
5979 try:
5980 queueName = str( queueName )
5981 prefix = "work-queue-test"
5982 operation = "totalPending"
5983 cmdStr = " ".join( [ prefix, queueName, operation ] )
5984 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08005985 main.log.debug( self.name + ": work queue unparsed: " + output )
5986 output = output.split( "\r\n" )[ -1 ]
5987 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07005988 pattern = r'\d+'
5989 if "Invalid operation name" in output:
5990 main.log.warn( output )
5991 return None
5992 else:
5993 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005994 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07005995 except ( AttributeError, TypeError ):
5996 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
5997 return None
5998 except Exception:
5999 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006000 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006001
6002 def workQueueTotalCompleted( self, queueName ):
6003 """
6004 CLI command to get the Total Completed items of the specified Work Queue.
6005 This function uses the distributed primitives test app, which
6006 gives some cli access to distributed primitives for testing
6007 purposes only.
6008
6009 Required arguments:
6010 queueName - The name of the queue to add to
6011 returns:
6012 The number of complete items in the specified work queue or
6013 None on error
6014 """
6015 try:
6016 queueName = str( queueName )
6017 prefix = "work-queue-test"
6018 operation = "totalCompleted"
6019 cmdStr = " ".join( [ prefix, queueName, operation ] )
6020 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006021 main.log.debug( self.name + ": work queue unparsed: " + output )
6022 output = output.split( "\r\n" )[ -1 ]
6023 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006024 pattern = r'\d+'
6025 if "Invalid operation name" in output:
6026 main.log.warn( output )
6027 return None
6028 else:
6029 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006030 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006031 except ( AttributeError, TypeError ):
6032 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6033 return None
6034 except Exception:
6035 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006036 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006037
6038 def workQueueTotalInProgress( self, queueName ):
6039 """
6040 CLI command to get the Total In Progress items of the specified Work Queue.
6041 This function uses the distributed primitives test app, which
6042 gives some cli access to distributed primitives for testing
6043 purposes only.
6044
6045 Required arguments:
6046 queueName - The name of the queue to add to
6047 returns:
6048 The number of In Progress items in the specified work queue or
6049 None on error
6050 """
6051 try:
6052 queueName = str( queueName )
6053 prefix = "work-queue-test"
6054 operation = "totalInProgress"
6055 cmdStr = " ".join( [ prefix, queueName, operation ] )
6056 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006057 main.log.debug( self.name + ": work queue unparsed: " + output )
6058 output = output.split( "\r\n" )[ -1 ]
6059 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006060 pattern = r'\d+'
6061 if "Invalid operation name" in output:
6062 main.log.warn( output )
6063 return None
6064 else:
6065 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006066 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006067 except ( AttributeError, TypeError ):
6068 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6069 return None
6070 except Exception:
6071 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006072 main.cleanAndExit()
Jeremy Ronquillo818bc7c2017-08-09 17:14:53 +00006073
6074 def events( self, args='-a' ):
6075 """
6076 Description: Returns events -a command output
6077 Optional:
6078 add other arguments
6079 """
6080 try:
6081 cmdStr = "events"
6082 if args:
6083 cmdStr += " " + args
6084 handle = self.sendline( cmdStr )
6085 assert handle is not None, "Error in sendline"
6086 assert "Command not found:" not in handle, handle
6087 return handle
6088 except AssertionError:
6089 main.log.exception( "" )
6090 return None
6091 except TypeError:
6092 main.log.exception( self.name + ": Object not as expected" )
6093 return None
6094 except pexpect.EOF:
6095 main.log.error( self.name + ": EOF exception found" )
6096 main.log.error( self.name + ": " + self.handle.before )
6097 main.cleanAndExit()
6098 except Exception:
6099 main.log.exception( self.name + ": Uncaught exception!" )
6100 main.cleanAndExit()
6101
6102 def getMaster( self, deviceID ):
6103 """
6104 Description: Obtains current master using "roles" command for a specific deviceID
6105 """
6106 try:
6107 return str( self.getRole( deviceID )[ 'master' ] )
6108 except AssertionError:
6109 main.log.exception( "" )
6110 return None
6111 except TypeError:
6112 main.log.exception( self.name + ": Object not as expected" )
6113 return None
6114 except pexpect.EOF:
6115 main.log.error( self.name + ": EOF exception found" )
6116 main.log.error( self.name + ": " + self.handle.before )
6117 main.cleanAndExit()
6118 except Exception:
6119 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lime6fe3c42017-10-18 16:28:40 -07006120 main.cleanAndExit()
Jon Halla478b852017-12-04 15:00:15 -08006121
6122 def issu( self ):
6123 """
6124 Short summary of In-Service Software Upgrade status
6125
6126 Returns the output of the cli command or None on Error
6127 """
6128 try:
6129 cmdStr = "issu"
6130 handle = self.sendline( cmdStr )
6131 assert handle is not None, "Error in sendline"
6132 assert "Command not found:" not in handle, handle
6133 assert "Unsupported command:" not in handle, handle
6134 return handle
6135 except AssertionError:
6136 main.log.exception( "" )
6137 return None
6138 except TypeError:
6139 main.log.exception( self.name + ": Object not as expected" )
6140 return None
6141 except pexpect.EOF:
6142 main.log.error( self.name + ": EOF exception found" )
6143 main.log.error( self.name + ": " + self.handle.before )
6144 main.cleanAndExit()
6145 except Exception:
6146 main.log.exception( self.name + ": Uncaught exception!" )
6147 main.cleanAndExit()
6148
6149 def issuInit( self ):
6150 """
6151 Initiates an In-Service Software Upgrade
6152
6153 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6154 """
6155 try:
6156 cmdStr = "issu init"
6157 handle = self.sendline( cmdStr )
6158 assert handle is not None, "Error in sendline"
6159 assert "Command not found:" not in handle, handle
6160 assert "Unsupported command:" not in handle, handle
6161 if "Initialized" in handle:
6162 return main.TRUE
6163 else:
6164 return main.FALSE
6165 except AssertionError:
6166 main.log.exception( "" )
6167 return main.ERROR
6168 except TypeError:
6169 main.log.exception( self.name + ": Object not as expected" )
6170 return main.ERROR
6171 except pexpect.EOF:
6172 main.log.error( self.name + ": EOF exception found" )
6173 main.log.error( self.name + ": " + self.handle.before )
6174 main.cleanAndExit()
6175 except Exception:
6176 main.log.exception( self.name + ": Uncaught exception!" )
6177 main.cleanAndExit()
6178
6179 def issuUpgrade( self ):
6180 """
6181 Transitions stores to upgraded nodes
6182
6183 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6184 """
6185 try:
6186 cmdStr = "issu upgrade"
6187 handle = self.sendline( cmdStr )
6188 assert handle is not None, "Error in sendline"
6189 assert "Command not found:" not in handle, handle
6190 assert "Unsupported command:" not in handle, handle
6191 if "Upgraded" in handle:
6192 return main.TRUE
6193 else:
6194 return main.FALSE
6195 except AssertionError:
6196 main.log.exception( "" )
6197 return main.ERROR
6198 except TypeError:
6199 main.log.exception( self.name + ": Object not as expected" )
6200 return main.ERROR
6201 except pexpect.EOF:
6202 main.log.error( self.name + ": EOF exception found" )
6203 main.log.error( self.name + ": " + self.handle.before )
6204 main.cleanAndExit()
6205 except Exception:
6206 main.log.exception( self.name + ": Uncaught exception!" )
6207 main.cleanAndExit()
6208
6209 def issuCommit( self ):
6210 """
6211 Finalizes an In-Service Software Upgrade
6212
6213 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6214 """
6215 try:
6216 cmdStr = "issu commit"
6217 handle = self.sendline( cmdStr )
6218 assert handle is not None, "Error in sendline"
6219 assert "Command not found:" not in handle, handle
6220 assert "Unsupported command:" not in handle, handle
6221 # TODO: Check the version returned by this command
6222 if "Committed version" in handle:
6223 return main.TRUE
6224 else:
6225 return main.FALSE
6226 except AssertionError:
6227 main.log.exception( "" )
6228 return main.ERROR
6229 except TypeError:
6230 main.log.exception( self.name + ": Object not as expected" )
6231 return main.ERROR
6232 except pexpect.EOF:
6233 main.log.error( self.name + ": EOF exception found" )
6234 main.log.error( self.name + ": " + self.handle.before )
6235 main.cleanAndExit()
6236 except Exception:
6237 main.log.exception( self.name + ": Uncaught exception!" )
6238 main.cleanAndExit()
6239
6240 def issuRollback( self ):
6241 """
6242 Rolls back an In-Service Software Upgrade
6243
6244 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6245 """
6246 try:
6247 cmdStr = "issu rollback"
6248 handle = self.sendline( cmdStr )
6249 assert handle is not None, "Error in sendline"
6250 assert "Command not found:" not in handle, handle
6251 assert "Unsupported command:" not in handle, handle
6252 # TODO: Check the version returned by this command
6253 if "Rolled back to version" in handle:
6254 return main.TRUE
6255 else:
6256 return main.FALSE
6257 except AssertionError:
6258 main.log.exception( "" )
6259 return main.ERROR
6260 except TypeError:
6261 main.log.exception( self.name + ": Object not as expected" )
6262 return main.ERROR
6263 except pexpect.EOF:
6264 main.log.error( self.name + ": EOF exception found" )
6265 main.log.error( self.name + ": " + self.handle.before )
6266 main.cleanAndExit()
6267 except Exception:
6268 main.log.exception( self.name + ": Uncaught exception!" )
6269 main.cleanAndExit()
6270
6271 def issuReset( self ):
6272 """
6273 Resets the In-Service Software Upgrade status after a rollback
6274
6275 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6276 """
6277 try:
6278 cmdStr = "issu reset"
6279 handle = self.sendline( cmdStr )
6280 assert handle is not None, "Error in sendline"
6281 assert "Command not found:" not in handle, handle
6282 assert "Unsupported command:" not in handle, handle
6283 # TODO: Check the version returned by this command
6284 if "Reset version" in handle:
6285 return main.TRUE
6286 else:
6287 return main.FALSE
6288 except AssertionError:
6289 main.log.exception( "" )
6290 return main.ERROR
6291 except TypeError:
6292 main.log.exception( self.name + ": Object not as expected" )
6293 return main.ERROR
6294 except pexpect.EOF:
6295 main.log.error( self.name + ": EOF exception found" )
6296 main.log.error( self.name + ": " + self.handle.before )
6297 main.cleanAndExit()
6298 except Exception:
6299 main.log.exception( self.name + ": Uncaught exception!" )
6300 main.cleanAndExit()
6301
6302 def issuStatus( self ):
6303 """
6304 Status of an In-Service Software Upgrade
6305
6306 Returns the output of the cli command or None on Error
6307 """
6308 try:
6309 cmdStr = "issu status"
6310 handle = self.sendline( cmdStr )
6311 assert handle is not None, "Error in sendline"
6312 assert "Command not found:" not in handle, handle
6313 assert "Unsupported command:" not in handle, handle
6314 return handle
6315 except AssertionError:
6316 main.log.exception( "" )
6317 return None
6318 except TypeError:
6319 main.log.exception( self.name + ": Object not as expected" )
6320 return None
6321 except pexpect.EOF:
6322 main.log.error( self.name + ": EOF exception found" )
6323 main.log.error( self.name + ": " + self.handle.before )
6324 main.cleanAndExit()
6325 except Exception:
6326 main.log.exception( self.name + ": Uncaught exception!" )
6327 main.cleanAndExit()
6328
6329 def issuVersion( self ):
6330 """
6331 Get the version of an In-Service Software Upgrade
6332
6333 Returns the output of the cli command or None on Error
6334 """
6335 try:
6336 cmdStr = "issu version"
6337 handle = self.sendline( cmdStr )
6338 assert handle is not None, "Error in sendline"
6339 assert "Command not found:" not in handle, handle
6340 assert "Unsupported command:" not in handle, handle
6341 return handle
6342 except AssertionError:
6343 main.log.exception( "" )
6344 return None
6345 except TypeError:
6346 main.log.exception( self.name + ": Object not as expected" )
6347 return None
6348 except pexpect.EOF:
6349 main.log.error( self.name + ": EOF exception found" )
6350 main.log.error( self.name + ": " + self.handle.before )
6351 main.cleanAndExit()
6352 except Exception:
6353 main.log.exception( self.name + ": Uncaught exception!" )
6354 main.cleanAndExit()
You Wange24d6272018-03-27 21:18:50 -07006355
6356 def mcastJoin( self, sIP, groupIP, sPort, dPorts ):
6357 """
6358 Create a multicast route by calling 'mcast-join' command
6359 sIP: source IP of the multicast route
6360 groupIP: group IP of the multicast route
6361 sPort: source port (e.g. of:0000000000000001/3 ) of the multicast route
6362 dPorts: a list of destination ports of the multicast route
6363 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6364 """
6365 try:
6366 cmdStr = "mcast-join"
6367 cmdStr += " " + str( sIP )
6368 cmdStr += " " + str( groupIP )
6369 cmdStr += " " + str( sPort )
6370 assert isinstance( dPorts, list )
6371 for dPort in dPorts:
6372 cmdStr += " " + str( dPort )
6373 handle = self.sendline( cmdStr )
6374 assert handle is not None, "Error in sendline"
6375 assert "Command not found:" not in handle, handle
6376 assert "Unsupported command:" not in handle, handle
6377 assert "Error executing command" not in handle, handle
6378 if "Added the mcast route" in handle:
6379 return main.TRUE
6380 else:
6381 return main.FALSE
6382 except AssertionError:
6383 main.log.exception( "" )
6384 return None
6385 except TypeError:
6386 main.log.exception( self.name + ": Object not as expected" )
6387 return None
6388 except pexpect.EOF:
6389 main.log.error( self.name + ": EOF exception found" )
6390 main.log.error( self.name + ": " + self.handle.before )
6391 main.cleanAndExit()
6392 except Exception:
6393 main.log.exception( self.name + ": Uncaught exception!" )
6394 main.cleanAndExit()
6395
6396 def mcastDelete( self, sIP, groupIP, dPorts ):
6397 """
6398 Delete a multicast route by calling 'mcast-delete' command
6399 sIP: source IP of the multicast route
6400 groupIP: group IP of the multicast route
6401 dPorts: a list of destination ports of the multicast route
6402 Returns main.TRUE if mcast route is deleted; Otherwise main.FALSE
6403 """
6404 try:
6405 cmdStr = "mcast-delete"
6406 cmdStr += " " + str( sIP )
6407 cmdStr += " " + str( groupIP )
6408 assert isinstance( dPorts, list )
6409 for dPort in dPorts:
6410 cmdStr += " " + str( dPort )
6411 handle = self.sendline( cmdStr )
6412 assert handle is not None, "Error in sendline"
6413 assert "Command not found:" not in handle, handle
6414 assert "Unsupported command:" not in handle, handle
6415 assert "Error executing command" not in handle, handle
6416 if "Updated the mcast route" in handle:
6417 return main.TRUE
6418 else:
6419 return main.FALSE
6420 except AssertionError:
6421 main.log.exception( "" )
6422 return None
6423 except TypeError:
6424 main.log.exception( self.name + ": Object not as expected" )
6425 return None
6426 except pexpect.EOF:
6427 main.log.error( self.name + ": EOF exception found" )
6428 main.log.error( self.name + ": " + self.handle.before )
6429 main.cleanAndExit()
6430 except Exception:
6431 main.log.exception( self.name + ": Uncaught exception!" )
6432 main.cleanAndExit()
6433
6434 def mcastHostJoin( self, sAddr, gAddr, srcs, sinks ):
6435 """
6436 Create a multicast route by calling 'mcast-host-join' command
6437 sAddr: we can provide * for ASM or a specific address for SSM
6438 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006439 srcs: a list of HostId of the sources e.g. ["00:AA:00:00:00:01/None"]
You Wange24d6272018-03-27 21:18:50 -07006440 sinks: a list of HostId of the sinks e.g. ["00:AA:00:00:01:05/40"]
6441 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6442 """
6443 try:
6444 cmdStr = "mcast-host-join"
6445 cmdStr += " -sAddr " + str( sAddr )
6446 cmdStr += " -gAddr " + str( gAddr )
6447 assert isinstance( srcs, list )
6448 for src in srcs:
6449 cmdStr += " -srcs " + str( src )
6450 assert isinstance( sinks, list )
6451 for sink in sinks:
6452 cmdStr += " -sinks " + str( sink )
6453 handle = self.sendline( cmdStr )
6454 assert handle is not None, "Error in sendline"
6455 assert "Command not found:" not in handle, handle
6456 assert "Unsupported command:" not in handle, handle
6457 assert "Error executing command" not in handle, handle
6458 if "Added the mcast route" in handle:
6459 return main.TRUE
6460 else:
6461 return main.FALSE
6462 except AssertionError:
6463 main.log.exception( "" )
6464 return None
6465 except TypeError:
6466 main.log.exception( self.name + ": Object not as expected" )
6467 return None
6468 except pexpect.EOF:
6469 main.log.error( self.name + ": EOF exception found" )
6470 main.log.error( self.name + ": " + self.handle.before )
6471 main.cleanAndExit()
6472 except Exception:
6473 main.log.exception( self.name + ": Uncaught exception!" )
6474 main.cleanAndExit()
6475
6476 def mcastHostDelete( self, sAddr, gAddr, host=None ):
6477 """
6478 Delete multicast sink(s) by calling 'mcast-host-delete' command
6479 sAddr: we can provide * for ASM or a specific address for SSM
6480 gAddr: specifies multicast group address
You Wangc02d8352018-04-17 16:42:10 -07006481 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
You Wange24d6272018-03-27 21:18:50 -07006482 will delete the route if not specified
6483 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6484 """
6485 try:
6486 cmdStr = "mcast-host-delete"
6487 cmdStr += " -sAddr " + str( sAddr )
6488 cmdStr += " -gAddr " + str( gAddr )
6489 if host:
6490 cmdStr += " -h " + str( host )
6491 handle = self.sendline( cmdStr )
6492 assert handle is not None, "Error in sendline"
6493 assert "Command not found:" not in handle, handle
6494 assert "Unsupported command:" not in handle, handle
6495 assert "Error executing command" not in handle, handle
6496 if "Updated the mcast route" in handle:
6497 return main.TRUE
6498 elif "Deleted the mcast route" in handle:
6499 return main.TRUE
6500 else:
6501 return main.FALSE
6502 except AssertionError:
6503 main.log.exception( "" )
6504 return None
6505 except TypeError:
6506 main.log.exception( self.name + ": Object not as expected" )
6507 return None
6508 except pexpect.EOF:
6509 main.log.error( self.name + ": EOF exception found" )
6510 main.log.error( self.name + ": " + self.handle.before )
6511 main.cleanAndExit()
6512 except Exception:
6513 main.log.exception( self.name + ": Uncaught exception!" )
6514 main.cleanAndExit()
6515
You Wang547893e2018-05-08 13:34:59 -07006516 def mcastSinkDelete( self, sAddr, gAddr, sink=None ):
6517 """
6518 Delete multicast sink(s) by calling 'mcast-sink-delete' command
6519 sAddr: we can provide * for ASM or a specific address for SSM
6520 gAddr: specifies multicast group address
6521 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
6522 will delete the route if not specified
6523 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6524 """
6525 try:
6526 cmdStr = "mcast-sink-delete"
6527 cmdStr += " -sAddr " + str( sAddr )
6528 cmdStr += " -gAddr " + str( gAddr )
6529 if sink:
6530 cmdStr += " -s " + str( sink )
6531 handle = self.sendline( cmdStr )
6532 assert handle is not None, "Error in sendline"
6533 assert "Command not found:" not in handle, handle
6534 assert "Unsupported command:" not in handle, handle
6535 assert "Error executing command" not in handle, handle
6536 if "Updated the mcast route" in handle:
6537 return main.TRUE
6538 elif "Deleted the mcast route" in handle:
6539 return main.TRUE
6540 else:
6541 return main.FALSE
6542 except AssertionError:
6543 main.log.exception( "" )
6544 return None
6545 except TypeError:
6546 main.log.exception( self.name + ": Object not as expected" )
6547 return None
6548 except pexpect.EOF:
6549 main.log.error( self.name + ": EOF exception found" )
6550 main.log.error( self.name + ": " + self.handle.before )
6551 main.cleanAndExit()
6552 except Exception:
6553 main.log.exception( self.name + ": Uncaught exception!" )
6554 main.cleanAndExit()
6555
You Wange24d6272018-03-27 21:18:50 -07006556 def mcastSourceDelete( self, sAddr, gAddr, srcs=None ):
6557 """
6558 Delete multicast src(s) by calling 'mcast-source-delete' command
6559 sAddr: we can provide * for ASM or a specific address for SSM
6560 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006561 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 -07006562 will delete the route if not specified
6563 Returns main.TRUE if mcast sink is deleted; Otherwise main.FALSE
6564 """
6565 try:
6566 cmdStr = "mcast-source-delete"
6567 cmdStr += " -sAddr " + str( sAddr )
6568 cmdStr += " -gAddr " + str( gAddr )
6569 if srcs:
6570 assert isinstance( srcs, list )
6571 for src in srcs:
6572 cmdStr += " -src " + str( src )
6573 handle = self.sendline( cmdStr )
6574 assert handle is not None, "Error in sendline"
6575 assert "Command not found:" not in handle, handle
6576 assert "Unsupported command:" not in handle, handle
6577 assert "Error executing command" not in handle, handle
6578 if "Updated the mcast route" in handle:
6579 return main.TRUE
6580 elif "Deleted the mcast route" in handle:
6581 return main.TRUE
6582 else:
6583 return main.FALSE
6584 except AssertionError:
6585 main.log.exception( "" )
6586 return None
6587 except TypeError:
6588 main.log.exception( self.name + ": Object not as expected" )
6589 return None
6590 except pexpect.EOF:
6591 main.log.error( self.name + ": EOF exception found" )
6592 main.log.error( self.name + ": " + self.handle.before )
6593 main.cleanAndExit()
6594 except Exception:
6595 main.log.exception( self.name + ": Uncaught exception!" )
6596 main.cleanAndExit()
You Wang5da39c82018-04-26 22:55:08 -07006597
6598 def netcfg( self, jsonFormat=True, args="" ):
6599 """
6600 Run netcfg cli command with given args
6601 """
6602 try:
6603 cmdStr = "netcfg"
6604 if jsonFormat:
6605 cmdStr = cmdStr + " -j"
6606 if args:
6607 cmdStr = cmdStr + " " + str( args )
6608 handle = self.sendline( cmdStr )
6609 assert handle is not None, "Error in sendline"
6610 assert "Command not found:" not in handle, handle
6611 assert "Unsupported command:" not in handle, handle
6612 assert "Error executing command" not in handle, handle
6613 return handle
6614 except AssertionError:
6615 main.log.exception( "" )
6616 return None
6617 except TypeError:
6618 main.log.exception( self.name + ": Object not as expected" )
6619 return None
6620 except pexpect.EOF:
6621 main.log.error( self.name + ": EOF exception found" )
6622 main.log.error( self.name + ": " + self.handle.before )
6623 main.cleanAndExit()
6624 except Exception:
6625 main.log.exception( self.name + ": Uncaught exception!" )
6626 main.cleanAndExit()
6627
You Wang0fa76e72018-05-18 11:33:25 -07006628 def composeT3Command( self, sAddr, dAddr, ipv6=False, verbose=True, simple=False ):
You Wang5da39c82018-04-26 22:55:08 -07006629 """
You Wang54b1d672018-06-11 16:44:13 -07006630 Compose and return a list of t3-troubleshoot cli commands for given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006631 Options:
6632 sAddr: IP address of the source host
6633 dAddr: IP address of the destination host
You Wang0fa76e72018-05-18 11:33:25 -07006634 ipv6: True if hosts are IPv6
6635 verbose: return verbose t3 output if True
6636 simple: compose command for t3-troubleshoot-simple if True
You Wang5da39c82018-04-26 22:55:08 -07006637 """
6638 try:
6639 # Collect information of both hosts from onos
6640 hosts = self.hosts()
6641 hosts = json.loads( hosts )
6642 sHost = None
6643 dHost = None
6644 for host in hosts:
6645 if sAddr in host[ "ipAddresses" ]:
6646 sHost = host
6647 elif dAddr in host[ "ipAddresses" ]:
6648 dHost = host
6649 if sHost and dHost:
6650 break
6651 assert sHost, "Not able to find host with IP {}".format( sAddr )
You Wang54b1d672018-06-11 16:44:13 -07006652 cmdList = []
You Wang5d9527b2018-05-29 17:08:54 -07006653 if simple:
6654 assert dHost, "Not able to find host with IP {}".format( dAddr )
You Wang54b1d672018-06-11 16:44:13 -07006655 cmdStr = "t3-troubleshoot-simple"
6656 if verbose:
6657 cmdStr += " -vv"
6658 if ipv6:
6659 cmdStr += " -et ipv6"
You Wang0fa76e72018-05-18 11:33:25 -07006660 cmdStr += " {}/{} {}/{}".format( sHost[ "mac" ], sHost[ "vlan" ], dHost[ "mac" ], dHost[ "vlan" ] )
You Wang54b1d672018-06-11 16:44:13 -07006661 cmdList.append( cmdStr )
You Wang0fa76e72018-05-18 11:33:25 -07006662 else:
You Wang54b1d672018-06-11 16:44:13 -07006663 for location in sHost[ "locations" ]:
6664 cmdStr = "t3-troubleshoot"
6665 if verbose:
6666 cmdStr += " -vv"
6667 if ipv6:
6668 cmdStr += " -et ipv6"
6669 cmdStr += " -s " + str( sAddr )
6670 cmdStr += " -sp " + str( location[ "elementId" ] ) + "/" + str( location[ "port" ] )
6671 cmdStr += " -sm " + str( sHost[ "mac" ] )
6672 if sHost[ "vlan" ] != "None":
6673 cmdStr += " -vid " + sHost[ "vlan" ]
6674 cmdStr += " -d " + str( dAddr )
6675 netcfg = self.netcfg( args="devices {}".format( location[ "elementId" ] ) )
6676 netcfg = json.loads( netcfg )
6677 assert netcfg, "Failed to get netcfg"
6678 cmdStr += " -dm " + str( netcfg[ "segmentrouting" ][ "routerMac" ] )
6679 cmdList.append( cmdStr )
6680 return cmdList
You Wang5da39c82018-04-26 22:55:08 -07006681 except AssertionError:
6682 main.log.exception( "" )
6683 return None
6684 except ( KeyError, TypeError ):
6685 main.log.exception( self.name + ": Object not as expected" )
6686 return None
6687 except Exception:
6688 main.log.exception( self.name + ": Uncaught exception!" )
6689 main.cleanAndExit()
6690
6691 def t3( self, sAddr, dAddr, ipv6=False ):
6692 """
You Wang54b1d672018-06-11 16:44:13 -07006693 Run t3-troubleshoot cli commands for all posible routes given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006694 Options:
6695 sAddr: IP address of the source host
6696 dAddr: IP address of the destination host
6697 """
6698 try:
You Wang54b1d672018-06-11 16:44:13 -07006699 cmdList = self.composeT3Command( sAddr, dAddr, ipv6 )
6700 assert cmdList is not None, "composeT3Command returned None"
6701 t3Output = ""
6702 for cmdStr in cmdList:
6703 handle = self.sendline( cmdStr )
6704 assert handle is not None, "Error in sendline"
6705 assert "Command not found:" not in handle, handle
6706 assert "Unsupported command:" not in handle, handle
6707 assert "Error executing command" not in handle, handle
6708 assert "Tracing packet" in handle
6709 t3Output += handle
6710 return t3Output
You Wang5da39c82018-04-26 22:55:08 -07006711 except AssertionError:
6712 main.log.exception( "" )
6713 return None
6714 except pexpect.EOF:
6715 main.log.error( self.name + ": EOF exception found" )
6716 main.log.error( self.name + ": " + self.handle.before )
6717 main.cleanAndExit()
6718 except Exception:
6719 main.log.exception( self.name + ": Uncaught exception!" )
6720 main.cleanAndExit()