blob: ef69aec025cd8b7b67e1d00c3ac4405e8f43894e [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 Hall9b0de1f2020-08-24 15:38:04 -070061 self.karafTimeout = None
62
Jon Hall3c0114c2020-08-11 15:07:42 -070063 self.dockerPrompt = None
You Wangdb8cd0a2016-05-26 15:19:45 -070064 self.graph = Graph()
Devin Limdc78e202017-06-09 18:30:07 -070065 super( OnosCliDriver, self ).__init__()
kelvin8ec71442015-01-15 16:57:00 -080066
67 def connect( self, **connectargs ):
68 """
andrewonlab95ce8322014-10-13 14:12:04 -040069 Creates ssh handle for ONOS cli.
kelvin8ec71442015-01-15 16:57:00 -080070 """
andrewonlab95ce8322014-10-13 14:12:04 -040071 try:
72 for key in connectargs:
kelvin8ec71442015-01-15 16:57:00 -080073 vars( self )[ key ] = connectargs[ key ]
Author Namee1c79982019-06-04 23:38:42 +010074 self.karafPrompt = self.user_name + "@root >"
andrew@onlab.us658ec012015-03-11 15:13:09 -070075 self.home = "~/onos"
andrewonlab95ce8322014-10-13 14:12:04 -040076 for key in self.options:
77 if key == "home":
Devin Limdc78e202017-06-09 18:30:07 -070078 self.home = self.options[ key ]
79 elif key == "karaf_username":
80 self.karafUser = self.options[ key ]
81 elif key == "karaf_password":
82 self.karafPass = self.options[ key ]
Jon Hall3c0114c2020-08-11 15:07:42 -070083 elif key == "docker_prompt":
84 self.dockerPrompt = self.options[ key ]
Jon Hall9b0de1f2020-08-24 15:38:04 -070085 elif key == "karaf_timeout":
86 self.karafTimeout = self.options[ key ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -070087 self.home = self.checkOptions( self.home, "~/onos" )
88 self.karafUser = self.checkOptions( self.karafUser, self.user_name )
89 self.karafPass = self.checkOptions( self.karafPass, self.pwd )
Jon Hall3c0114c2020-08-11 15:07:42 -070090 self.dockerPrompt = self.checkOptions( self.dockerPrompt, "~/onos#" )
Jon Hall9b0de1f2020-08-24 15:38:04 -070091 self.karafTimeout = self.checkOptions( self.karafTimeout, 7200000 )
andrewonlab95ce8322014-10-13 14:12:04 -040092
kelvin-onlaba4074292015-07-09 15:19:49 -070093 for key in self.options:
94 if key == 'onosIp':
95 self.onosIp = self.options[ 'onosIp' ]
96 break
97
kelvin8ec71442015-01-15 16:57:00 -080098 self.name = self.options[ 'name' ]
kelvin-onlaba4074292015-07-09 15:19:49 -070099
100 try:
Jon Hallc6793552016-01-19 14:18:37 -0800101 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -0700102 self.ip_address = os.getenv( str( self.ip_address ) )
103 else:
104 main.log.info( self.name +
105 ": Trying to connect to " +
106 self.ip_address )
107
108 except KeyError:
109 main.log.info( "Invalid host name," +
110 " connecting to local host instead" )
111 self.ip_address = 'localhost'
112 except Exception as inst:
113 main.log.error( "Uncaught exception: " + str( inst ) )
114
kelvin8ec71442015-01-15 16:57:00 -0800115 self.handle = super( OnosCliDriver, self ).connect(
kelvin-onlab08679eb2015-01-21 16:11:48 -0800116 user_name=self.user_name,
117 ip_address=self.ip_address,
kelvin-onlab898a6c62015-01-16 14:13:53 -0800118 port=self.port,
119 pwd=self.pwd,
120 home=self.home )
andrewonlab95ce8322014-10-13 14:12:04 -0400121
kelvin8ec71442015-01-15 16:57:00 -0800122 self.handle.sendline( "cd " + self.home )
Devin Limdc78e202017-06-09 18:30:07 -0700123 self.handle.expect( self.prompt )
andrewonlab95ce8322014-10-13 14:12:04 -0400124 if self.handle:
125 return self.handle
kelvin8ec71442015-01-15 16:57:00 -0800126 else:
127 main.log.info( "NO ONOS HANDLE" )
andrewonlab95ce8322014-10-13 14:12:04 -0400128 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -0800129 except TypeError:
130 main.log.exception( self.name + ": Object not as expected" )
131 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400132 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800133 main.log.error( self.name + ": EOF exception found" )
134 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700135 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800136 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800137 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700138 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400139
kelvin8ec71442015-01-15 16:57:00 -0800140 def disconnect( self ):
141 """
andrewonlab95ce8322014-10-13 14:12:04 -0400142 Called when Test is complete to disconnect the ONOS handle.
kelvin8ec71442015-01-15 16:57:00 -0800143 """
Jon Halld61331b2015-02-17 16:35:47 -0800144 response = main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -0400145 try:
Jon Hall61282e32015-03-19 11:34:11 -0700146 if self.handle:
147 i = self.logout()
148 if i == main.TRUE:
149 self.handle.sendline( "" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700150 for l in range( 3 ):
151 p = self.handle.expect( [ self.prompt, self.dockerPrompt ] )
152 if p == 1:
153 self.inDocker = False
154 self.handle.sendline( "exit" )
155 j = self.handle.expect( [ "closed", pexpect.TIMEOUT ], timeout=3 )
156 if j == 0:
157 return response
158 response = main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -0800159 except TypeError:
160 main.log.exception( self.name + ": Object not as expected" )
Jon Halld61331b2015-02-17 16:35:47 -0800161 response = main.FALSE
andrewonlab95ce8322014-10-13 14:12:04 -0400162 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800163 main.log.error( self.name + ": EOF exception found" )
164 main.log.error( self.name + ": " + self.handle.before )
Jon Hall61282e32015-03-19 11:34:11 -0700165 except ValueError:
Jon Hall1a77a1e2015-04-06 10:41:13 -0700166 main.log.exception( "Exception in disconnect of " + self.name )
Jon Hall61282e32015-03-19 11:34:11 -0700167 response = main.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -0800168 except Exception:
Jon Hall3c0114c2020-08-11 15:07:42 -0700169 main.log.exception( self.name + ": disconnection failed from the host" )
andrewonlab95ce8322014-10-13 14:12:04 -0400170 response = main.FALSE
171 return response
172
kelvin8ec71442015-01-15 16:57:00 -0800173 def logout( self ):
174 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500175 Sends 'logout' command to ONOS cli
Jon Hall61282e32015-03-19 11:34:11 -0700176 Returns main.TRUE if exited CLI and
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000177 main.FALSE on timeout (not guranteed you are disconnected)
Jon Hall61282e32015-03-19 11:34:11 -0700178 None on TypeError
179 Exits test on unknown error or pexpect exits unexpectedly
kelvin8ec71442015-01-15 16:57:00 -0800180 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500181 try:
Jon Hall61282e32015-03-19 11:34:11 -0700182 if self.handle:
183 self.handle.sendline( "" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700184 i = self.handle.expect( [ self.karafPrompt,
185 self.Prompt(),
186 pexpect.TIMEOUT ],
187
Jon Hall61282e32015-03-19 11:34:11 -0700188 timeout=10 )
189 if i == 0: # In ONOS CLI
190 self.handle.sendline( "logout" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700191 j = self.handle.expect( [ self.Prompt(),
Jon Hallbfe00002016-04-05 10:23:54 -0700192 "Command not found:",
193 pexpect.TIMEOUT ] )
194 if j == 0: # Successfully logged out
195 return main.TRUE
196 elif j == 1 or j == 2:
197 # ONOS didn't fully load, and logout command isn't working
198 # or the command timed out
199 self.handle.send( "\x04" ) # send ctrl-d
Jon Hall64ab3bd2016-05-13 11:29:44 -0700200 try:
Jon Hall3c0114c2020-08-11 15:07:42 -0700201 self.handle.expect( self.Prompt() )
Jon Hall64ab3bd2016-05-13 11:29:44 -0700202 except pexpect.TIMEOUT:
203 main.log.error( "ONOS did not respond to 'logout' or CTRL-d" )
Jon Hallbfe00002016-04-05 10:23:54 -0700204 return main.TRUE
Jon Halle0f0b342017-04-18 11:43:47 -0700205 else: # some other output
Jon Hallbfe00002016-04-05 10:23:54 -0700206 main.log.warn( "Unknown repsonse to logout command: '{}'",
207 repr( self.handle.before ) )
208 return main.FALSE
Jon Hall61282e32015-03-19 11:34:11 -0700209 elif i == 1: # not in CLI
210 return main.TRUE
steven30801e42f1fb2019-01-17 11:31:45 +0800211 elif i == 2: # Timeout
Jon Hall61282e32015-03-19 11:34:11 -0700212 return main.FALSE
213 else:
andrewonlab9627f432014-11-14 12:45:10 -0500214 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800215 except TypeError:
216 main.log.exception( self.name + ": Object not as expected" )
217 return None
andrewonlab38d2b4a2014-11-13 16:28:47 -0500218 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800219 main.log.error( self.name + ": eof exception found" )
Jon Hall61282e32015-03-19 11:34:11 -0700220 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700221 main.cleanAndExit()
Jon Hall61282e32015-03-19 11:34:11 -0700222 except ValueError:
Jon Hall5aa168b2015-03-23 14:23:09 -0700223 main.log.error( self.name +
224 "ValueError exception in logout method" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800225 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800226 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700227 main.cleanAndExit()
andrewonlab38d2b4a2014-11-13 16:28:47 -0500228
kelvin-onlabd3b64892015-01-20 13:26:24 -0800229 def setCell( self, cellname ):
kelvin8ec71442015-01-15 16:57:00 -0800230 """
andrewonlab95ce8322014-10-13 14:12:04 -0400231 Calls 'cell <name>' to set the environment variables on ONOSbench
kelvin8ec71442015-01-15 16:57:00 -0800232
andrewonlab95ce8322014-10-13 14:12:04 -0400233 Before issuing any cli commands, set the environment variable first.
kelvin8ec71442015-01-15 16:57:00 -0800234 """
andrewonlab95ce8322014-10-13 14:12:04 -0400235 try:
236 if not cellname:
kelvin8ec71442015-01-15 16:57:00 -0800237 main.log.error( "Must define cellname" )
Devin Lim44075962017-08-11 10:56:37 -0700238 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400239 else:
kelvin8ec71442015-01-15 16:57:00 -0800240 self.handle.sendline( "cell " + str( cellname ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800241 # Expect the cellname in the ONOSCELL variable.
kelvin8ec71442015-01-15 16:57:00 -0800242 # Note that this variable name is subject to change
andrewonlab95ce8322014-10-13 14:12:04 -0400243 # and that this driver will have to change accordingly
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700244 self.handle.expect( str( cellname ) )
andrew@onlab.usc400b112015-01-21 15:33:19 -0800245 handleBefore = self.handle.before
246 handleAfter = self.handle.after
kelvin8ec71442015-01-15 16:57:00 -0800247 # Get the rest of the handle
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700248 self.handle.sendline( "" )
249 self.handle.expect( self.prompt )
andrew@onlab.usc400b112015-01-21 15:33:19 -0800250 handleMore = self.handle.before
andrewonlab95ce8322014-10-13 14:12:04 -0400251
kelvin-onlabd3b64892015-01-20 13:26:24 -0800252 main.log.info( "Cell call returned: " + handleBefore +
253 handleAfter + handleMore )
andrewonlab95ce8322014-10-13 14:12:04 -0400254
255 return main.TRUE
256
Jon Halld4d4b372015-01-28 16:02:41 -0800257 except TypeError:
258 main.log.exception( self.name + ": Object not as expected" )
259 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400260 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800261 main.log.error( self.name + ": eof exception found" )
262 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700263 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800264 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800265 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700266 main.cleanAndExit()
kelvin8ec71442015-01-15 16:57:00 -0800267
pingping-lin57a56ce2015-05-20 16:43:48 -0700268 def startOnosCli( self, ONOSIp, karafTimeout="",
Chiyu Chengef109502016-11-21 15:51:38 -0800269 commandlineTimeout=10, onosStartTimeout=60, waitForStart=False ):
kelvin8ec71442015-01-15 16:57:00 -0800270 """
Jon Hallefbd9792015-03-05 16:11:36 -0800271 karafTimeout is an optional argument. karafTimeout value passed
kelvin-onlabd3b64892015-01-20 13:26:24 -0800272 by user would be used to set the current karaf shell idle timeout.
273 Note that when ever this property is modified the shell will exit and
Hari Krishnad7b9c202015-01-05 10:38:14 -0800274 the subsequent login would reflect new idle timeout.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800275 Below is an example to start a session with 60 seconds idle timeout
276 ( input value is in milliseconds ):
kelvin8ec71442015-01-15 16:57:00 -0800277
Hari Krishna25d42f72015-01-05 15:08:28 -0800278 tValue = "60000"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800279 main.ONOScli1.startOnosCli( ONOSIp, karafTimeout=tValue )
kelvin8ec71442015-01-15 16:57:00 -0800280
kelvin-onlabd3b64892015-01-20 13:26:24 -0800281 Note: karafTimeout is left as str so that this could be read
282 and passed to startOnosCli from PARAMS file as str.
kelvin8ec71442015-01-15 16:57:00 -0800283 """
You Wangf69ab392016-01-26 16:34:38 -0800284 self.onosIp = ONOSIp
andrewonlab95ce8322014-10-13 14:12:04 -0400285 try:
Jon Hall67253832016-12-05 09:47:13 -0800286 # Check if we are already in the cli
kelvin8ec71442015-01-15 16:57:00 -0800287 self.handle.sendline( "" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700288 x = self.handle.expect( [ self.Prompt(), self.karafPrompt ], commandlineTimeout )
andrewonlab48829f62014-11-17 13:49:01 -0500289 if x == 1:
kelvin8ec71442015-01-15 16:57:00 -0800290 main.log.info( "ONOS cli is already running" )
andrewonlab48829f62014-11-17 13:49:01 -0500291 return main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -0400292
Jon Hall67253832016-12-05 09:47:13 -0800293 # Not in CLI so login
Jon Hall3c0114c2020-08-11 15:07:42 -0700294 if self.inDocker:
295 # The Docker does not have all the wrapper scripts
296 startCliCommand = "ssh -p 8101 -o StrictHostKeyChecking=no %s@localhost" % self.karafUser
297 elif waitForStart:
Jeremy Ronquilloec916a42018-02-02 13:05:57 -0800298 # Wait for onos start ( onos-wait-for-start ) and enter onos cli
Jon Hall3c0114c2020-08-11 15:07:42 -0700299 startCliCommand = "onos-wait-for-start " + str( ONOSIp )
Chiyu Chengef109502016-11-21 15:51:38 -0800300 else:
Jon Hall3c0114c2020-08-11 15:07:42 -0700301 startCliCommand = "onos " + str( ONOSIp )
302 self.handle.sendline( startCliCommand )
303 tries = 0
Jon Hallf69e3162020-09-01 09:08:44 -0700304 timeoutSet = False
Jon Hall3c0114c2020-08-11 15:07:42 -0700305 while tries < 5:
306 i = self.handle.expect( [
307 self.karafPrompt,
308 "Password:",
309 pexpect.TIMEOUT ], onosStartTimeout )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400310
andrewonlab3a7c3c72014-10-24 17:21:03 -0400311 if i == 0:
Jon Hallf69e3162020-09-01 09:08:44 -0700312 if not karafTimeout or timeoutSet:
Jon Hall9b0de1f2020-08-24 15:38:04 -0700313 main.log.info( str( ONOSIp ) + " CLI Started successfully" )
314 return main.TRUE
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\
Jon Hall3c0114c2020-08-11 15:07:42 -0700318 sshIdleTimeout " +
Jon Hall9b0de1f2020-08-24 15:38:04 -0700319 str( karafTimeout ) )
320 self.handle.expect( "closed by remote host" )
Jon Hallf69e3162020-09-01 09:08:44 -0700321 self.handle.expect( self.Prompt() )
Jon Hall9b0de1f2020-08-24 15:38:04 -0700322 self.handle.sendline( startCliCommand )
Jon Hallf69e3162020-09-01 09:08:44 -0700323 timeoutSet = True
Jon Hall3c0114c2020-08-11 15:07:42 -0700324 elif i == 1:
325 main.log.info( str( ONOSIp ) + " CLI asking for password" )
326 main.log.debug( "Sending %s" % self.karafPass )
327 self.handle.sendline( self.karafPass )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400328 else:
Jon Hall3c0114c2020-08-11 15:07:42 -0700329 # If failed, send ctrl+c to process and try again
330 main.log.info( "Starting CLI failed. Retrying..." )
Jon Hallf69e3162020-09-01 09:08:44 -0700331 time.sleep( 5 )
Jon Hall3c0114c2020-08-11 15:07:42 -0700332 self.handle.send( "\x03" )
333 self.handle.sendline( startCliCommand )
334 tries += 1
335 main.log.error( "Connection to CLI " + str( ONOSIp ) + " timeout" )
336 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -0800337 except TypeError:
338 main.log.exception( self.name + ": Object not as expected" )
339 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400340 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800341 main.log.error( self.name + ": EOF exception found" )
342 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700343 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800344 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800345 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700346 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400347
suibin zhang116647a2016-05-06 16:30:09 -0700348 def startCellCli( self, karafTimeout="",
349 commandlineTimeout=10, onosStartTimeout=60 ):
350 """
Jon Hall3c0114c2020-08-11 15:07:42 -0700351 Start CLI on onos cell handle.
suibin zhang116647a2016-05-06 16:30:09 -0700352
353 karafTimeout is an optional argument. karafTimeout value passed
354 by user would be used to set the current karaf shell idle timeout.
355 Note that when ever this property is modified the shell will exit and
356 the subsequent login would reflect new idle timeout.
357 Below is an example to start a session with 60 seconds idle timeout
358 ( input value is in milliseconds ):
359
360 tValue = "60000"
361
362 Note: karafTimeout is left as str so that this could be read
363 and passed to startOnosCli from PARAMS file as str.
364 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000365
suibin zhang116647a2016-05-06 16:30:09 -0700366 try:
367 self.handle.sendline( "" )
368 x = self.handle.expect( [
Jon Hall3c0114c2020-08-11 15:07:42 -0700369 self.Prompt(), self.karafPrompt ], commandlineTimeout )
suibin zhang116647a2016-05-06 16:30:09 -0700370
371 if x == 1:
372 main.log.info( "ONOS cli is already running" )
373 return main.TRUE
374
Jeremy Ronquilloec916a42018-02-02 13:05:57 -0800375 # Wait for onos start ( onos-wait-for-start ) and enter onos cli
suibin zhang116647a2016-05-06 16:30:09 -0700376 self.handle.sendline( "/opt/onos/bin/onos" )
377 i = self.handle.expect( [
Jon Hall6c9e2da2018-11-06 12:01:23 -0800378 self.karafPrompt,
suibin zhang116647a2016-05-06 16:30:09 -0700379 pexpect.TIMEOUT ], onosStartTimeout )
380
381 if i == 0:
382 main.log.info( self.name + " CLI Started successfully" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800383 if karafTimeout: # FIXME: This doesn't look right
suibin zhang116647a2016-05-06 16:30:09 -0700384 self.handle.sendline(
385 "config:property-set -p org.apache.karaf.shell\
386 sshIdleTimeout " +
387 karafTimeout )
Jon Hall3c0114c2020-08-11 15:07:42 -0700388 self.handle.expect( self.Prompt() )
suibin zhang116647a2016-05-06 16:30:09 -0700389 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800390 self.handle.expect( self.karafPrompt )
suibin zhang116647a2016-05-06 16:30:09 -0700391 return main.TRUE
392 else:
393 # If failed, send ctrl+c to process and try again
394 main.log.info( "Starting CLI failed. Retrying..." )
395 self.handle.send( "\x03" )
396 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800397 i = self.handle.expect( [ self.karafPrompt, pexpect.TIMEOUT ],
suibin zhang116647a2016-05-06 16:30:09 -0700398 timeout=30 )
399 if i == 0:
400 main.log.info( self.name + " CLI Started " +
401 "successfully after retry attempt" )
402 if karafTimeout:
403 self.handle.sendline(
404 "config:property-set -p org.apache.karaf.shell\
405 sshIdleTimeout " +
406 karafTimeout )
Jon Hall3c0114c2020-08-11 15:07:42 -0700407 self.handle.expect( self.Prompt() )
suibin zhang116647a2016-05-06 16:30:09 -0700408 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800409 self.handle.expect( self.karafPrompt )
suibin zhang116647a2016-05-06 16:30:09 -0700410 return main.TRUE
411 else:
412 main.log.error( "Connection to CLI " +
413 self.name + " timeout" )
414 return main.FALSE
415
416 except TypeError:
417 main.log.exception( self.name + ": Object not as expected" )
418 return None
419 except pexpect.EOF:
420 main.log.error( self.name + ": EOF exception found" )
421 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700422 main.cleanAndExit()
suibin zhang116647a2016-05-06 16:30:09 -0700423 except Exception:
424 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700425 main.cleanAndExit()
suibin zhang116647a2016-05-06 16:30:09 -0700426
Pratik Parab3b2ab5a2017-02-14 13:15:14 -0800427 def log( self, cmdStr, level="", noExit=False ):
kelvin-onlab9f541032015-02-04 16:19:53 -0800428 """
429 log the commands in the onos CLI.
kelvin-onlab338f5512015-02-06 10:53:16 -0800430 returns main.TRUE on success
Jon Hallefbd9792015-03-05 16:11:36 -0800431 returns main.FALSE if Error occurred
YPZhangebf9eb52016-05-12 15:20:24 -0700432 if noExit is True, TestON will not exit, but clean up
kelvin-onlab338f5512015-02-06 10:53:16 -0800433 Available level: DEBUG, TRACE, INFO, WARN, ERROR
434 Level defaults to INFO
Pratik Parab3b2ab5a2017-02-14 13:15:14 -0800435 if cmdStr has spaces then put quotes in the passed string
kelvin-onlab9f541032015-02-04 16:19:53 -0800436 """
437 try:
kelvin-onlab338f5512015-02-06 10:53:16 -0800438 lvlStr = ""
439 if level:
440 lvlStr = "--level=" + level
441
kelvin-onlab338f5512015-02-06 10:53:16 -0800442 self.handle.sendline( "log:log " + lvlStr + " " + cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -0700443 self.handle.expect( "log:log" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800444 self.handle.expect( self.karafPrompt )
kelvin-onlabfb521662015-02-27 09:52:40 -0800445
kelvin-onlab9f541032015-02-04 16:19:53 -0800446 response = self.handle.before
447 if re.search( "Error", response ):
Jon Halldac3eae2020-06-05 12:04:06 -0700448 main.log.debug( response )
kelvin-onlab9f541032015-02-04 16:19:53 -0800449 return main.FALSE
450 return main.TRUE
Jon Hall80daded2015-05-27 16:07:00 -0700451 except pexpect.TIMEOUT:
452 main.log.exception( self.name + ": TIMEOUT exception found" )
Jon Hall43060f62020-06-23 13:13:33 -0700453 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700454 if noExit:
455 main.cleanup()
456 return None
457 else:
Devin Lim44075962017-08-11 10:56:37 -0700458 main.cleanAndExit()
kelvin-onlab9f541032015-02-04 16:19:53 -0800459 except pexpect.EOF:
460 main.log.error( self.name + ": EOF exception found" )
461 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700462 if noExit:
463 main.cleanup()
464 return None
465 else:
Devin Lim44075962017-08-11 10:56:37 -0700466 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800467 except Exception:
kelvin-onlabfb521662015-02-27 09:52:40 -0800468 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700469 if noExit:
470 main.cleanup()
471 return None
472 else:
Devin Lim44075962017-08-11 10:56:37 -0700473 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400474
Jon Hall0e240372018-05-02 11:21:57 -0700475 def clearBuffer( self, debug=False, timeout=10, noExit=False ):
kelvin8ec71442015-01-15 16:57:00 -0800476 """
Jon Hall0e240372018-05-02 11:21:57 -0700477 Test cli connection and clear any left over output in the buffer
478 Optional Arguments:
479 debug - Defaults to False. If True, will enable debug logging.
480 timeout - Defaults to 10. Amount of time in seconds for a command to return
481 before a timeout.
482 noExit - Defaults to False. If True, will not exit TestON in the event of a
kelvin8ec71442015-01-15 16:57:00 -0800483 """
andrewonlaba18f6bf2014-10-13 19:31:54 -0400484 try:
Jon Halla495f562016-05-16 18:03:26 -0700485 # Try to reconnect if disconnected from cli
486 self.handle.sendline( "" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700487 i = self.handle.expect( [ self.karafPrompt,
488 self.Prompt(),
489 pexpect.TIMEOUT ] )
Jon Hall0e240372018-05-02 11:21:57 -0700490 response = self.handle.before
Jon Halla495f562016-05-16 18:03:26 -0700491 if i == 1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700492 main.log.error( self.name + ": onos cli session closed. " )
Jon Halla495f562016-05-16 18:03:26 -0700493 if self.onosIp:
494 main.log.warn( "Trying to reconnect " + self.onosIp )
495 reconnectResult = self.startOnosCli( self.onosIp )
496 if reconnectResult:
497 main.log.info( self.name + ": onos cli session reconnected." )
498 else:
499 main.log.error( self.name + ": reconnection failed." )
YPZhang14a4aa92016-07-15 13:37:15 -0700500 if noExit:
501 return None
502 else:
Devin Lim44075962017-08-11 10:56:37 -0700503 main.cleanAndExit()
Jon Halla495f562016-05-16 18:03:26 -0700504 else:
Devin Lim44075962017-08-11 10:56:37 -0700505 main.cleanAndExit()
Jon Halla495f562016-05-16 18:03:26 -0700506 if i == 2:
Jon Hall7a6ebfd2017-03-13 10:58:58 -0700507 main.log.warn( "Timeout when testing cli responsiveness" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700508 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
Jon Hall7a6ebfd2017-03-13 10:58:58 -0700509 self.handle.send( "\x03" ) # Send ctrl-c to clear previous output
Jon Hall6c9e2da2018-11-06 12:01:23 -0800510 self.handle.expect( self.karafPrompt )
Jon Halla495f562016-05-16 18:03:26 -0700511
Jon Hall0e240372018-05-02 11:21:57 -0700512 response += self.handle.before
Jon Hall14a03b52016-05-11 12:07:30 -0700513 if debug:
Jon Hall0e240372018-05-02 11:21:57 -0700514 main.log.debug( self.name + ": Raw output from sending ''" )
515 main.log.debug( self.name + ": " + repr( response ) )
516 except pexpect.TIMEOUT:
517 main.log.error( self.name + ": ONOS timeout" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700518 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
You Wang141b43b2018-06-26 16:50:18 -0700519 self.handle.send( "\x03" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800520 self.handle.expect( self.karafPrompt )
Jon Hall0e240372018-05-02 11:21:57 -0700521 return None
522 except pexpect.EOF:
523 main.log.error( self.name + ": EOF exception found" )
524 main.log.error( self.name + ": " + self.handle.before )
525 if noExit:
526 return None
527 else:
528 main.cleanAndExit()
529 except Exception:
530 main.log.exception( self.name + ": Uncaught exception!" )
531 if noExit:
532 return None
533 else:
534 main.cleanAndExit()
535
Jon Hall22e94ce2019-01-15 14:52:17 -0800536 def sendline( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False, relaxedRegex=True, expectJson=False ):
Jon Hall0e240372018-05-02 11:21:57 -0700537 """
538 A wrapper around pexpect's sendline/expect. Will return all the output from a given command
539
540 Required Arguments:
541 cmdStr - String to send to the pexpect session
542
543 Optional Arguments:
544 showResponse - Defaults to False. If True will log the response.
545 debug - Defaults to False. If True, will enable debug logging.
546 timeout - Defaults to 10. Amount of time in seconds for a command to return
547 before a timeout.
548 noExit - Defaults to False. If True, will not exit TestON in the event of a
549 closed channel, but instead return None
Jon Hall6c9e2da2018-11-06 12:01:23 -0800550 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 -0700551
552 Warning: There are no sanity checking to commands sent using this method.
553
554 """
555 try:
556 # Try to reconnect if disconnected from cli
557 self.clearBuffer( debug=debug, timeout=timeout, noExit=noExit )
558 if debug:
559 # NOTE: This adds an average of .4 seconds per call
Jon Hall14a03b52016-05-11 12:07:30 -0700560 logStr = "\"Sending CLI command: '" + cmdStr + "'\""
Jon Halle0f0b342017-04-18 11:43:47 -0700561 self.log( logStr, noExit=noExit )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800562 self.handle.sendline( cmdStr )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800563 self.handle.expect( self.karafPrompt, timeout )
Jon Hall63604932015-02-26 17:09:50 -0800564 response = self.handle.before
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000565 main.log.info( "Command '" + str( cmdStr ) + "' sent to "
Jon Hallc6793552016-01-19 14:18:37 -0800566 + self.name + "." )
Jon Hallc6358dd2015-04-10 12:44:28 -0700567 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700568 main.log.debug( self.name + ": Raw output" )
569 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700570
Jon Hall3c0114c2020-08-11 15:07:42 -0700571 response = self.cleanOutput( response, debug=debug )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800572 # Remove control codes from karaf 4.2.1
Jon Hall3c0114c2020-08-11 15:07:42 -0700573 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 -0800574 response = karafEscape.sub( '', response )
575 if debug:
576 main.log.debug( self.name + ": karafEscape output" )
577 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700578 # Remove ANSI color control strings from output
Jon Hall43060f62020-06-23 13:13:33 -0700579 response = self.cleanOutput( response, debug )
Jon Hallc6358dd2015-04-10 12:44:28 -0700580
Jon Hall6c9e2da2018-11-06 12:01:23 -0800581 # Remove ANSI color control strings from output
Jon Hallcf31d0f2018-12-13 11:18:48 -0800582 # NOTE: karaf is sometimes adding a single character then two
583 # backspaces and sometimes adding 2 characters with 2 backspaces??
Jon Hall3c0114c2020-08-11 15:07:42 -0700584 backspaceEscape = re.compile( r'((.|\s)\x08)' )
585 unchanged = False
586 while not unchanged:
587 old = response
588 response = backspaceEscape.sub( '', response, count=1 )
589 if debug:
590 main.log.debug( self.name + ": backspaceEscape output" )
591 main.log.debug( self.name + ": " + repr( response ) )
592 unchanged = old == response
Jon Hall6c9e2da2018-11-06 12:01:23 -0800593
kelvin-onlabfb521662015-02-27 09:52:40 -0800594 # Remove extra return chars that get added
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000595 response = re.sub( r"\s\r", "", response )
Jon Hallc6358dd2015-04-10 12:44:28 -0700596 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700597 main.log.debug( self.name + ": Removed extra returns " +
598 "from output" )
599 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700600
601 # Strip excess whitespace
Jon Hall63604932015-02-26 17:09:50 -0800602 response = response.strip()
Jon Hallc6358dd2015-04-10 12:44:28 -0700603 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700604 main.log.debug( self.name + ": parsed and stripped output" )
605 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700606
Jon Hall63604932015-02-26 17:09:50 -0800607 # parse for just the output, remove the cmd from response
Jon Hallce0d70b2018-12-11 11:01:32 -0800608 cmdPattern = cmdStr.strip()
609 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
610 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800611 if relaxedRegex:
Jon Hallce0d70b2018-12-11 11:01:32 -0800612 cmdPattern = cmdPattern.split( '|' )[ -1 ].strip()
613 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
614 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800615 # This was added because karaf 4.2 is stripping some characters from the command echo
Jon Hallce0d70b2018-12-11 11:01:32 -0800616 output = response.split( cmdPattern, 1 )
Jon Hall22e94ce2019-01-15 14:52:17 -0800617 if expectJson:
618 main.log.warn( "Relaxed Regex: Searching for a json string amongst the output" )
619 jsonPattern = r'\{.*\}'
620 match = re.search( jsonPattern, output[ 0 ] )
621 if match:
622 output = [ '' , match.group( 0 ) ] # We expect a list with the second element to be the output
Jon Hall39e3ffe2018-12-05 11:40:29 -0800623 if len( output ) < 2:
624 main.log.warn( "Relaxing regex match to last 5 characters of the sent command" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800625 cmdPattern = cmdPattern[ -5: ]
626 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
627 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
628 output = response.split( cmdPattern, 1 )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800629 else:
Jon Hallce0d70b2018-12-11 11:01:32 -0800630 output = response.split( cmdPattern, 1 )
631 if len( output ) < 2: # TODO: Should we do this without the relaxedRegex flag?
Jon Hall8c9dd1c2018-11-14 15:40:39 -0800632 main.log.warn( "Relaxing regex match to last 5 characters of the sent command" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800633 output = response.split( cmdPattern[ -5: ], 1 )
Jon Hall0e240372018-05-02 11:21:57 -0700634 if output:
635 if debug:
636 main.log.debug( self.name + ": split output" )
637 for r in output:
638 main.log.debug( self.name + ": " + repr( r ) )
Jon Hallce0d70b2018-12-11 11:01:32 -0800639 if len( output ) == 1:
640 main.log.error( "Could not remove sent command echo from output" )
641 return output
Jon Hall0e240372018-05-02 11:21:57 -0700642 output = output[ 1 ].strip()
GlennRC85870432015-11-23 11:45:51 -0800643 if showResponse:
GlennRCed771242016-01-13 17:02:47 -0800644 main.log.info( "Response from ONOS: {}".format( output ) )
Jon Hall0e240372018-05-02 11:21:57 -0700645 self.clearBuffer( debug=debug, timeout=timeout, noExit=noExit )
GlennRC85870432015-11-23 11:45:51 -0800646 return output
GlennRCed771242016-01-13 17:02:47 -0800647 except pexpect.TIMEOUT:
Jon Hall0e240372018-05-02 11:21:57 -0700648 main.log.error( self.name + ": ONOS timeout" )
GlennRCed771242016-01-13 17:02:47 -0800649 if debug:
Jon Hall3c0114c2020-08-11 15:07:42 -0700650 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
You Wang6b5e5ba2019-01-31 15:32:40 -0800651 self.exitFromCmd( self.karafPrompt, 100 )
GlennRCed771242016-01-13 17:02:47 -0800652 return None
Jon Hallc6358dd2015-04-10 12:44:28 -0700653 except IndexError:
654 main.log.exception( self.name + ": Object not as expected" )
Jon Halla495f562016-05-16 18:03:26 -0700655 main.log.debug( "response: {}".format( repr( response ) ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700656 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800657 except TypeError:
658 main.log.exception( self.name + ": Object not as expected" )
659 return None
andrewonlaba18f6bf2014-10-13 19:31:54 -0400660 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800661 main.log.error( self.name + ": EOF exception found" )
662 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700663 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700664 return None
665 else:
Devin Lim44075962017-08-11 10:56:37 -0700666 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800667 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800668 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700669 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700670 return None
671 else:
Devin Lim44075962017-08-11 10:56:37 -0700672 main.cleanAndExit()
andrewonlaba18f6bf2014-10-13 19:31:54 -0400673
Jon Halld5a94fb2018-11-13 14:32:23 -0800674 def lineCount( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False, relaxedRegex=True ):
675 """
676 A wrapper around sendline(). Will return the number of lines returned or None on error
677
678 Required Arguments:
679 cmdStr - String to send to the pexpect session
680
681 Optional Arguments:
682 showResponse - Defaults to False. If True will log the response.
683 debug - Defaults to False. If True, will enable debug logging.
684 timeout - Defaults to 10. Amount of time in seconds for a command to return
685 before a timeout.
686 noExit - Defaults to False. If True, will not exit TestON in the event of a
687 closed channel, but instead return None
688 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.
689
690 Warning: There are no sanity checking to commands sent using this method.
691
692 """
693 try:
694 numLines = self.sendline( cmdStr, showResponse, debug, timeout, noExit, relaxedRegex )
You Wang0ce8e0c2019-02-22 12:22:26 -0800695 parsed = re.search( "(\d+)", numLines )
Jon Hall8c9dd1c2018-11-14 15:40:39 -0800696 if not parsed:
697 main.log.error( "Warning, output of karaf's wc may have changed" )
698 return None
699 return parsed.group( 1 )
Jon Halld5a94fb2018-11-13 14:32:23 -0800700 except IndexError:
701 main.log.exception( self.name + ": Object not as expected" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800702 main.log.debug( "response: {}".format( repr( numLines ) ) )
Jon Halld5a94fb2018-11-13 14:32:23 -0800703 return None
704 except TypeError:
705 main.log.exception( self.name + ": Object not as expected" )
706 return None
707 except Exception:
708 main.log.exception( self.name + ": Uncaught exception!" )
709 if noExit:
710 return None
711 else:
712 main.cleanAndExit()
713
kelvin8ec71442015-01-15 16:57:00 -0800714 # IMPORTANT NOTE:
715 # For all cli commands, naming convention should match
kelvin-onlabd3b64892015-01-20 13:26:24 -0800716 # the cli command changing 'a:b' with 'aB'.
717 # Ex ) onos:topology > onosTopology
718 # onos:links > onosLinks
719 # feature:list > featureList
Jon Halle3f39ff2015-01-13 11:50:53 -0800720
kelvin-onlabd3b64892015-01-20 13:26:24 -0800721 def addNode( self, nodeId, ONOSIp, tcpPort="" ):
kelvin8ec71442015-01-15 16:57:00 -0800722 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400723 Adds a new cluster node by ID and address information.
724 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800725 * nodeId
726 * ONOSIp
andrewonlabc2d05aa2014-10-13 16:51:10 -0400727 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800728 * tcpPort
kelvin8ec71442015-01-15 16:57:00 -0800729 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400730 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800731 cmdStr = "add-node " + str( nodeId ) + " " +\
732 str( ONOSIp ) + " " + str( tcpPort )
733 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700734 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800735 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -0800736 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700737 main.log.error( self.name + ": Error in adding node" )
kelvin8ec71442015-01-15 16:57:00 -0800738 main.log.error( handle )
Jon Halle3f39ff2015-01-13 11:50:53 -0800739 return main.FALSE
andrewonlabc2d05aa2014-10-13 16:51:10 -0400740 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800741 main.log.info( "Node " + str( ONOSIp ) + " added" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400742 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800743 except AssertionError:
744 main.log.exception( "" )
745 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800746 except TypeError:
747 main.log.exception( self.name + ": Object not as expected" )
748 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400749 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800750 main.log.error( self.name + ": EOF exception found" )
751 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700752 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800753 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800754 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700755 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400756
kelvin-onlabd3b64892015-01-20 13:26:24 -0800757 def removeNode( self, nodeId ):
kelvin8ec71442015-01-15 16:57:00 -0800758 """
andrewonlab86dc3082014-10-13 18:18:38 -0400759 Removes a cluster by ID
760 Issues command: 'remove-node [<node-id>]'
761 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800762 * nodeId
kelvin8ec71442015-01-15 16:57:00 -0800763 """
andrewonlab86dc3082014-10-13 18:18:38 -0400764 try:
andrewonlab86dc3082014-10-13 18:18:38 -0400765
kelvin-onlabd3b64892015-01-20 13:26:24 -0800766 cmdStr = "remove-node " + str( nodeId )
Jon Hall08f61bc2015-04-13 16:00:30 -0700767 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700768 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800769 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700770 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700771 main.log.error( self.name + ": Error in removing node" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700772 main.log.error( handle )
773 return main.FALSE
774 else:
775 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800776 except AssertionError:
777 main.log.exception( "" )
778 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800779 except TypeError:
780 main.log.exception( self.name + ": Object not as expected" )
781 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400782 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800783 main.log.error( self.name + ": EOF exception found" )
784 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700785 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800786 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800787 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700788 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400789
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700790 def nodes( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800791 """
andrewonlab7c211572014-10-15 16:45:20 -0400792 List the nodes currently visible
793 Issues command: 'nodes'
Jon Hall61282e32015-03-19 11:34:11 -0700794 Optional argument:
795 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800796 """
andrewonlab7c211572014-10-15 16:45:20 -0400797 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700798 cmdStr = "nodes"
Jon Hall61282e32015-03-19 11:34:11 -0700799 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700800 cmdStr += " -j"
801 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700802 assert output is not None, "Error in sendline"
Jon Halle37bd1f2020-09-10 12:16:41 -0700803 # "Command not found" or "Service org.onosproject.security.AuditService not found"
804 assert "not found" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -0700805 return output
Jon Hallc6793552016-01-19 14:18:37 -0800806 except AssertionError:
807 main.log.exception( "" )
808 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800809 except TypeError:
810 main.log.exception( self.name + ": Object not as expected" )
811 return None
andrewonlab7c211572014-10-15 16:45:20 -0400812 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800813 main.log.error( self.name + ": EOF exception found" )
814 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700815 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800816 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800817 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700818 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400819
kelvin8ec71442015-01-15 16:57:00 -0800820 def topology( self ):
821 """
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700822 Definition:
Jon Hall390696c2015-05-05 17:13:41 -0700823 Returns the output of topology command.
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700824 Return:
825 topology = current ONOS topology
kelvin8ec71442015-01-15 16:57:00 -0800826 """
andrewonlab95ce8322014-10-13 14:12:04 -0400827 try:
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700828 cmdStr = "topology -j"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800829 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800830 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800831 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700832 main.log.info( cmdStr + " returned: " + str( handle ) )
andrewonlab95ce8322014-10-13 14:12:04 -0400833 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800834 except AssertionError:
835 main.log.exception( "" )
Jon Halld4d4b372015-01-28 16:02:41 -0800836 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800837 except TypeError:
838 main.log.exception( self.name + ": Object not as expected" )
839 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400840 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800841 main.log.error( self.name + ": EOF exception found" )
842 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700843 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800844 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800845 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700846 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -0800847
jenkins7ead5a82015-03-13 10:28:21 -0700848 def deviceRemove( self, deviceId ):
849 """
850 Removes particular device from storage
851
852 TODO: refactor this function
853 """
854 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700855 cmdStr = "device-remove " + str( deviceId )
856 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800857 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800858 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700859 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700860 main.log.error( self.name + ": Error in removing device" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700861 main.log.error( handle )
862 return main.FALSE
863 else:
864 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800865 except AssertionError:
866 main.log.exception( "" )
867 return None
jenkins7ead5a82015-03-13 10:28:21 -0700868 except TypeError:
869 main.log.exception( self.name + ": Object not as expected" )
870 return None
871 except pexpect.EOF:
872 main.log.error( self.name + ": EOF exception found" )
873 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700874 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700875 except Exception:
876 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700877 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700878
You Wang3b9689a2018-08-30 12:24:00 -0700879 def devices( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -0800880 """
Jon Hall7b02d952014-10-17 20:14:54 -0400881 Lists all infrastructure devices or switches
andrewonlab86dc3082014-10-13 18:18:38 -0400882 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800883 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800884 """
andrewonlab86dc3082014-10-13 18:18:38 -0400885 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700886 cmdStr = "devices"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800887 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700888 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -0700889 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -0800890 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800891 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700892 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800893 except AssertionError:
894 main.log.exception( "" )
895 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800896 except TypeError:
897 main.log.exception( self.name + ": Object not as expected" )
898 return None
andrewonlab7c211572014-10-15 16:45:20 -0400899 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800900 main.log.error( self.name + ": EOF exception found" )
901 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700902 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800903 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800904 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700905 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400906
kelvin-onlabd3b64892015-01-20 13:26:24 -0800907 def balanceMasters( self ):
kelvin8ec71442015-01-15 16:57:00 -0800908 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800909 This balances the devices across all controllers
910 by issuing command: 'onos> onos:balance-masters'
911 If required this could be extended to return devices balanced output.
kelvin8ec71442015-01-15 16:57:00 -0800912 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800913 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800914 cmdStr = "onos:balance-masters"
Jon Hallc6358dd2015-04-10 12:44:28 -0700915 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800916 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800917 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700918 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700919 main.log.error( self.name + ": Error in balancing masters" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700920 main.log.error( handle )
921 return main.FALSE
922 else:
923 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800924 except AssertionError:
925 main.log.exception( "" )
926 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800927 except TypeError:
928 main.log.exception( self.name + ": Object not as expected" )
929 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800930 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800931 main.log.error( self.name + ": EOF exception found" )
932 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700933 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800934 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800935 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700936 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800937
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000938 def checkMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700939 """
940 Returns the output of the masters command.
941 Optional argument:
942 * jsonFormat - boolean indicating if you want output in json
943 """
944 try:
945 cmdStr = "onos:masters"
946 if jsonFormat:
947 cmdStr += " -j"
948 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700949 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800950 assert "Command not found:" not in output, output
acsmars24950022015-07-30 18:00:43 -0700951 return output
Jon Hallc6793552016-01-19 14:18:37 -0800952 except AssertionError:
953 main.log.exception( "" )
954 return None
acsmars24950022015-07-30 18:00:43 -0700955 except TypeError:
956 main.log.exception( self.name + ": Object not as expected" )
957 return None
958 except pexpect.EOF:
959 main.log.error( self.name + ": EOF exception found" )
960 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700961 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700962 except Exception:
963 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700964 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700965
Jon Hallc6793552016-01-19 14:18:37 -0800966 def checkBalanceMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700967 """
968 Uses the master command to check that the devices' leadership
969 is evenly divided
970
971 Dependencies: checkMasters() and summary()
972
Jon Hall6509dbf2016-06-21 17:01:17 -0700973 Returns main.TRUE if the devices are balanced
974 Returns main.FALSE if the devices are unbalanced
acsmars24950022015-07-30 18:00:43 -0700975 Exits on Exception
976 Returns None on TypeError
977 """
978 try:
Jon Hallc6793552016-01-19 14:18:37 -0800979 summaryOutput = self.summary()
980 totalDevices = json.loads( summaryOutput )[ "devices" ]
981 except ( TypeError, ValueError ):
982 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summaryOutput ) )
983 return None
984 try:
acsmars24950022015-07-30 18:00:43 -0700985 totalOwnedDevices = 0
Jon Hallc6793552016-01-19 14:18:37 -0800986 mastersOutput = self.checkMasters()
987 masters = json.loads( mastersOutput )
acsmars24950022015-07-30 18:00:43 -0700988 first = masters[ 0 ][ "size" ]
989 for master in masters:
990 totalOwnedDevices += master[ "size" ]
991 if master[ "size" ] > first + 1 or master[ "size" ] < first - 1:
992 main.log.error( "Mastership not balanced" )
993 main.log.info( "\n" + self.checkMasters( False ) )
994 return main.FALSE
Jon Halle0f0b342017-04-18 11:43:47 -0700995 main.log.info( "Mastership balanced between " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700996 str( len( masters ) ) + " masters" )
acsmars24950022015-07-30 18:00:43 -0700997 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800998 except ( TypeError, ValueError ):
999 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, mastersOutput ) )
acsmars24950022015-07-30 18:00:43 -07001000 return None
1001 except pexpect.EOF:
1002 main.log.error( self.name + ": EOF exception found" )
1003 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001004 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -07001005 except Exception:
1006 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001007 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -07001008
YPZhangfebf7302016-05-24 16:45:56 -07001009 def links( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -08001010 """
Jon Halle8217482014-10-17 13:49:14 -04001011 Lists all core links
1012 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001013 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001014 """
Jon Halle8217482014-10-17 13:49:14 -04001015 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001016 cmdStr = "links"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001017 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001018 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07001019 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001020 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001021 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001022 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001023 except AssertionError:
1024 main.log.exception( "" )
1025 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001026 except TypeError:
1027 main.log.exception( self.name + ": Object not as expected" )
1028 return None
Jon Halle8217482014-10-17 13:49:14 -04001029 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001030 main.log.error( self.name + ": EOF exception found" )
1031 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001032 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001033 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001034 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001035 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001036
You Wang3b9689a2018-08-30 12:24:00 -07001037 def ports( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -08001038 """
Jon Halle8217482014-10-17 13:49:14 -04001039 Lists all ports
1040 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001041 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001042 """
Jon Halle8217482014-10-17 13:49:14 -04001043 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001044 cmdStr = "ports"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001045 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001046 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -07001047 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001048 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001049 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001050 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001051 except AssertionError:
1052 main.log.exception( "" )
1053 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001054 except TypeError:
1055 main.log.exception( self.name + ": Object not as expected" )
1056 return None
Jon Halle8217482014-10-17 13:49:14 -04001057 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001058 main.log.error( self.name + ": EOF exception found" )
1059 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001060 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001061 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001062 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001063 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001064
kelvin-onlabd3b64892015-01-20 13:26:24 -08001065 def roles( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001066 """
Jon Hall983a1702014-10-28 18:44:22 -04001067 Lists all devices and the controllers with roles assigned to them
1068 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001069 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001070 """
andrewonlab7c211572014-10-15 16:45:20 -04001071 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001072 cmdStr = "roles"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001073 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001074 cmdStr += " -j"
1075 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001076 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001077 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001078 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001079 except AssertionError:
1080 main.log.exception( "" )
1081 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001082 except TypeError:
1083 main.log.exception( self.name + ": Object not as expected" )
1084 return None
Jon Hall983a1702014-10-28 18:44:22 -04001085 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001086 main.log.error( self.name + ": EOF exception found" )
1087 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001088 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001089 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001090 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001091 main.cleanAndExit()
Jon Hall983a1702014-10-28 18:44:22 -04001092
kelvin-onlabd3b64892015-01-20 13:26:24 -08001093 def getRole( self, deviceId ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001094 """
Jon Halle3f39ff2015-01-13 11:50:53 -08001095 Given the a string containing the json representation of the "roles"
1096 cli command and a partial or whole device id, returns a json object
1097 containing the roles output for the first device whose id contains
1098 "device_id"
Jon Hall983a1702014-10-28 18:44:22 -04001099
1100 Returns:
Jon Halle3f39ff2015-01-13 11:50:53 -08001101 A dict of the role assignments for the given device or
1102 None if no match
kelvin8ec71442015-01-15 16:57:00 -08001103 """
Jon Hall983a1702014-10-28 18:44:22 -04001104 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001105 if deviceId is None:
Jon Hall983a1702014-10-28 18:44:22 -04001106 return None
1107 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001108 rawRoles = self.roles()
1109 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001110 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001111 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001112 # print device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001113 if str( deviceId ) in device[ 'id' ]:
Jon Hall983a1702014-10-28 18:44:22 -04001114 return device
1115 return None
Jon Hallc6793552016-01-19 14:18:37 -08001116 except ( TypeError, ValueError ):
1117 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001118 return None
andrewonlab86dc3082014-10-13 18:18:38 -04001119 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001120 main.log.error( self.name + ": EOF exception found" )
1121 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001122 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001123 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001124 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001125 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001126
kelvin-onlabd3b64892015-01-20 13:26:24 -08001127 def rolesNotNull( self ):
kelvin8ec71442015-01-15 16:57:00 -08001128 """
Jon Hall94fd0472014-12-08 11:52:42 -08001129 Iterates through each device and checks if there is a master assigned
1130 Returns: main.TRUE if each device has a master
1131 main.FALSE any device has no master
kelvin8ec71442015-01-15 16:57:00 -08001132 """
Jon Hall94fd0472014-12-08 11:52:42 -08001133 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001134 rawRoles = self.roles()
1135 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001136 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001137 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001138 # print device
1139 if device[ 'master' ] == "none":
1140 main.log.warn( "Device has no master: " + str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08001141 return main.FALSE
1142 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08001143 except ( TypeError, ValueError ):
1144 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001145 return None
Jon Hall94fd0472014-12-08 11:52:42 -08001146 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001147 main.log.error( self.name + ": EOF exception found" )
1148 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001149 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001150 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001151 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001152 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001153
kelvin-onlabd3b64892015-01-20 13:26:24 -08001154 def paths( self, srcId, dstId ):
kelvin8ec71442015-01-15 16:57:00 -08001155 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001156 Returns string of paths, and the cost.
1157 Issues command: onos:paths <src> <dst>
kelvin8ec71442015-01-15 16:57:00 -08001158 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001159 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001160 cmdStr = "onos:paths " + str( srcId ) + " " + str( dstId )
1161 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001162 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001163 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08001164 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001165 main.log.error( self.name + ": Error in getting paths" )
kelvin8ec71442015-01-15 16:57:00 -08001166 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001167 else:
kelvin8ec71442015-01-15 16:57:00 -08001168 path = handle.split( ";" )[ 0 ]
1169 cost = handle.split( ";" )[ 1 ]
1170 return ( path, cost )
Jon Hallc6793552016-01-19 14:18:37 -08001171 except AssertionError:
1172 main.log.exception( "" )
1173 return ( handle, "Error" )
Jon Halld4d4b372015-01-28 16:02:41 -08001174 except TypeError:
1175 main.log.exception( self.name + ": Object not as expected" )
1176 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001177 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001178 main.log.error( self.name + ": EOF exception found" )
1179 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001180 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001181 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001182 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001183 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -08001184
kelvin-onlabd3b64892015-01-20 13:26:24 -08001185 def hosts( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001186 """
Jon Hallffb386d2014-11-21 13:43:38 -08001187 Lists all discovered hosts
Jon Hall42db6dc2014-10-24 19:03:48 -04001188 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001189 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001190 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001191 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001192 cmdStr = "hosts"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001193 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001194 cmdStr += " -j"
1195 handle = self.sendline( cmdStr )
Jeremyd9e4eb12016-04-13 12:09:06 -07001196 if handle:
1197 assert "Command not found:" not in handle, handle
Jon Hallbaf53162015-12-17 17:04:34 -08001198 # TODO: Maybe make this less hardcoded
1199 # ConsistentMap Exceptions
1200 assert "org.onosproject.store.service" not in handle
1201 # Node not leader
1202 assert "java.lang.IllegalStateException" not in handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001203 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001204 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07001205 main.log.exception( self.name + ": Error in processing '" + cmdStr + "' " +
Jeremy Songster6949cea2016-04-19 18:13:18 -07001206 "command: " + str( handle ) )
Jon Hallc6793552016-01-19 14:18:37 -08001207 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001208 except TypeError:
1209 main.log.exception( self.name + ": Object not as expected" )
1210 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001211 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001212 main.log.error( self.name + ": EOF exception found" )
1213 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001214 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001215 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001216 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001217 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001218
kelvin-onlabd3b64892015-01-20 13:26:24 -08001219 def getHost( self, mac ):
kelvin8ec71442015-01-15 16:57:00 -08001220 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001221 Return the first host from the hosts api whose 'id' contains 'mac'
Jon Halle3f39ff2015-01-13 11:50:53 -08001222
Jon Hallefbd9792015-03-05 16:11:36 -08001223 Note: mac must be a colon separated mac address, but could be a
Jon Halle3f39ff2015-01-13 11:50:53 -08001224 partial mac address
1225
Jon Hall42db6dc2014-10-24 19:03:48 -04001226 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08001227 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001228 try:
kelvin8ec71442015-01-15 16:57:00 -08001229 if mac is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04001230 return None
1231 else:
1232 mac = mac
kelvin-onlabd3b64892015-01-20 13:26:24 -08001233 rawHosts = self.hosts()
1234 hostsJson = json.loads( rawHosts )
kelvin8ec71442015-01-15 16:57:00 -08001235 # search json for the host with mac then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001236 for host in hostsJson:
kelvin8ec71442015-01-15 16:57:00 -08001237 # print "%s in %s?" % ( mac, host[ 'id' ] )
Jon Halld4d4b372015-01-28 16:02:41 -08001238 if not host:
1239 pass
1240 elif mac in host[ 'id' ]:
Jon Hall42db6dc2014-10-24 19:03:48 -04001241 return host
1242 return None
Jon Hallc6793552016-01-19 14:18:37 -08001243 except ( TypeError, ValueError ):
1244 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawHosts ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001245 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001246 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001247 main.log.error( self.name + ": EOF exception found" )
1248 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001249 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001250 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001251 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001252 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001253
kelvin-onlabd3b64892015-01-20 13:26:24 -08001254 def getHostsId( self, hostList ):
kelvin8ec71442015-01-15 16:57:00 -08001255 """
1256 Obtain list of hosts
andrewonlab3f0a4af2014-10-17 12:25:14 -04001257 Issues command: 'onos> hosts'
kelvin8ec71442015-01-15 16:57:00 -08001258
andrewonlab3f0a4af2014-10-17 12:25:14 -04001259 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001260 * hostList: List of hosts obtained by Mininet
andrewonlab3f0a4af2014-10-17 12:25:14 -04001261 IMPORTANT:
1262 This function assumes that you started your
kelvin8ec71442015-01-15 16:57:00 -08001263 topology with the option '--mac'.
andrewonlab3f0a4af2014-10-17 12:25:14 -04001264 Furthermore, it assumes that value of VLAN is '-1'
1265 Description:
kelvin8ec71442015-01-15 16:57:00 -08001266 Converts mininet hosts ( h1, h2, h3... ) into
1267 ONOS format ( 00:00:00:00:00:01/-1 , ... )
1268 """
andrewonlab3f0a4af2014-10-17 12:25:14 -04001269 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001270 onosHostList = []
andrewonlab3f0a4af2014-10-17 12:25:14 -04001271
kelvin-onlabd3b64892015-01-20 13:26:24 -08001272 for host in hostList:
kelvin8ec71442015-01-15 16:57:00 -08001273 host = host.replace( "h", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001274 hostHex = hex( int( host ) ).zfill( 12 )
1275 hostHex = str( hostHex ).replace( 'x', '0' )
1276 i = iter( str( hostHex ) )
1277 hostHex = ":".join( a + b for a, b in zip( i, i ) )
1278 hostHex = hostHex + "/-1"
1279 onosHostList.append( hostHex )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001280
kelvin-onlabd3b64892015-01-20 13:26:24 -08001281 return onosHostList
andrewonlab3f0a4af2014-10-17 12:25:14 -04001282
Jon Halld4d4b372015-01-28 16:02:41 -08001283 except TypeError:
1284 main.log.exception( self.name + ": Object not as expected" )
1285 return None
andrewonlab3f0a4af2014-10-17 12:25:14 -04001286 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001287 main.log.error( self.name + ": EOF exception found" )
1288 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001289 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001290 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001291 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001292 main.cleanAndExit()
andrewonlab3e15ead2014-10-15 14:21:34 -04001293
You Wangbc898b82018-05-03 16:22:34 -07001294 def verifyHostLocation( self, hostIp, location ):
1295 """
1296 Description:
1297 Verify the host given is discovered in all locations expected
1298 Required:
1299 hostIp: IP address of the host
1300 location: expected location(s) of the given host. ex. "of:0000000000000005/8"
1301 Could be a string or list
1302 Returns:
1303 main.TRUE if host is discovered on all locations provided
1304 main.FALSE otherwise
1305 """
You Wangbc898b82018-05-03 16:22:34 -07001306 locations = [ location ] if isinstance( location, str ) else location
1307 assert isinstance( locations, list ), "Wrong type of location: {}".format( type( location ) )
1308 try:
1309 hosts = self.hosts()
1310 hosts = json.loads( hosts )
1311 targetHost = None
1312 for host in hosts:
1313 if hostIp in host[ "ipAddresses" ]:
1314 targetHost = host
You Wangfd80ab42018-05-10 17:21:53 -07001315 assert targetHost, "Not able to find host with IP {}".format( hostIp )
You Wangbc898b82018-05-03 16:22:34 -07001316 result = main.TRUE
1317 locationsDiscovered = [ loc[ "elementId" ] + "/" + loc[ "port" ] for loc in targetHost[ "locations" ] ]
1318 for loc in locations:
1319 discovered = False
1320 for locDiscovered in locationsDiscovered:
You Wang547893e2018-05-08 13:34:59 -07001321 locToMatch = locDiscovered if "/" in loc else locDiscovered.split( "/" )[0]
1322 if loc == locToMatch:
You Wangbc898b82018-05-03 16:22:34 -07001323 main.log.debug( "Host {} discovered with location {}".format( hostIp, loc ) )
You Wang547893e2018-05-08 13:34:59 -07001324 discovered = True
You Wangbc898b82018-05-03 16:22:34 -07001325 break
1326 if discovered:
1327 locationsDiscovered.remove( locDiscovered )
1328 else:
1329 main.log.warn( "Host {} not discovered with location {}".format( hostIp, loc ) )
1330 result = main.FALSE
1331 if locationsDiscovered:
1332 main.log.warn( "Host {} is also discovered with location {}".format( hostIp, locationsDiscovered ) )
1333 result = main.FALSE
1334 return result
1335 except KeyError:
1336 main.log.exception( self.name + ": host data not as expected: " + hosts )
1337 return None
1338 except pexpect.EOF:
1339 main.log.error( self.name + ": EOF exception found" )
1340 main.log.error( self.name + ": " + self.handle.before )
1341 main.cleanAndExit()
1342 except Exception:
1343 main.log.exception( self.name + ": Uncaught exception" )
1344 return None
1345
You Wang53dba1e2018-02-02 17:45:44 -08001346 def verifyHostIp( self, hostList=[], prefix="" ):
1347 """
1348 Description:
1349 Verify that all hosts have IP address assigned to them
1350 Optional:
1351 hostList: If specified, verifications only happen to the hosts
1352 in hostList
1353 prefix: at least one of the ip address assigned to the host
1354 needs to have the specified prefix
1355 Returns:
1356 main.TRUE if all hosts have specific IP address assigned;
1357 main.FALSE otherwise
1358 """
You Wang53dba1e2018-02-02 17:45:44 -08001359 try:
1360 hosts = self.hosts()
1361 hosts = json.loads( hosts )
1362 if not hostList:
1363 hostList = [ host[ "id" ] for host in hosts ]
1364 for host in hosts:
1365 hostId = host[ "id" ]
1366 if hostId not in hostList:
1367 continue
1368 ipList = host[ "ipAddresses" ]
1369 main.log.debug( self.name + ": IP list on host " + str( hostId ) + ": " + str( ipList ) )
1370 if not ipList:
1371 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostId ) )
1372 else:
1373 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
1374 main.log.warn( self.name + ": None of the IPs on host " + str( hostId ) + " has prefix " + str( prefix ) )
1375 else:
1376 main.log.debug( self.name + ": Found matching IP on host " + str( hostId ) )
1377 hostList.remove( hostId )
1378 if hostList:
1379 main.log.warn( self.name + ": failed to verify IP on following hosts: " + str( hostList) )
Jon Hall43060f62020-06-23 13:13:33 -07001380 # Print info for debugging
1381 main.log.debug( self.name + ": hosts output: " + str( hosts ) )
You Wang53dba1e2018-02-02 17:45:44 -08001382 return main.FALSE
1383 else:
1384 return main.TRUE
1385 except KeyError:
1386 main.log.exception( self.name + ": host data not as expected: " + hosts )
1387 return None
1388 except pexpect.EOF:
1389 main.log.error( self.name + ": EOF exception found" )
1390 main.log.error( self.name + ": " + self.handle.before )
1391 main.cleanAndExit()
1392 except Exception:
1393 main.log.exception( self.name + ": Uncaught exception" )
1394 return None
1395
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001396 def addHostIntent( self, hostIdOne, hostIdTwo, vlanId="", setVlan="", encap="", bandwidth="" ):
kelvin8ec71442015-01-15 16:57:00 -08001397 """
andrewonlabe6745342014-10-17 14:29:13 -04001398 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001399 * hostIdOne: ONOS host id for host1
1400 * hostIdTwo: ONOS host id for host2
Jeremy Songster832f9e92016-05-05 14:30:49 -07001401 Optional:
1402 * vlanId: specify a VLAN id for the intent
Jeremy Songsterff553672016-05-12 17:06:23 -07001403 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001404 * encap: specify an encapsulation type
andrewonlabe6745342014-10-17 14:29:13 -04001405 Description:
Jon Hallefbd9792015-03-05 16:11:36 -08001406 Adds a host-to-host intent ( bidirectional ) by
Jon Hallb1290e82014-11-18 16:17:48 -05001407 specifying the two hosts.
kelvin-onlabfb521662015-02-27 09:52:40 -08001408 Returns:
1409 A string of the intent id or None on Error
kelvin8ec71442015-01-15 16:57:00 -08001410 """
andrewonlabe6745342014-10-17 14:29:13 -04001411 try:
Jeremy Songster832f9e92016-05-05 14:30:49 -07001412 cmdStr = "add-host-intent "
1413 if vlanId:
1414 cmdStr += "-v " + str( vlanId ) + " "
Jeremy Songsterff553672016-05-12 17:06:23 -07001415 if setVlan:
1416 cmdStr += "--setVlan " + str( vlanId ) + " "
Jeremy Songsterc032f162016-08-04 17:14:49 -07001417 if encap:
1418 cmdStr += "--encapsulation " + str( encap ) + " "
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001419 if bandwidth:
1420 cmdStr += "-b " + str( bandwidth ) + " "
Jeremy Songster832f9e92016-05-05 14:30:49 -07001421 cmdStr += str( hostIdOne ) + " " + str( hostIdTwo )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001422 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001423 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001424 assert "Command not found:" not in handle, handle
Hari Krishnaac4e1782015-01-26 12:09:12 -08001425 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001426 main.log.error( self.name + ": Error in adding Host intent" )
Jon Hall61282e32015-03-19 11:34:11 -07001427 main.log.debug( "Response from ONOS was: " + repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001428 return None
Hari Krishnaac4e1782015-01-26 12:09:12 -08001429 else:
1430 main.log.info( "Host intent installed between " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001431 str( hostIdOne ) + " and " + str( hostIdTwo ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001432 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001433 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001434 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001435 else:
1436 main.log.error( "Error, intent ID not found" )
Jon Hall61282e32015-03-19 11:34:11 -07001437 main.log.debug( "Response from ONOS was: " +
1438 repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001439 return None
Jon Hallc6793552016-01-19 14:18:37 -08001440 except AssertionError:
1441 main.log.exception( "" )
1442 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001443 except TypeError:
1444 main.log.exception( self.name + ": Object not as expected" )
1445 return None
andrewonlabe6745342014-10-17 14:29:13 -04001446 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001447 main.log.error( self.name + ": EOF exception found" )
1448 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001449 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001450 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001451 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001452 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04001453
kelvin-onlabd3b64892015-01-20 13:26:24 -08001454 def addOpticalIntent( self, ingressDevice, egressDevice ):
kelvin8ec71442015-01-15 16:57:00 -08001455 """
andrewonlab7b31d232014-10-24 13:31:47 -04001456 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001457 * ingressDevice: device id of ingress device
1458 * egressDevice: device id of egress device
andrewonlab7b31d232014-10-24 13:31:47 -04001459 Optional:
1460 TODO: Still needs to be implemented via dev side
kelvin-onlabfb521662015-02-27 09:52:40 -08001461 Description:
1462 Adds an optical intent by specifying an ingress and egress device
1463 Returns:
1464 A string of the intent id or None on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08001465 """
andrewonlab7b31d232014-10-24 13:31:47 -04001466 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001467 cmdStr = "add-optical-intent " + str( ingressDevice ) +\
1468 " " + str( egressDevice )
1469 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001470 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001471 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08001472 # If error, return error message
Jon Halle3f39ff2015-01-13 11:50:53 -08001473 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001474 main.log.error( self.name + ": Error in adding Optical intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001475 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001476 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001477 main.log.info( "Optical intent installed between " +
1478 str( ingressDevice ) + " and " +
1479 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001480 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001481 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001482 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001483 else:
1484 main.log.error( "Error, intent ID not found" )
1485 return None
Jon Hallc6793552016-01-19 14:18:37 -08001486 except AssertionError:
1487 main.log.exception( "" )
1488 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001489 except TypeError:
1490 main.log.exception( self.name + ": Object not as expected" )
1491 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001492 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001493 main.log.error( self.name + ": EOF exception found" )
1494 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001495 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001496 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001497 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001498 main.cleanAndExit()
andrewonlab7b31d232014-10-24 13:31:47 -04001499
kelvin-onlabd3b64892015-01-20 13:26:24 -08001500 def addPointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001501 self,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001502 ingressDevice,
1503 egressDevice,
1504 portIngress="",
1505 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001506 ethType="",
1507 ethSrc="",
1508 ethDst="",
1509 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001510 lambdaAlloc=False,
alisonda157272016-12-22 01:13:21 -08001511 protected=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001512 ipProto="",
1513 ipSrc="",
1514 ipDst="",
1515 tcpSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001516 tcpDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001517 vlanId="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001518 setVlan="",
1519 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001520 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001521 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001522 * ingressDevice: device id of ingress device
1523 * egressDevice: device id of egress device
andrewonlab289e4b72014-10-21 21:24:18 -04001524 Optional:
1525 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001526 * ethSrc: specify ethSrc ( i.e. src mac addr )
1527 * ethDst: specify ethDst ( i.e. dst mac addr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001528 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001529 * lambdaAlloc: if True, intent will allocate lambda
andrewonlab40ccd8b2014-11-06 16:23:34 -05001530 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001531 * ipProto: specify ip protocol
andrewonlabf77e0cb2014-11-11 17:17:59 -05001532 * ipSrc: specify ip source address
1533 * ipDst: specify ip destination address
1534 * tcpSrc: specify tcp source port
1535 * tcpDst: specify tcp destination port
Jeremy Songster832f9e92016-05-05 14:30:49 -07001536 * vlanId: specify vlan ID
Jeremy Songsterff553672016-05-12 17:06:23 -07001537 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001538 * encap: specify an Encapsulation type to use
andrewonlab4dbb4d82014-10-17 18:22:31 -04001539 Description:
kelvin8ec71442015-01-15 16:57:00 -08001540 Adds a point-to-point intent ( uni-directional ) by
andrewonlab289e4b72014-10-21 21:24:18 -04001541 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001542 Returns:
1543 A string of the intent id or None on error
andrewonlab289e4b72014-10-21 21:24:18 -04001544
Jon Halle3f39ff2015-01-13 11:50:53 -08001545 NOTE: This function may change depending on the
andrewonlab4dbb4d82014-10-17 18:22:31 -04001546 options developers provide for point-to-point
1547 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001548 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001549 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001550 cmd = "add-point-intent"
andrewonlab36af3822014-11-18 17:48:18 -05001551
Jeremy Songsterff553672016-05-12 17:06:23 -07001552 if ethType:
1553 cmd += " --ethType " + str( ethType )
1554 if ethSrc:
1555 cmd += " --ethSrc " + str( ethSrc )
1556 if ethDst:
1557 cmd += " --ethDst " + str( ethDst )
1558 if bandwidth:
1559 cmd += " --bandwidth " + str( bandwidth )
1560 if lambdaAlloc:
1561 cmd += " --lambda "
1562 if ipProto:
1563 cmd += " --ipProto " + str( ipProto )
1564 if ipSrc:
1565 cmd += " --ipSrc " + str( ipSrc )
1566 if ipDst:
1567 cmd += " --ipDst " + str( ipDst )
1568 if tcpSrc:
1569 cmd += " --tcpSrc " + str( tcpSrc )
1570 if tcpDst:
1571 cmd += " --tcpDst " + str( tcpDst )
1572 if vlanId:
1573 cmd += " -v " + str( vlanId )
1574 if setVlan:
1575 cmd += " --setVlan " + str( setVlan )
Jeremy Songsterc032f162016-08-04 17:14:49 -07001576 if encap:
1577 cmd += " --encapsulation " + str( encap )
alisonda157272016-12-22 01:13:21 -08001578 if protected:
1579 cmd += " --protect "
andrewonlab289e4b72014-10-21 21:24:18 -04001580
kelvin8ec71442015-01-15 16:57:00 -08001581 # Check whether the user appended the port
1582 # or provided it as an input
kelvin-onlabd3b64892015-01-20 13:26:24 -08001583 if "/" in ingressDevice:
1584 cmd += " " + str( ingressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001585 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001586 if not portIngress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001587 main.log.error( "You must specify the ingress port" )
kelvin8ec71442015-01-15 16:57:00 -08001588 # TODO: perhaps more meaningful return
kelvin-onlabfb521662015-02-27 09:52:40 -08001589 # Would it make sense to throw an exception and exit
1590 # the test?
1591 return None
andrewonlab36af3822014-11-18 17:48:18 -05001592
kelvin8ec71442015-01-15 16:57:00 -08001593 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001594 str( ingressDevice ) + "/" +\
1595 str( portIngress ) + " "
andrewonlab36af3822014-11-18 17:48:18 -05001596
kelvin-onlabd3b64892015-01-20 13:26:24 -08001597 if "/" in egressDevice:
1598 cmd += " " + str( egressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001599 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001600 if not portEgress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001601 main.log.error( "You must specify the egress port" )
1602 return None
Jon Halle3f39ff2015-01-13 11:50:53 -08001603
kelvin8ec71442015-01-15 16:57:00 -08001604 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001605 str( egressDevice ) + "/" +\
1606 str( portEgress )
kelvin8ec71442015-01-15 16:57:00 -08001607
kelvin-onlab898a6c62015-01-16 14:13:53 -08001608 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001609 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001610 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001611 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001612 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001613 main.log.error( self.name + ": Error in adding point-to-point intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001614 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001615 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001616 # TODO: print out all the options in this message?
1617 main.log.info( "Point-to-point intent installed between " +
1618 str( ingressDevice ) + " and " +
1619 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001620 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001621 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001622 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001623 else:
1624 main.log.error( "Error, intent ID not found" )
1625 return None
Jon Hallc6793552016-01-19 14:18:37 -08001626 except AssertionError:
1627 main.log.exception( "" )
1628 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001629 except TypeError:
1630 main.log.exception( self.name + ": Object not as expected" )
1631 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001632 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001633 main.log.error( self.name + ": EOF exception found" )
1634 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001635 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001636 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001637 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001638 main.cleanAndExit()
andrewonlab4dbb4d82014-10-17 18:22:31 -04001639
kelvin-onlabd3b64892015-01-20 13:26:24 -08001640 def addMultipointToSinglepointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001641 self,
shahshreyac2f97072015-03-19 17:04:29 -07001642 ingressDeviceList,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001643 egressDevice,
shahshreyac2f97072015-03-19 17:04:29 -07001644 portIngressList=None,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001645 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001646 ethType="",
1647 ethSrc="",
1648 ethDst="",
1649 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001650 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001651 ipProto="",
1652 ipSrc="",
1653 ipDst="",
1654 tcpSrc="",
1655 tcpDst="",
1656 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001657 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001658 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001659 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001660 partial=False,
1661 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001662 """
shahshreyad0c80432014-12-04 16:56:05 -08001663 Note:
shahshreya70622b12015-03-19 17:19:00 -07001664 This function assumes the format of all ingress devices
Jon Hallbe379602015-03-24 13:39:32 -07001665 is same. That is, all ingress devices include port numbers
1666 with a "/" or all ingress devices could specify device
1667 ids and port numbers seperately.
shahshreyad0c80432014-12-04 16:56:05 -08001668 Required:
Jon Hallbe379602015-03-24 13:39:32 -07001669 * ingressDeviceList: List of device ids of ingress device
shahshreyac2f97072015-03-19 17:04:29 -07001670 ( Atleast 2 ingress devices required in the list )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001671 * egressDevice: device id of egress device
shahshreyad0c80432014-12-04 16:56:05 -08001672 Optional:
1673 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001674 * ethSrc: specify ethSrc ( i.e. src mac addr )
1675 * ethDst: specify ethDst ( i.e. dst mac addr )
shahshreyad0c80432014-12-04 16:56:05 -08001676 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001677 * lambdaAlloc: if True, intent will allocate lambda
shahshreyad0c80432014-12-04 16:56:05 -08001678 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001679 * ipProto: specify ip protocol
shahshreyad0c80432014-12-04 16:56:05 -08001680 * ipSrc: specify ip source address
1681 * ipDst: specify ip destination address
1682 * tcpSrc: specify tcp source port
1683 * tcpDst: specify tcp destination port
1684 * setEthSrc: action to Rewrite Source MAC Address
1685 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001686 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001687 * setVlan: specify VLAN Id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001688 * encap: specify a type of encapsulation
shahshreyad0c80432014-12-04 16:56:05 -08001689 Description:
kelvin8ec71442015-01-15 16:57:00 -08001690 Adds a multipoint-to-singlepoint intent ( uni-directional ) by
shahshreyad0c80432014-12-04 16:56:05 -08001691 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001692 Returns:
1693 A string of the intent id or None on error
shahshreyad0c80432014-12-04 16:56:05 -08001694
Jon Halle3f39ff2015-01-13 11:50:53 -08001695 NOTE: This function may change depending on the
Jon Hallefbd9792015-03-05 16:11:36 -08001696 options developers provide for multipoint-to-singlepoint
shahshreyad0c80432014-12-04 16:56:05 -08001697 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001698 """
shahshreyad0c80432014-12-04 16:56:05 -08001699 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001700 cmd = "add-multi-to-single-intent"
shahshreyad0c80432014-12-04 16:56:05 -08001701
Jeremy Songsterff553672016-05-12 17:06:23 -07001702 if ethType:
1703 cmd += " --ethType " + str( ethType )
1704 if ethSrc:
1705 cmd += " --ethSrc " + str( ethSrc )
1706 if ethDst:
1707 cmd += " --ethDst " + str( ethDst )
1708 if bandwidth:
1709 cmd += " --bandwidth " + str( bandwidth )
1710 if lambdaAlloc:
1711 cmd += " --lambda "
1712 if ipProto:
1713 cmd += " --ipProto " + str( ipProto )
1714 if ipSrc:
1715 cmd += " --ipSrc " + str( ipSrc )
1716 if ipDst:
1717 cmd += " --ipDst " + str( ipDst )
1718 if tcpSrc:
1719 cmd += " --tcpSrc " + str( tcpSrc )
1720 if tcpDst:
1721 cmd += " --tcpDst " + str( tcpDst )
1722 if setEthSrc:
1723 cmd += " --setEthSrc " + str( setEthSrc )
1724 if setEthDst:
1725 cmd += " --setEthDst " + str( setEthDst )
1726 if vlanId:
1727 cmd += " -v " + str( vlanId )
1728 if setVlan:
1729 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001730 if partial:
1731 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001732 if encap:
1733 cmd += " --encapsulation " + str( encap )
shahshreyad0c80432014-12-04 16:56:05 -08001734
kelvin8ec71442015-01-15 16:57:00 -08001735 # Check whether the user appended the port
1736 # or provided it as an input
shahshreyac2f97072015-03-19 17:04:29 -07001737
1738 if portIngressList is None:
1739 for ingressDevice in ingressDeviceList:
1740 if "/" in ingressDevice:
1741 cmd += " " + str( ingressDevice )
1742 else:
1743 main.log.error( "You must specify " +
Jon Hallbe379602015-03-24 13:39:32 -07001744 "the ingress port" )
shahshreyac2f97072015-03-19 17:04:29 -07001745 # TODO: perhaps more meaningful return
1746 return main.FALSE
shahshreyad0c80432014-12-04 16:56:05 -08001747 else:
Jon Hall71ce4e72015-03-23 14:05:58 -07001748 if len( ingressDeviceList ) == len( portIngressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001749 for ingressDevice, portIngress in zip( ingressDeviceList,
1750 portIngressList ):
shahshreya70622b12015-03-19 17:19:00 -07001751 cmd += " " + \
1752 str( ingressDevice ) + "/" +\
1753 str( portIngress ) + " "
kelvin-onlab38143812015-04-01 15:03:01 -07001754 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001755 main.log.error( "Device list and port list does not " +
1756 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001757 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001758 if "/" in egressDevice:
1759 cmd += " " + str( egressDevice )
shahshreyad0c80432014-12-04 16:56:05 -08001760 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001761 if not portEgress:
kelvin8ec71442015-01-15 16:57:00 -08001762 main.log.error( "You must specify " +
1763 "the egress port" )
shahshreyad0c80432014-12-04 16:56:05 -08001764 return main.FALSE
Jon Halle3f39ff2015-01-13 11:50:53 -08001765
kelvin8ec71442015-01-15 16:57:00 -08001766 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001767 str( egressDevice ) + "/" +\
1768 str( portEgress )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001769 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001770 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001771 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001772 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001773 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001774 main.log.error( self.name + ": Error in adding multipoint-to-singlepoint " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001775 "intent" )
1776 return None
shahshreyad0c80432014-12-04 16:56:05 -08001777 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001778 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001779 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001780 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001781 else:
1782 main.log.error( "Error, intent ID not found" )
1783 return None
Jon Hallc6793552016-01-19 14:18:37 -08001784 except AssertionError:
1785 main.log.exception( "" )
1786 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001787 except TypeError:
1788 main.log.exception( self.name + ": Object not as expected" )
1789 return None
1790 except pexpect.EOF:
1791 main.log.error( self.name + ": EOF exception found" )
1792 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001793 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001794 except Exception:
1795 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001796 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001797
1798 def addSinglepointToMultipointIntent(
1799 self,
1800 ingressDevice,
1801 egressDeviceList,
1802 portIngress="",
1803 portEgressList=None,
1804 ethType="",
1805 ethSrc="",
1806 ethDst="",
1807 bandwidth="",
1808 lambdaAlloc=False,
1809 ipProto="",
1810 ipSrc="",
1811 ipDst="",
1812 tcpSrc="",
1813 tcpDst="",
1814 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001815 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001816 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001817 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001818 partial=False,
1819 encap="" ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001820 """
1821 Note:
1822 This function assumes the format of all egress devices
1823 is same. That is, all egress devices include port numbers
1824 with a "/" or all egress devices could specify device
1825 ids and port numbers seperately.
1826 Required:
1827 * EgressDeviceList: List of device ids of egress device
1828 ( Atleast 2 eress devices required in the list )
1829 * ingressDevice: device id of ingress device
1830 Optional:
1831 * ethType: specify ethType
1832 * ethSrc: specify ethSrc ( i.e. src mac addr )
1833 * ethDst: specify ethDst ( i.e. dst mac addr )
1834 * bandwidth: specify bandwidth capacity of link
1835 * lambdaAlloc: if True, intent will allocate lambda
1836 for the specified intent
1837 * ipProto: specify ip protocol
1838 * ipSrc: specify ip source address
1839 * ipDst: specify ip destination address
1840 * tcpSrc: specify tcp source port
1841 * tcpDst: specify tcp destination port
1842 * setEthSrc: action to Rewrite Source MAC Address
1843 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001844 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001845 * setVlan: specify VLAN ID treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001846 * encap: specify an encapsulation type
kelvin-onlabb9408212015-04-01 13:34:04 -07001847 Description:
1848 Adds a singlepoint-to-multipoint intent ( uni-directional ) by
1849 specifying device id's and optional fields
1850 Returns:
1851 A string of the intent id or None on error
1852
1853 NOTE: This function may change depending on the
1854 options developers provide for singlepoint-to-multipoint
1855 intent via cli
1856 """
1857 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001858 cmd = "add-single-to-multi-intent"
kelvin-onlabb9408212015-04-01 13:34:04 -07001859
Jeremy Songsterff553672016-05-12 17:06:23 -07001860 if ethType:
1861 cmd += " --ethType " + str( ethType )
1862 if ethSrc:
1863 cmd += " --ethSrc " + str( ethSrc )
1864 if ethDst:
1865 cmd += " --ethDst " + str( ethDst )
1866 if bandwidth:
1867 cmd += " --bandwidth " + str( bandwidth )
1868 if lambdaAlloc:
1869 cmd += " --lambda "
1870 if ipProto:
1871 cmd += " --ipProto " + str( ipProto )
1872 if ipSrc:
1873 cmd += " --ipSrc " + str( ipSrc )
1874 if ipDst:
1875 cmd += " --ipDst " + str( ipDst )
1876 if tcpSrc:
1877 cmd += " --tcpSrc " + str( tcpSrc )
1878 if tcpDst:
1879 cmd += " --tcpDst " + str( tcpDst )
1880 if setEthSrc:
1881 cmd += " --setEthSrc " + str( setEthSrc )
1882 if setEthDst:
1883 cmd += " --setEthDst " + str( setEthDst )
1884 if vlanId:
1885 cmd += " -v " + str( vlanId )
1886 if setVlan:
1887 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001888 if partial:
1889 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001890 if encap:
1891 cmd += " --encapsulation " + str( encap )
kelvin-onlabb9408212015-04-01 13:34:04 -07001892
1893 # Check whether the user appended the port
1894 # or provided it as an input
Jon Hall08f61bc2015-04-13 16:00:30 -07001895
kelvin-onlabb9408212015-04-01 13:34:04 -07001896 if "/" in ingressDevice:
1897 cmd += " " + str( ingressDevice )
1898 else:
1899 if not portIngress:
1900 main.log.error( "You must specify " +
1901 "the Ingress port" )
1902 return main.FALSE
1903
1904 cmd += " " +\
1905 str( ingressDevice ) + "/" +\
1906 str( portIngress )
1907
1908 if portEgressList is None:
1909 for egressDevice in egressDeviceList:
1910 if "/" in egressDevice:
1911 cmd += " " + str( egressDevice )
1912 else:
1913 main.log.error( "You must specify " +
1914 "the egress port" )
1915 # TODO: perhaps more meaningful return
1916 return main.FALSE
1917 else:
1918 if len( egressDeviceList ) == len( portEgressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001919 for egressDevice, portEgress in zip( egressDeviceList,
1920 portEgressList ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001921 cmd += " " + \
1922 str( egressDevice ) + "/" +\
1923 str( portEgress )
kelvin-onlab38143812015-04-01 15:03:01 -07001924 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001925 main.log.error( "Device list and port list does not " +
1926 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001927 return main.FALSE
kelvin-onlabb9408212015-04-01 13:34:04 -07001928 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001929 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001930 assert "Command not found:" not in handle, handle
kelvin-onlabb9408212015-04-01 13:34:04 -07001931 # If error, return error message
1932 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001933 main.log.error( self.name + ": Error in adding singlepoint-to-multipoint " +
kelvin-onlabb9408212015-04-01 13:34:04 -07001934 "intent" )
shahshreyac2f97072015-03-19 17:04:29 -07001935 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001936 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001937 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001938 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001939 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001940 else:
1941 main.log.error( "Error, intent ID not found" )
1942 return None
Jon Hallc6793552016-01-19 14:18:37 -08001943 except AssertionError:
1944 main.log.exception( "" )
1945 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001946 except TypeError:
1947 main.log.exception( self.name + ": Object not as expected" )
1948 return None
shahshreyad0c80432014-12-04 16:56:05 -08001949 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001950 main.log.error( self.name + ": EOF exception found" )
1951 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001952 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001953 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001954 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001955 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001956
Hari Krishna9e232602015-04-13 17:29:08 -07001957 def addMplsIntent(
1958 self,
1959 ingressDevice,
1960 egressDevice,
Hari Krishna87a17f12015-04-13 17:42:23 -07001961 ingressPort="",
1962 egressPort="",
Hari Krishna9e232602015-04-13 17:29:08 -07001963 ethType="",
1964 ethSrc="",
1965 ethDst="",
1966 bandwidth="",
1967 lambdaAlloc=False,
1968 ipProto="",
1969 ipSrc="",
1970 ipDst="",
1971 tcpSrc="",
1972 tcpDst="",
Hari Krishna87a17f12015-04-13 17:42:23 -07001973 ingressLabel="",
Hari Krishnadfff6672015-04-13 17:53:27 -07001974 egressLabel="",
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001975 priority="" ):
Hari Krishna9e232602015-04-13 17:29:08 -07001976 """
1977 Required:
1978 * ingressDevice: device id of ingress device
1979 * egressDevice: device id of egress device
1980 Optional:
1981 * ethType: specify ethType
1982 * ethSrc: specify ethSrc ( i.e. src mac addr )
1983 * ethDst: specify ethDst ( i.e. dst mac addr )
1984 * bandwidth: specify bandwidth capacity of link
1985 * lambdaAlloc: if True, intent will allocate lambda
1986 for the specified intent
1987 * ipProto: specify ip protocol
1988 * ipSrc: specify ip source address
1989 * ipDst: specify ip destination address
1990 * tcpSrc: specify tcp source port
1991 * tcpDst: specify tcp destination port
1992 * ingressLabel: Ingress MPLS label
1993 * egressLabel: Egress MPLS label
1994 Description:
1995 Adds MPLS intent by
1996 specifying device id's and optional fields
1997 Returns:
1998 A string of the intent id or None on error
1999
2000 NOTE: This function may change depending on the
2001 options developers provide for MPLS
2002 intent via cli
2003 """
2004 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07002005 cmd = "add-mpls-intent"
Hari Krishna9e232602015-04-13 17:29:08 -07002006
Jeremy Songsterff553672016-05-12 17:06:23 -07002007 if ethType:
2008 cmd += " --ethType " + str( ethType )
2009 if ethSrc:
2010 cmd += " --ethSrc " + str( ethSrc )
2011 if ethDst:
2012 cmd += " --ethDst " + str( ethDst )
2013 if bandwidth:
2014 cmd += " --bandwidth " + str( bandwidth )
2015 if lambdaAlloc:
2016 cmd += " --lambda "
2017 if ipProto:
2018 cmd += " --ipProto " + str( ipProto )
2019 if ipSrc:
2020 cmd += " --ipSrc " + str( ipSrc )
2021 if ipDst:
2022 cmd += " --ipDst " + str( ipDst )
2023 if tcpSrc:
2024 cmd += " --tcpSrc " + str( tcpSrc )
2025 if tcpDst:
2026 cmd += " --tcpDst " + str( tcpDst )
2027 if ingressLabel:
2028 cmd += " --ingressLabel " + str( ingressLabel )
2029 if egressLabel:
2030 cmd += " --egressLabel " + str( egressLabel )
2031 if priority:
2032 cmd += " --priority " + str( priority )
Hari Krishna9e232602015-04-13 17:29:08 -07002033
2034 # Check whether the user appended the port
2035 # or provided it as an input
2036 if "/" in ingressDevice:
2037 cmd += " " + str( ingressDevice )
2038 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002039 if not ingressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002040 main.log.error( "You must specify the ingress port" )
2041 return None
2042
2043 cmd += " " + \
2044 str( ingressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002045 str( ingressPort ) + " "
Hari Krishna9e232602015-04-13 17:29:08 -07002046
2047 if "/" in egressDevice:
2048 cmd += " " + str( egressDevice )
2049 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002050 if not egressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002051 main.log.error( "You must specify the egress port" )
2052 return None
2053
2054 cmd += " " +\
2055 str( egressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002056 str( egressPort )
Hari Krishna9e232602015-04-13 17:29:08 -07002057
2058 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08002059 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002060 assert "Command not found:" not in handle, handle
Hari Krishna9e232602015-04-13 17:29:08 -07002061 # If error, return error message
2062 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002063 main.log.error( self.name + ": Error in adding mpls intent" )
Hari Krishna9e232602015-04-13 17:29:08 -07002064 return None
2065 else:
2066 # TODO: print out all the options in this message?
2067 main.log.info( "MPLS intent installed between " +
2068 str( ingressDevice ) + " and " +
2069 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002070 match = re.search( 'id=0x([\da-f]+),', handle )
Hari Krishna9e232602015-04-13 17:29:08 -07002071 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002072 return match.group()[ 3:-1 ]
Hari Krishna9e232602015-04-13 17:29:08 -07002073 else:
2074 main.log.error( "Error, intent ID not found" )
2075 return None
Jon Hallc6793552016-01-19 14:18:37 -08002076 except AssertionError:
2077 main.log.exception( "" )
2078 return None
Hari Krishna9e232602015-04-13 17:29:08 -07002079 except TypeError:
2080 main.log.exception( self.name + ": Object not as expected" )
2081 return None
2082 except pexpect.EOF:
2083 main.log.error( self.name + ": EOF exception found" )
2084 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002085 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002086 except Exception:
2087 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002088 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002089
Jon Hallefbd9792015-03-05 16:11:36 -08002090 def removeIntent( self, intentId, app='org.onosproject.cli',
2091 purge=False, sync=False ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002092 """
shahshreya1c818fc2015-02-26 13:44:08 -08002093 Remove intent for specified application id and intent id
Jon Hall61282e32015-03-19 11:34:11 -07002094 Optional args:-
shahshreya1c818fc2015-02-26 13:44:08 -08002095 -s or --sync: Waits for the removal before returning
Jon Hall61282e32015-03-19 11:34:11 -07002096 -p or --purge: Purge the intent from the store after removal
2097
Jon Halle3f39ff2015-01-13 11:50:53 -08002098 Returns:
Jon Hall6509dbf2016-06-21 17:01:17 -07002099 main.FALSE on error and
Jon Halle3f39ff2015-01-13 11:50:53 -08002100 cli output otherwise
kelvin-onlab898a6c62015-01-16 14:13:53 -08002101 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002102 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002103 cmdStr = "remove-intent"
shahshreya1c818fc2015-02-26 13:44:08 -08002104 if purge:
2105 cmdStr += " -p"
2106 if sync:
2107 cmdStr += " -s"
2108
2109 cmdStr += " " + app + " " + str( intentId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002110 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002111 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002112 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08002113 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002114 main.log.error( self.name + ": Error in removing intent" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002115 return main.FALSE
andrewonlab9a50dfe2014-10-17 17:22:31 -04002116 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002117 # TODO: Should this be main.TRUE
2118 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002119 except AssertionError:
2120 main.log.exception( "" )
2121 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002122 except TypeError:
2123 main.log.exception( self.name + ": Object not as expected" )
2124 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002125 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002126 main.log.error( self.name + ": EOF exception found" )
2127 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002128 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002129 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002130 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002131 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04002132
YPZhangfebf7302016-05-24 16:45:56 -07002133 def removeAllIntents( self, purge=False, sync=False, app='org.onosproject.cli', timeout=30 ):
Jeremy42df2e72016-02-23 16:37:46 -08002134 """
2135 Description:
2136 Remove all the intents
2137 Optional args:-
2138 -s or --sync: Waits for the removal before returning
2139 -p or --purge: Purge the intent from the store after removal
2140 Returns:
2141 Returns main.TRUE if all intents are removed, otherwise returns
2142 main.FALSE; Returns None for exception
2143 """
2144 try:
2145 cmdStr = "remove-intent"
2146 if purge:
2147 cmdStr += " -p"
2148 if sync:
2149 cmdStr += " -s"
2150
2151 cmdStr += " " + app
YPZhangfebf7302016-05-24 16:45:56 -07002152 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08002153 assert handle is not None, "Error in sendline"
Jeremy42df2e72016-02-23 16:37:46 -08002154 assert "Command not found:" not in handle, handle
2155 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002156 main.log.error( self.name + ": Error in removing intent" )
Jeremy42df2e72016-02-23 16:37:46 -08002157 return main.FALSE
2158 else:
2159 return main.TRUE
2160 except AssertionError:
2161 main.log.exception( "" )
2162 return None
2163 except TypeError:
2164 main.log.exception( self.name + ": Object not as expected" )
2165 return None
2166 except pexpect.EOF:
2167 main.log.error( self.name + ": EOF exception found" )
2168 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002169 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002170 except Exception:
2171 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002172 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002173
Hari Krishnaacabd5a2015-07-01 17:10:19 -07002174 def purgeWithdrawnIntents( self ):
Hari Krishna0ce0e152015-06-23 09:55:29 -07002175 """
2176 Purges all WITHDRAWN Intents
2177 """
2178 try:
2179 cmdStr = "purge-intents"
2180 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002181 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002182 assert "Command not found:" not in handle, handle
Hari Krishna0ce0e152015-06-23 09:55:29 -07002183 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002184 main.log.error( self.name + ": Error in purging intents" )
Hari Krishna0ce0e152015-06-23 09:55:29 -07002185 return main.FALSE
2186 else:
2187 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002188 except AssertionError:
2189 main.log.exception( "" )
2190 return None
Hari Krishna0ce0e152015-06-23 09:55:29 -07002191 except TypeError:
2192 main.log.exception( self.name + ": Object not as expected" )
2193 return None
2194 except pexpect.EOF:
2195 main.log.error( self.name + ": EOF exception found" )
2196 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002197 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002198 except Exception:
2199 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002200 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002201
Devin Lime6fe3c42017-10-18 16:28:40 -07002202 def wipeout( self ):
2203 """
2204 Wipe out the flows,intents,links,devices,hosts, and groups from the ONOS.
2205 """
2206 try:
2207 cmdStr = "wipe-out please"
2208 handle = self.sendline( cmdStr, timeout=60 )
2209 assert handle is not None, "Error in sendline"
2210 assert "Command not found:" not in handle, handle
2211 return main.TRUE
2212 except AssertionError:
2213 main.log.exception( "" )
2214 return None
2215 except TypeError:
2216 main.log.exception( self.name + ": Object not as expected" )
2217 return None
2218 except pexpect.EOF:
2219 main.log.error( self.name + ": EOF exception found" )
2220 main.log.error( self.name + ": " + self.handle.before )
2221 main.cleanAndExit()
2222 except Exception:
2223 main.log.exception( self.name + ": Uncaught exception!" )
2224 main.cleanAndExit()
2225
kelvin-onlabd3b64892015-01-20 13:26:24 -08002226 def routes( self, jsonFormat=False ):
kelvin8ec71442015-01-15 16:57:00 -08002227 """
kelvin-onlab898a6c62015-01-16 14:13:53 -08002228 NOTE: This method should be used after installing application:
2229 onos-app-sdnip
pingping-lin8b306ac2014-11-17 18:13:51 -08002230 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002231 * jsonFormat: enable output formatting in json
pingping-lin8b306ac2014-11-17 18:13:51 -08002232 Description:
2233 Obtain all routes in the system
kelvin8ec71442015-01-15 16:57:00 -08002234 """
pingping-lin8b306ac2014-11-17 18:13:51 -08002235 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002236 cmdStr = "routes"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002237 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002238 cmdStr += " -j"
2239 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002240 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002241 assert "Command not found:" not in handle, handle
pingping-lin8b306ac2014-11-17 18:13:51 -08002242 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002243 except AssertionError:
2244 main.log.exception( "" )
2245 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002246 except TypeError:
2247 main.log.exception( self.name + ": Object not as expected" )
2248 return None
pingping-lin8b306ac2014-11-17 18:13:51 -08002249 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002250 main.log.error( self.name + ": EOF exception found" )
2251 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002252 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002253 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002254 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002255 main.cleanAndExit()
pingping-lin8b306ac2014-11-17 18:13:51 -08002256
pingping-lin54b03372015-08-13 14:43:10 -07002257 def ipv4RouteNumber( self ):
2258 """
2259 NOTE: This method should be used after installing application:
2260 onos-app-sdnip
2261 Description:
2262 Obtain the total IPv4 routes number in the system
2263 """
2264 try:
Pratik Parab57963572017-05-09 11:37:54 -07002265 cmdStr = "routes -j"
pingping-lin54b03372015-08-13 14:43:10 -07002266 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002267 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002268 assert "Command not found:" not in handle, handle
pingping-lin54b03372015-08-13 14:43:10 -07002269 jsonResult = json.loads( handle )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002270 return len( jsonResult[ 'routes4' ] )
Jon Hallc6793552016-01-19 14:18:37 -08002271 except AssertionError:
2272 main.log.exception( "" )
2273 return None
2274 except ( TypeError, ValueError ):
2275 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002276 return None
2277 except pexpect.EOF:
2278 main.log.error( self.name + ": EOF exception found" )
2279 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002280 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002281 except Exception:
2282 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002283 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002284
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002285 # =============Function to check Bandwidth allocation========
Jon Hall0e240372018-05-02 11:21:57 -07002286 def allocations( self, jsonFormat = True ):
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002287 """
2288 Description:
2289 Obtain Bandwidth Allocation Information from ONOS cli.
2290 """
2291 try:
2292 cmdStr = "allocations"
2293 if jsonFormat:
2294 cmdStr += " -j"
Jon Hall0e240372018-05-02 11:21:57 -07002295 handle = self.sendline( cmdStr, timeout=300 )
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002296 assert handle is not None, "Error in sendline"
2297 assert "Command not found:" not in handle, handle
2298 return handle
2299 except AssertionError:
2300 main.log.exception( "" )
2301 return None
2302 except ( TypeError, ValueError ):
2303 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
2304 return None
2305 except pexpect.EOF:
2306 main.log.error( self.name + ": EOF exception found" )
2307 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002308 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002309 except Exception:
2310 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002311 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002312
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002313 def intents( self, jsonFormat = True, summary = False, **intentargs ):
kelvin8ec71442015-01-15 16:57:00 -08002314 """
andrewonlabe6745342014-10-17 14:29:13 -04002315 Description:
Jon Hallff566d52016-01-15 14:45:36 -08002316 Obtain intents from the ONOS cli.
2317 Optional:
2318 * jsonFormat: Enable output formatting in json, default to True
2319 * summary: Whether only output the intent summary, defaults to False
2320 * type: Only output a certain type of intent. This options is valid
2321 only when jsonFormat is True and summary is True.
kelvin-onlab898a6c62015-01-16 14:13:53 -08002322 """
andrewonlabe6745342014-10-17 14:29:13 -04002323 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002324 cmdStr = "intents"
pingping-lin8244a3b2015-09-16 13:36:56 -07002325 if summary:
2326 cmdStr += " -s"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002327 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002328 cmdStr += " -j"
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002329 handle = self.sendline( cmdStr, timeout=300 )
You Wangb5a55f72017-03-03 12:51:05 -08002330 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002331 assert "Command not found:" not in handle, handle
pingping-lin8244a3b2015-09-16 13:36:56 -07002332 args = utilities.parse_args( [ "TYPE" ], **intentargs )
acsmars5b5fbaf2015-09-18 10:38:20 -07002333 if "TYPE" in args.keys():
Jon Hallff566d52016-01-15 14:45:36 -08002334 intentType = args[ "TYPE" ]
acsmars5b5fbaf2015-09-18 10:38:20 -07002335 else:
Jon Hallff566d52016-01-15 14:45:36 -08002336 intentType = ""
2337 # IF we want the summary of a specific intent type
2338 if jsonFormat and summary and ( intentType != "" ):
pingping-lin8244a3b2015-09-16 13:36:56 -07002339 jsonResult = json.loads( handle )
Jon Hallff566d52016-01-15 14:45:36 -08002340 if intentType in jsonResult.keys():
2341 return jsonResult[ intentType ]
pingping-lin8244a3b2015-09-16 13:36:56 -07002342 else:
Jon Hallff566d52016-01-15 14:45:36 -08002343 main.log.error( "unknown TYPE, returning all types of intents" )
pingping-lin8244a3b2015-09-16 13:36:56 -07002344 return handle
2345 else:
2346 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002347 except AssertionError:
2348 main.log.exception( "" )
2349 return None
2350 except ( TypeError, ValueError ):
2351 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002352 return None
2353 except pexpect.EOF:
2354 main.log.error( self.name + ": EOF exception found" )
2355 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002356 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002357 except Exception:
2358 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002359 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002360
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002361 def getIntentState( self, intentsId, intentsJson=None ):
kelvin-onlab54400a92015-02-26 18:05:51 -08002362 """
You Wangfdcbfc42016-05-16 12:16:53 -07002363 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002364 Gets intent state. Accepts a single intent ID (string type) or a
You Wangfdcbfc42016-05-16 12:16:53 -07002365 list of intent IDs.
2366 Parameters:
2367 intentsId: intent ID, both string type and list type are acceptable
kelvin-onlab54400a92015-02-26 18:05:51 -08002368 intentsJson: parsed json object from the onos:intents api
You Wangfdcbfc42016-05-16 12:16:53 -07002369 Returns:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002370 Returns the state (string type) of the ID if a single intent ID is
You Wangfdcbfc42016-05-16 12:16:53 -07002371 accepted.
2372 Returns a list of dictionaries if a list of intent IDs is accepted,
2373 and each dictionary maps 'id' to the Intent ID and 'state' to
2374 corresponding intent state.
kelvin-onlab54400a92015-02-26 18:05:51 -08002375 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002376
kelvin-onlab54400a92015-02-26 18:05:51 -08002377 try:
2378 state = "State is Undefined"
2379 if not intentsJson:
Jon Hallc6793552016-01-19 14:18:37 -08002380 rawJson = self.intents()
kelvin-onlab54400a92015-02-26 18:05:51 -08002381 else:
Jon Hallc6793552016-01-19 14:18:37 -08002382 rawJson = intentsJson
2383 parsedIntentsJson = json.loads( rawJson )
Jon Hallefbd9792015-03-05 16:11:36 -08002384 if isinstance( intentsId, types.StringType ):
Jon Hallc6793552016-01-19 14:18:37 -08002385 for intent in parsedIntentsJson:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002386 if intentsId == intent[ 'id' ]:
2387 state = intent[ 'state' ]
kelvin-onlab54400a92015-02-26 18:05:51 -08002388 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002389 main.log.info( "Cannot find intent ID" + str( intentsId ) +
Jon Hall53158082017-05-18 11:17:00 -07002390 " in the list" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002391 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002392 elif isinstance( intentsId, types.ListType ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002393 dictList = []
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002394 for i in xrange( len( intentsId ) ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002395 stateDict = {}
Jon Hall53158082017-05-18 11:17:00 -07002396 for intent in parsedIntentsJson:
2397 if intentsId[ i ] == intent[ 'id' ]:
2398 stateDict[ 'state' ] = intent[ 'state' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002399 stateDict[ 'id' ] = intentsId[ i ]
Jon Hallefbd9792015-03-05 16:11:36 -08002400 dictList.append( stateDict )
kelvin-onlab54400a92015-02-26 18:05:51 -08002401 break
Jon Hallefbd9792015-03-05 16:11:36 -08002402 if len( intentsId ) != len( dictList ):
Jon Hall53158082017-05-18 11:17:00 -07002403 main.log.warn( "Could not find all intents in ONOS output" )
2404 main.log.debug( "expected ids: {} \n ONOS intents: {}".format( intentsId, parsedIntentsJson ) )
kelvin-onlab07dbd012015-03-04 16:29:39 -08002405 return dictList
kelvin-onlab54400a92015-02-26 18:05:51 -08002406 else:
Jon Hall53158082017-05-18 11:17:00 -07002407 main.log.info( "Invalid type for intentsId argument" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002408 return None
Jon Hallc6793552016-01-19 14:18:37 -08002409 except ( TypeError, ValueError ):
2410 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
kelvin-onlab54400a92015-02-26 18:05:51 -08002411 return None
2412 except pexpect.EOF:
2413 main.log.error( self.name + ": EOF exception found" )
2414 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002415 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002416 except Exception:
kelvin-onlab54400a92015-02-26 18:05:51 -08002417 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002418 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07002419
Jon Hallf539eb92017-05-22 17:18:42 -07002420 def checkIntentState( self, intentsId, expectedState='INSTALLED' ):
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002421 """
2422 Description:
2423 Check intents state
2424 Required:
2425 intentsId - List of intents ID to be checked
2426 Optional:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002427 expectedState - Check the expected state(s) of each intents
kelvin-onlabf512e942015-06-08 19:42:59 -07002428 state in the list.
2429 *NOTE: You can pass in a list of expected state,
2430 Eg: expectedState = [ 'INSTALLED' , 'INSTALLING' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002431 Return:
Jon Hall53158082017-05-18 11:17:00 -07002432 Returns main.TRUE only if all intent are the same as expected states,
2433 otherwise returns main.FALSE.
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002434 """
2435 try:
kelvin-onlabf512e942015-06-08 19:42:59 -07002436 returnValue = main.TRUE
Jon Hallf539eb92017-05-22 17:18:42 -07002437 # Generating a dictionary: intent id as a key and state as value
Devin Lim752dd7b2017-06-27 14:40:03 -07002438
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002439 # intentsDict = self.getIntentState( intentsId )
Devin Lim752dd7b2017-06-27 14:40:03 -07002440 intentsDict = []
2441 for intent in json.loads( self.intents() ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002442 if isinstance( intentsId, types.StringType ) \
2443 and intent.get( 'id' ) == intentsId:
2444 intentsDict.append( intent )
2445 elif isinstance( intentsId, types.ListType ) \
Devin Lim752dd7b2017-06-27 14:40:03 -07002446 and any( intent.get( 'id' ) == ids for ids in intentsId ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002447 intentsDict.append( intent )
Devin Lim752dd7b2017-06-27 14:40:03 -07002448
2449 if not intentsDict:
Jon Hallae04e622016-01-27 10:38:05 -08002450 main.log.info( self.name + ": There is something wrong " +
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002451 "getting intents state" )
2452 return main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002453
2454 if isinstance( expectedState, types.StringType ):
2455 for intents in intentsDict:
2456 if intents.get( 'state' ) != expectedState:
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002457 main.log.debug( self.name + " : Intent ID - " +
2458 intents.get( 'id' ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002459 " actual state = " +
2460 intents.get( 'state' )
2461 + " does not equal expected state = "
2462 + expectedState )
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002463 returnValue = main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002464 elif isinstance( expectedState, types.ListType ):
2465 for intents in intentsDict:
2466 if not any( state == intents.get( 'state' ) for state in
2467 expectedState ):
2468 main.log.debug( self.name + " : Intent ID - " +
2469 intents.get( 'id' ) +
2470 " actual state = " +
2471 intents.get( 'state' ) +
2472 " does not equal expected states = "
2473 + str( expectedState ) )
2474 returnValue = main.FALSE
2475
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002476 if returnValue == main.TRUE:
2477 main.log.info( self.name + ": All " +
2478 str( len( intentsDict ) ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002479 " intents are in " + str( expectedState ) +
2480 " state" )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002481 return returnValue
2482 except TypeError:
2483 main.log.exception( self.name + ": Object not as expected" )
2484 return None
2485 except pexpect.EOF:
2486 main.log.error( self.name + ": EOF exception found" )
2487 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002488 main.cleanAndExit()
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002489 except Exception:
2490 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002491 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04002492
Jon Hallf539eb92017-05-22 17:18:42 -07002493 def compareBandwidthAllocations( self, expectedAllocations ):
2494 """
2495 Description:
2496 Compare the allocated bandwidth with the given allocations
2497 Required:
2498 expectedAllocations - The expected ONOS output of the allocations command
2499 Return:
2500 Returns main.TRUE only if all intent are the same as expected states,
2501 otherwise returns main.FALSE.
2502 """
2503 # FIXME: Convert these string comparisons to object comparisons
2504 try:
2505 returnValue = main.TRUE
2506 bandwidthFailed = False
2507 rawAlloc = self.allocations()
2508 expectedFormat = StringIO( expectedAllocations )
2509 ONOSOutput = StringIO( rawAlloc )
2510 main.log.debug( "ONOSOutput: {}\nexpected output: {}".format( str( ONOSOutput ),
2511 str( expectedFormat ) ) )
2512
2513 for actual, expected in izip( ONOSOutput, expectedFormat ):
2514 actual = actual.rstrip()
2515 expected = expected.rstrip()
2516 main.log.debug( "Expect: {}\nactual: {}".format( expected, actual ) )
2517 if actual != expected and 'allocated' in actual and 'allocated' in expected:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002518 marker1 = actual.find( 'allocated' )
2519 m1 = actual[ :marker1 ]
2520 marker2 = expected.find( 'allocated' )
2521 m2 = expected[ :marker2 ]
Jon Hallf539eb92017-05-22 17:18:42 -07002522 if m1 != m2:
2523 bandwidthFailed = True
2524 elif actual != expected and 'allocated' not in actual and 'allocated' not in expected:
2525 bandwidthFailed = True
2526 expectedFormat.close()
2527 ONOSOutput.close()
2528
2529 if bandwidthFailed:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002530 main.log.error( "Bandwidth not allocated correctly using Intents!!" )
Jon Hallf539eb92017-05-22 17:18:42 -07002531 returnValue = main.FALSE
2532 return returnValue
2533 except TypeError:
2534 main.log.exception( self.name + ": Object not as expected" )
2535 return None
2536 except pexpect.EOF:
2537 main.log.error( self.name + ": EOF exception found" )
2538 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002539 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002540 except Exception:
2541 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002542 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002543
You Wang66518af2016-05-16 15:32:59 -07002544 def compareIntent( self, intentDict ):
2545 """
2546 Description:
2547 Compare the intent ids and states provided in the argument with all intents in ONOS
2548 Return:
2549 Returns main.TRUE if the two sets of intents match exactly, otherwise main.FALSE
2550 Arguments:
2551 intentDict: a dictionary which maps intent ids to intent states
2552 """
2553 try:
2554 intentsRaw = self.intents()
2555 intentsJson = json.loads( intentsRaw )
2556 intentDictONOS = {}
2557 for intent in intentsJson:
2558 intentDictONOS[ intent[ 'id' ] ] = intent[ 'state' ]
You Wang58d04452016-09-21 15:13:05 -07002559 returnValue = main.TRUE
You Wang66518af2016-05-16 15:32:59 -07002560 if len( intentDict ) != len( intentDictONOS ):
You Wang58d04452016-09-21 15:13:05 -07002561 main.log.warn( self.name + ": expected intent count does not match that in ONOS, " +
You Wang66518af2016-05-16 15:32:59 -07002562 str( len( intentDict ) ) + " expected and " +
2563 str( len( intentDictONOS ) ) + " actual" )
You Wang58d04452016-09-21 15:13:05 -07002564 returnValue = main.FALSE
You Wang66518af2016-05-16 15:32:59 -07002565 for intentID in intentDict.keys():
Jon Halle0f0b342017-04-18 11:43:47 -07002566 if intentID not in intentDictONOS.keys():
You Wang66518af2016-05-16 15:32:59 -07002567 main.log.debug( self.name + ": intent ID - " + intentID + " is not in ONOS" )
2568 returnValue = main.FALSE
You Wang58d04452016-09-21 15:13:05 -07002569 else:
2570 if intentDict[ intentID ] != intentDictONOS[ intentID ]:
2571 main.log.debug( self.name + ": intent ID - " + intentID +
2572 " expected state is " + intentDict[ intentID ] +
2573 " but actual state is " + intentDictONOS[ intentID ] )
2574 returnValue = main.FALSE
2575 intentDictONOS.pop( intentID )
2576 if len( intentDictONOS ) > 0:
2577 returnValue = main.FALSE
2578 for intentID in intentDictONOS.keys():
2579 main.log.debug( self.name + ": find extra intent in ONOS: intent ID " + intentID )
You Wang66518af2016-05-16 15:32:59 -07002580 if returnValue == main.TRUE:
2581 main.log.info( self.name + ": all intent IDs and states match that in ONOS" )
2582 return returnValue
You Wang1be9a512016-05-26 16:54:17 -07002583 except KeyError:
2584 main.log.exception( self.name + ": KeyError exception found" )
2585 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002586 except ( TypeError, ValueError ):
2587 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intentsRaw ) )
You Wang85560372016-05-18 10:44:33 -07002588 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002589 except pexpect.EOF:
2590 main.log.error( self.name + ": EOF exception found" )
2591 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002592 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002593 except Exception:
2594 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002595 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002596
YPZhang14a4aa92016-07-15 13:37:15 -07002597 def checkIntentSummary( self, timeout=60, noExit=True ):
GlennRCed771242016-01-13 17:02:47 -08002598 """
2599 Description:
2600 Check the number of installed intents.
2601 Optional:
2602 timeout - the timeout for pexcept
YPZhang14a4aa92016-07-15 13:37:15 -07002603 noExit - If noExit, TestON will not exit if any except.
GlennRCed771242016-01-13 17:02:47 -08002604 Return:
2605 Returns main.TRUE only if the number of all installed intents are the same as total intents number
2606 , otherwise, returns main.FALSE.
2607 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002608
GlennRCed771242016-01-13 17:02:47 -08002609 try:
2610 cmd = "intents -s -j"
2611
2612 # Check response if something wrong
YPZhang14a4aa92016-07-15 13:37:15 -07002613 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002614 if response is None:
YPZhang0584d432016-06-21 15:20:13 -07002615 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002616 response = json.loads( response )
2617
2618 # get total and installed number, see if they are match
2619 allState = response.get( 'all' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002620 if allState.get( 'total' ) == allState.get( 'installed' ):
Jon Halla478b852017-12-04 15:00:15 -08002621 main.log.info( 'Total Intents: {} Installed Intents: {}'.format(
2622 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002623 return main.TRUE
Jon Halla478b852017-12-04 15:00:15 -08002624 main.log.info( 'Verified Intents failed Expected intents: {} installed intents: {}'.format(
2625 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002626 return main.FALSE
2627
Jon Hallc6793552016-01-19 14:18:37 -08002628 except ( TypeError, ValueError ):
2629 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
GlennRCed771242016-01-13 17:02:47 -08002630 return None
2631 except pexpect.EOF:
2632 main.log.error( self.name + ": EOF exception found" )
2633 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002634 if noExit:
2635 return main.FALSE
2636 else:
Devin Lim44075962017-08-11 10:56:37 -07002637 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07002638 except pexpect.TIMEOUT:
2639 main.log.error( self.name + ": ONOS timeout" )
2640 return None
GlennRCed771242016-01-13 17:02:47 -08002641 except Exception:
2642 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002643 if noExit:
2644 return main.FALSE
2645 else:
Devin Lim44075962017-08-11 10:56:37 -07002646 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002647
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002648 def flows( self, state="any", jsonFormat=True, timeout=60, noExit=False, noCore=False, device=""):
kelvin8ec71442015-01-15 16:57:00 -08002649 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002650 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002651 * jsonFormat: enable output formatting in json
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002652 * noCore: suppress core flows
Shreya Shah0f01c812014-10-26 20:15:28 -04002653 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002654 Obtain flows currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08002655 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002656 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002657 cmdStr = "flows"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002658 if jsonFormat:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002659 cmdStr += " -j"
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002660 if noCore:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002661 cmdStr += " -n"
2662 cmdStr += " " + state
2663 cmdStr += " " + device
YPZhangebf9eb52016-05-12 15:20:24 -07002664 handle = self.sendline( cmdStr, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002665 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002666 assert "Command not found:" not in handle, handle
2667 if re.search( "Error:", handle ):
2668 main.log.error( self.name + ": flows() response: " +
2669 str( handle ) )
2670 return handle
2671 except AssertionError:
2672 main.log.exception( "" )
GlennRCed771242016-01-13 17:02:47 -08002673 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002674 except TypeError:
2675 main.log.exception( self.name + ": Object not as expected" )
2676 return None
Jon Hallc6793552016-01-19 14:18:37 -08002677 except pexpect.TIMEOUT:
2678 main.log.error( self.name + ": ONOS timeout" )
2679 return None
Shreya Shah0f01c812014-10-26 20:15:28 -04002680 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002681 main.log.error( self.name + ": EOF exception found" )
2682 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002683 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002684 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002685 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002686 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002687
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002688 def checkFlowCount( self, min=0, timeout=60 ):
Flavio Castroa1286fe2016-07-25 14:48:51 -07002689 count = self.getTotalFlowsNum( timeout=timeout )
Jon Halle0f0b342017-04-18 11:43:47 -07002690 count = int( count ) if count else 0
steven30801eccfe212019-01-24 13:00:42 +08002691 main.log.debug( "found {} flows".format( count ) )
Jon Hall39570262020-11-17 12:18:19 -08002692 return count if ( count >= min ) else False
GlennRCed771242016-01-13 17:02:47 -08002693
Jon Halle0f0b342017-04-18 11:43:47 -07002694 def checkFlowsState( self, isPENDING=True, timeout=60, noExit=False ):
kelvin-onlab4df89f22015-04-13 18:10:23 -07002695 """
2696 Description:
GlennRCed771242016-01-13 17:02:47 -08002697 Check the if all the current flows are in ADDED state
Jon Hallc6793552016-01-19 14:18:37 -08002698 We check PENDING_ADD, PENDING_REMOVE, REMOVED, and FAILED flows,
2699 if the count of those states is 0, which means all current flows
2700 are in ADDED state, and return main.TRUE otherwise return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002701 Optional:
GlennRCed771242016-01-13 17:02:47 -08002702 * isPENDING: whether the PENDING_ADD is also a correct status
kelvin-onlab4df89f22015-04-13 18:10:23 -07002703 Return:
2704 returnValue - Returns main.TRUE only if all flows are in
Jon Hallc6793552016-01-19 14:18:37 -08002705 ADDED state or PENDING_ADD if the isPENDING
pingping-linbab7f8a2015-09-21 17:33:36 -07002706 parameter is set true, return main.FALSE otherwise.
kelvin-onlab4df89f22015-04-13 18:10:23 -07002707 """
2708 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002709 states = [ "PENDING_ADD", "PENDING_REMOVE", "REMOVED", "FAILED" ]
GlennRCed771242016-01-13 17:02:47 -08002710 checkedStates = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002711 statesCount = [ 0, 0, 0, 0 ]
GlennRCed771242016-01-13 17:02:47 -08002712 for s in states:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002713 rawFlows = self.flows( state=s, timeout = timeout )
YPZhang240842b2016-05-17 12:00:50 -07002714 if rawFlows:
2715 # if we didn't get flows or flows function return None, we should return
2716 # main.Flase
2717 checkedStates.append( json.loads( rawFlows ) )
2718 else:
2719 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002720 for i in range( len( states ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002721 for c in checkedStates[ i ]:
Jon Hallc6793552016-01-19 14:18:37 -08002722 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002723 statesCount[ i ] += int( c.get( "flowCount" ) )
Jon Hallc6793552016-01-19 14:18:37 -08002724 except TypeError:
2725 main.log.exception( "Json object not as expected" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002726 main.log.info( states[ i ] + " flows: " + str( statesCount[ i ] ) )
kelvin-onlabf2ec6e02015-05-27 14:15:28 -07002727
GlennRCed771242016-01-13 17:02:47 -08002728 # We want to count PENDING_ADD if isPENDING is true
2729 if isPENDING:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002730 if statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002731 return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002732 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002733 if statesCount[ 0 ] + statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002734 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002735 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002736 except ( TypeError, ValueError ):
2737 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawFlows ) )
kelvin-onlab4df89f22015-04-13 18:10:23 -07002738 return None
Jeremy Songster9385d412016-06-02 17:57:36 -07002739
YPZhang240842b2016-05-17 12:00:50 -07002740 except AssertionError:
2741 main.log.exception( "" )
2742 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002743 except pexpect.TIMEOUT:
2744 main.log.error( self.name + ": ONOS timeout" )
2745 return None
kelvin-onlab4df89f22015-04-13 18:10:23 -07002746 except pexpect.EOF:
2747 main.log.error( self.name + ": EOF exception found" )
2748 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002749 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002750 except Exception:
2751 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002752 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002753
GlennRCed771242016-01-13 17:02:47 -08002754 def pushTestIntents( self, ingress, egress, batchSize, offset="",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002755 options="", timeout=10, background = False, noExit=False, getResponse=False ):
kelvin8ec71442015-01-15 16:57:00 -08002756 """
andrewonlab87852b02014-11-19 18:44:19 -05002757 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002758 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05002759 a specific point-to-point intent definition
2760 Required:
GlennRCed771242016-01-13 17:02:47 -08002761 * ingress: specify source dpid
2762 * egress: specify destination dpid
2763 * batchSize: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05002764 Optional:
GlennRCed771242016-01-13 17:02:47 -08002765 * offset: the keyOffset is where the next batch of intents
2766 will be installed
YPZhangb34b7e12016-06-14 14:28:19 -07002767 * noExit: If set to True, TestON will not exit if any error when issus command
2768 * getResponse: If set to True, function will return ONOS response.
2769
GlennRCed771242016-01-13 17:02:47 -08002770 Returns: If failed to push test intents, it will returen None,
2771 if successful, return true.
2772 Timeout expection will return None,
2773 TypeError will return false
2774 other expections will exit()
kelvin8ec71442015-01-15 16:57:00 -08002775 """
andrewonlab87852b02014-11-19 18:44:19 -05002776 try:
GlennRCed771242016-01-13 17:02:47 -08002777 if background:
2778 back = "&"
andrewonlab87852b02014-11-19 18:44:19 -05002779 else:
GlennRCed771242016-01-13 17:02:47 -08002780 back = ""
2781 cmd = "push-test-intents {} {} {} {} {} {}".format( options,
Jon Hallc6793552016-01-19 14:18:37 -08002782 ingress,
2783 egress,
2784 batchSize,
2785 offset,
2786 back )
YPZhangebf9eb52016-05-12 15:20:24 -07002787 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002788 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002789 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08002790 main.log.info( response )
YPZhangb34b7e12016-06-14 14:28:19 -07002791 if getResponse:
2792 return response
2793
GlennRCed771242016-01-13 17:02:47 -08002794 # TODO: We should handle if there is failure in installation
2795 return main.TRUE
2796
Jon Hallc6793552016-01-19 14:18:37 -08002797 except AssertionError:
2798 main.log.exception( "" )
2799 return None
GlennRCed771242016-01-13 17:02:47 -08002800 except pexpect.TIMEOUT:
2801 main.log.error( self.name + ": ONOS timeout" )
Jon Halld4d4b372015-01-28 16:02:41 -08002802 return None
andrewonlab87852b02014-11-19 18:44:19 -05002803 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002804 main.log.error( self.name + ": EOF exception found" )
2805 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002806 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002807 except TypeError:
2808 main.log.exception( self.name + ": Object not as expected" )
Jon Hallc6793552016-01-19 14:18:37 -08002809 return None
Jon Hallfebb1c72015-03-05 13:30:09 -08002810 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002811 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002812 main.cleanAndExit()
andrewonlab87852b02014-11-19 18:44:19 -05002813
YPZhangebf9eb52016-05-12 15:20:24 -07002814 def getTotalFlowsNum( self, timeout=60, noExit=False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002815 """
2816 Description:
YPZhangf6f14a02016-01-28 15:17:31 -08002817 Get the number of ADDED flows.
YPZhangb5d3f832016-01-23 22:54:26 -08002818 Return:
YPZhangf6f14a02016-01-28 15:17:31 -08002819 The number of ADDED flows
YPZhang14a4aa92016-07-15 13:37:15 -07002820 Or return None if any exceptions
YPZhangb5d3f832016-01-23 22:54:26 -08002821 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002822
YPZhangb5d3f832016-01-23 22:54:26 -08002823 try:
YPZhange3109a72016-02-02 11:25:37 -08002824 # get total added flows number
YPZhang14a4aa92016-07-15 13:37:15 -07002825 cmd = "flows -c added"
2826 rawFlows = self.sendline( cmd, timeout=timeout, noExit=noExit )
2827 if rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002828 rawFlows = rawFlows.split( "\n" )
YPZhange3109a72016-02-02 11:25:37 -08002829 totalFlows = 0
YPZhang14a4aa92016-07-15 13:37:15 -07002830 for l in rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002831 totalFlows += int( l.split( "Count=" )[ 1 ] )
YPZhang14a4aa92016-07-15 13:37:15 -07002832 else:
You Wang68568b12019-03-04 11:49:57 -08002833 main.log.warn( "Response not as expected!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002834 return None
2835 return totalFlows
YPZhange3109a72016-02-02 11:25:37 -08002836
You Wangd3097f72018-12-12 11:56:03 -08002837 except IndexError:
2838 main.log.exception( "{}: Object not as expected!".format( self.name ) )
2839 main.log.debug( "rawFlows: {}".format( rawFlows ) )
2840 return None
You Wangd3cb2ce2016-05-16 14:01:24 -07002841 except ( TypeError, ValueError ):
YPZhang14a4aa92016-07-15 13:37:15 -07002842 main.log.exception( "{}: Object not as expected!".format( self.name ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002843 return None
2844 except pexpect.EOF:
2845 main.log.error( self.name + ": EOF exception found" )
2846 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002847 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002848 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002849 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002850 except pexpect.TIMEOUT:
2851 main.log.error( self.name + ": ONOS timeout" )
2852 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002853 except Exception:
2854 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002855 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002856 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002857 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002858
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002859 def getTotalIntentsNum( self, timeout=60, noExit = False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002860 """
2861 Description:
2862 Get the total number of intents, include every states.
YPZhang14a4aa92016-07-15 13:37:15 -07002863 Optional:
2864 noExit - If noExit, TestON will not exit if any except.
YPZhangb5d3f832016-01-23 22:54:26 -08002865 Return:
2866 The number of intents
2867 """
2868 try:
2869 cmd = "summary -j"
YPZhang14a4aa92016-07-15 13:37:15 -07002870 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002871 if response is None:
2872 return -1
YPZhangb5d3f832016-01-23 22:54:26 -08002873 response = json.loads( response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002874 return int( response.get( "intents" ) )
You Wangd3cb2ce2016-05-16 14:01:24 -07002875 except ( TypeError, ValueError ):
2876 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002877 return None
2878 except pexpect.EOF:
2879 main.log.error( self.name + ": EOF exception found" )
2880 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002881 if noExit:
2882 return -1
2883 else:
Devin Lim44075962017-08-11 10:56:37 -07002884 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002885 except Exception:
2886 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002887 if noExit:
2888 return -1
2889 else:
Devin Lim44075962017-08-11 10:56:37 -07002890 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002891
kelvin-onlabd3b64892015-01-20 13:26:24 -08002892 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002893 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002894 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002895 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002896 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002897 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002898 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002899 cmdStr = "intents-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002900 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002901 cmdStr += " -j"
2902 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002903 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002904 assert "Command not found:" not in handle, handle
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002905 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002906 except AssertionError:
2907 main.log.exception( "" )
2908 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002909 except TypeError:
2910 main.log.exception( self.name + ": Object not as expected" )
2911 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002912 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002913 main.log.error( self.name + ": EOF exception found" )
2914 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002915 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002916 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002917 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002918 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002919
kelvin-onlabd3b64892015-01-20 13:26:24 -08002920 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002921 """
2922 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04002923 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002924 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002925 """
andrewonlab867212a2014-10-22 20:13:38 -04002926 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002927 cmdStr = "topology-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002928 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002929 cmdStr += " -j"
2930 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002931 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002932 assert "Command not found:" not in handle, handle
jenkins7ead5a82015-03-13 10:28:21 -07002933 if handle:
2934 return handle
Jon Hallc6358dd2015-04-10 12:44:28 -07002935 elif jsonFormat:
Jon Hallbe379602015-03-24 13:39:32 -07002936 # Return empty json
jenkins7ead5a82015-03-13 10:28:21 -07002937 return '{}'
Jon Hallc6358dd2015-04-10 12:44:28 -07002938 else:
2939 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002940 except AssertionError:
2941 main.log.exception( "" )
2942 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002943 except TypeError:
2944 main.log.exception( self.name + ": Object not as expected" )
2945 return None
andrewonlab867212a2014-10-22 20:13:38 -04002946 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002947 main.log.error( self.name + ": EOF exception found" )
2948 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002949 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002950 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002951 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002952 main.cleanAndExit()
andrewonlab867212a2014-10-22 20:13:38 -04002953
kelvin8ec71442015-01-15 16:57:00 -08002954 # Wrapper functions ****************
2955 # Wrapper functions use existing driver
2956 # functions and extends their use case.
2957 # For example, we may use the output of
2958 # a normal driver function, and parse it
2959 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04002960
kelvin-onlabd3b64892015-01-20 13:26:24 -08002961 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002962 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002963 Description:
2964 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08002965 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002966 try:
kelvin8ec71442015-01-15 16:57:00 -08002967 # Obtain output of intents function
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002968 intentsStr = self.intents( jsonFormat=True )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07002969 if intentsStr is None:
2970 raise TypeError
Jon Hall6021e062017-01-30 11:10:06 -08002971 # Convert to a dictionary
2972 intents = json.loads( intentsStr )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002973 intentIdList = []
Jon Hall6021e062017-01-30 11:10:06 -08002974 for intent in intents:
2975 intentIdList.append( intent[ 'id' ] )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002976 return intentIdList
Jon Halld4d4b372015-01-28 16:02:41 -08002977 except TypeError:
2978 main.log.exception( self.name + ": Object not as expected" )
2979 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002980 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002981 main.log.error( self.name + ": EOF exception found" )
2982 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002983 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002984 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002985 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002986 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04002987
You Wang3c276252016-09-21 15:21:36 -07002988 def flowAddedCount( self, deviceId, core=False ):
Jon Hall30b82fa2015-03-04 17:15:43 -08002989 """
2990 Determine the number of flow rules for the given device id that are
2991 in the added state
You Wang3c276252016-09-21 15:21:36 -07002992 Params:
2993 core: if True, only return the number of core flows added
Jon Hall30b82fa2015-03-04 17:15:43 -08002994 """
2995 try:
You Wang3c276252016-09-21 15:21:36 -07002996 if core:
2997 cmdStr = "flows any " + str( deviceId ) + " | " +\
2998 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
2999 else:
3000 cmdStr = "flows any " + str( deviceId ) + " | " +\
3001 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003002 handle = self.lineCount( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003003 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003004 assert "Command not found:" not in handle, handle
Jon Hall30b82fa2015-03-04 17:15:43 -08003005 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003006 except AssertionError:
3007 main.log.exception( "" )
3008 return None
Jon Hall30b82fa2015-03-04 17:15:43 -08003009 except pexpect.EOF:
3010 main.log.error( self.name + ": EOF exception found" )
3011 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003012 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003013 except Exception:
Jon Hall30b82fa2015-03-04 17:15:43 -08003014 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003015 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -04003016
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003017 def groupAddedCount( self, deviceId, core=False ):
3018 """
3019 Determine the number of group rules for the given device id that are
3020 in the added state
3021 Params:
3022 core: if True, only return the number of core groups added
3023 """
3024 try:
3025 if core:
3026 cmdStr = "groups any " + str( deviceId ) + " | " +\
3027 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
3028 else:
3029 cmdStr = "groups any " + str( deviceId ) + " | " +\
3030 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003031 handle = self.lineCount( cmdStr )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003032 assert handle is not None, "Error in sendline"
3033 assert "Command not found:" not in handle, handle
3034 return handle
3035 except AssertionError:
3036 main.log.exception( "" )
3037 return None
3038 except pexpect.EOF:
3039 main.log.error( self.name + ": EOF exception found" )
3040 main.log.error( self.name + ": " + self.handle.before )
3041 main.cleanAndExit()
3042 except Exception:
3043 main.log.exception( self.name + ": Uncaught exception!" )
3044 main.cleanAndExit()
3045
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003046 def addStaticRoute( self, subnet, intf):
3047 """
3048 Adds a static route to onos.
3049 Params:
3050 subnet: The subnet reaching through this route
3051 intf: The interface this route is reachable through
3052 """
3053 try:
3054 cmdStr = "route-add " + subnet + " " + intf
3055 handle = self.sendline( cmdStr )
3056 assert handle is not None, "Error in sendline"
3057 assert "Command not found:" not in handle, handle
3058 return handle
3059 except AssertionError:
3060 main.log.exception( "" )
3061 return None
3062 except pexpect.EOF:
3063 main.log.error( self.name + ": EOF exception found" )
3064 main.log.error( self.name + ": " + self.handle.before )
3065 main.cleanAndExit()
3066 except Exception:
3067 main.log.exception( self.name + ": Uncaught exception!" )
3068 main.cleanAndExit()
3069
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003070 def checkGroupAddedCount( self, deviceId, expectedGroupCount=0, core=False, comparison=0):
3071 """
3072 Description:
3073 Check whether the number of groups for the given device id that
3074 are in ADDED state is bigger than minGroupCount.
3075 Required:
3076 * deviceId: device id to check the number of added group rules
3077 Optional:
3078 * minGroupCount: the number of groups to compare
3079 * core: if True, only check the number of core groups added
3080 * comparison: if 0, compare with greater than minFlowCount
3081 * if 1, compare with equal to minFlowCount
3082 Return:
3083 Returns the number of groups if it is bigger than minGroupCount,
3084 returns main.FALSE otherwise.
3085 """
3086 count = self.groupAddedCount( deviceId, core )
3087 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003088 main.log.debug( "found {} groups".format( count ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003089 return count if ((count > expectedGroupCount) if (comparison == 0) else (count == expectedGroupCount)) else main.FALSE
3090
You Wangc02f3be2018-05-18 12:14:23 -07003091 def getGroups( self, deviceId, groupType="any" ):
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003092 """
3093 Retrieve groups from a specific device.
You Wangc02f3be2018-05-18 12:14:23 -07003094 deviceId: Id of the device from which we retrieve groups
3095 groupType: Type of group
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003096 """
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003097 try:
You Wangc02f3be2018-05-18 12:14:23 -07003098 groupCmd = "groups -t {0} any {1}".format( groupType, deviceId )
3099 handle = self.sendline( groupCmd )
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003100 assert handle is not None, "Error in sendline"
3101 assert "Command not found:" not in handle, handle
3102 return handle
3103 except AssertionError:
3104 main.log.exception( "" )
3105 return None
3106 except TypeError:
3107 main.log.exception( self.name + ": Object not as expected" )
3108 return None
3109 except pexpect.EOF:
3110 main.log.error( self.name + ": EOF exception found" )
3111 main.log.error( self.name + ": " + self.handle.before )
3112 main.cleanAndExit()
3113 except Exception:
3114 main.log.exception( self.name + ": Uncaught exception!" )
3115 main.cleanAndExit()
3116
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003117 def checkFlowAddedCount( self, deviceId, expectedFlowCount=0, core=False, comparison=0):
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003118 """
3119 Description:
3120 Check whether the number of flow rules for the given device id that
3121 are in ADDED state is bigger than minFlowCount.
3122 Required:
3123 * deviceId: device id to check the number of added flow rules
3124 Optional:
3125 * minFlowCount: the number of flow rules to compare
3126 * core: if True, only check the number of core flows added
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003127 * comparison: if 0, compare with greater than minFlowCount
3128 * if 1, compare with equal to minFlowCount
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003129 Return:
3130 Returns the number of flow rules if it is bigger than minFlowCount,
3131 returns main.FALSE otherwise.
3132 """
3133 count = self.flowAddedCount( deviceId, core )
3134 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003135 main.log.debug( "found {} flows".format( count ) )
Jon Hall39570262020-11-17 12:18:19 -08003136 return count if ((count >= expectedFlowCount) if (comparison == 0) else (count == expectedFlowCount)) else main.FALSE
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003137
kelvin-onlabd3b64892015-01-20 13:26:24 -08003138 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003139 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003140 Use 'devices' function to obtain list of all devices
3141 and parse the result to obtain a list of all device
3142 id's. Returns this list. Returns empty list if no
3143 devices exist
kelvin8ec71442015-01-15 16:57:00 -08003144 List is ordered sequentially
3145
andrewonlab3e15ead2014-10-15 14:21:34 -04003146 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08003147 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04003148 the ids. By obtaining the list of device ids on the fly,
3149 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08003150 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003151 try:
kelvin8ec71442015-01-15 16:57:00 -08003152 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08003153 devicesStr = self.devices( jsonFormat=False )
3154 idList = []
kelvin8ec71442015-01-15 16:57:00 -08003155
kelvin-onlabd3b64892015-01-20 13:26:24 -08003156 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08003157 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003158 return idList
kelvin8ec71442015-01-15 16:57:00 -08003159
3160 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08003161 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08003162 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08003163 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08003164 # Split list further into arguments before and after string
3165 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08003166 # append to idList
3167 for arg in tempList:
3168 idList.append( arg.split( "id=" )[ 1 ] )
3169 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04003170
Jon Halld4d4b372015-01-28 16:02:41 -08003171 except TypeError:
3172 main.log.exception( self.name + ": Object not as expected" )
3173 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04003174 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003175 main.log.error( self.name + ": EOF exception found" )
3176 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003177 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003178 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003179 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003180 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003181
kelvin-onlabd3b64892015-01-20 13:26:24 -08003182 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003183 """
andrewonlab7c211572014-10-15 16:45:20 -04003184 Uses 'nodes' function to obtain list of all nodes
3185 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08003186 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04003187 Returns:
3188 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08003189 """
andrewonlab7c211572014-10-15 16:45:20 -04003190 try:
Jon Hall5aa168b2015-03-23 14:23:09 -07003191 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003192 idList = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003193 # Sample nodesStr output
Jon Hallbd182782016-03-28 16:42:22 -07003194 # id=local, address=127.0.0.1:9876, state=READY *
kelvin-onlabd3b64892015-01-20 13:26:24 -08003195 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08003196 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003197 return idList
Jon Hall5aa168b2015-03-23 14:23:09 -07003198 nodesJson = json.loads( nodesStr )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003199 idList = [ node.get( 'id' ) for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08003200 return idList
Jon Hallc6793552016-01-19 14:18:37 -08003201 except ( TypeError, ValueError ):
3202 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, nodesStr ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003203 return None
andrewonlab7c211572014-10-15 16:45:20 -04003204 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003205 main.log.error( self.name + ": EOF exception found" )
3206 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003207 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003208 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003209 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003210 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003211
kelvin-onlabd3b64892015-01-20 13:26:24 -08003212 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08003213 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003214 Return the first device from the devices api whose 'id' contains 'dpid'
3215 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08003216 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003217 try:
kelvin8ec71442015-01-15 16:57:00 -08003218 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04003219 return None
3220 else:
kelvin8ec71442015-01-15 16:57:00 -08003221 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003222 rawDevices = self.devices()
3223 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08003224 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08003225 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08003226 # print "%s in %s?" % ( dpid, device[ 'id' ] )
3227 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04003228 return device
3229 return None
Jon Hallc6793552016-01-19 14:18:37 -08003230 except ( TypeError, ValueError ):
3231 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawDevices ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003232 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04003233 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003234 main.log.error( self.name + ": EOF exception found" )
3235 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003236 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003237 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003238 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003239 main.cleanAndExit()
Jon Halla91c4dc2014-10-22 12:57:04 -04003240
You Wang24139872016-05-03 11:48:47 -07003241 def getTopology( self, topologyOutput ):
3242 """
3243 Definition:
3244 Loads a json topology output
3245 Return:
3246 topology = current ONOS topology
3247 """
You Wang24139872016-05-03 11:48:47 -07003248 try:
3249 # either onos:topology or 'topology' will work in CLI
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003250 topology = json.loads( topologyOutput )
Jeremy Songsterbc2d8ac2016-05-04 11:25:42 -07003251 main.log.debug( topology )
You Wang24139872016-05-03 11:48:47 -07003252 return topology
You Wangd3cb2ce2016-05-16 14:01:24 -07003253 except ( TypeError, ValueError ):
3254 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, topologyOutput ) )
3255 return None
You Wang24139872016-05-03 11:48:47 -07003256 except pexpect.EOF:
3257 main.log.error( self.name + ": EOF exception found" )
3258 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003259 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003260 except Exception:
3261 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003262 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003263
Jon Hall39570262020-11-17 12:18:19 -08003264 def checkStatus( self, numoswitch, numolink = -1, numoctrl = -1, numoSCCs=1, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08003265 """
Jon Hallefbd9792015-03-05 16:11:36 -08003266 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08003267 supplied values. By default this will report to main.log, but the
You Wang24139872016-05-03 11:48:47 -07003268 log level can be specific.
kelvin8ec71442015-01-15 16:57:00 -08003269
Flavio Castro82ee2f62016-06-07 15:04:12 -07003270 Params: numoswitch = expected number of switches
Jon Hallefbd9792015-03-05 16:11:36 -08003271 numolink = expected number of links
Flavio Castro82ee2f62016-06-07 15:04:12 -07003272 numoctrl = expected number of controllers
Jon Hall39570262020-11-17 12:18:19 -08003273 numoSCCs = Number of expected SCCs
You Wang24139872016-05-03 11:48:47 -07003274 logLevel = level to log to.
3275 Currently accepts 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04003276
Jon Hallefbd9792015-03-05 16:11:36 -08003277 Returns: main.TRUE if the number of switches and links are correct,
3278 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04003279 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08003280 """
Jon Hall42db6dc2014-10-24 19:03:48 -04003281 try:
You Wang13310252016-07-31 10:56:14 -07003282 summary = self.summary()
3283 summary = json.loads( summary )
Flavio Castrof5b3f872016-06-23 17:52:31 -07003284 except ( TypeError, ValueError ):
3285 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summary ) )
3286 return main.ERROR
3287 try:
3288 topology = self.getTopology( self.topology() )
Jon Halle0f0b342017-04-18 11:43:47 -07003289 if topology == {} or topology is None or summary == {} or summary is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04003290 return main.ERROR
3291 output = ""
kelvin8ec71442015-01-15 16:57:00 -08003292 # Is the number of switches is what we expected
3293 devices = topology.get( 'devices', False )
3294 links = topology.get( 'links', False )
Flavio Castro82ee2f62016-06-07 15:04:12 -07003295 nodes = summary.get( 'nodes', False )
Jon Hall39570262020-11-17 12:18:19 -08003296 SCCs = summary.get( 'SCC(s)', False )
3297 if devices is False or links is False or nodes is False or SCCs is False:
3298 main.log.warn( "Issues parsing topology and summary output" )
3299 main.log.debug( topology )
3300 main.log.debug( summary )
Jon Hall42db6dc2014-10-24 19:03:48 -04003301 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08003302 switchCheck = ( int( devices ) == int( numoswitch ) )
Jon Hall39570262020-11-17 12:18:19 -08003303 if not switchCheck:
3304 main.log.debug( "switch Check Failed" )
Pier6a0c4de2018-03-18 16:01:30 -07003305 linkCheck = ( int( links ) == int( numolink ) ) or int( numolink ) == -1
Jon Hall39570262020-11-17 12:18:19 -08003306 if not linkCheck:
3307 main.log.debug( "link Check Failed" )
Flavio Castro82ee2f62016-06-07 15:04:12 -07003308 nodeCheck = ( int( nodes ) == int( numoctrl ) ) or int( numoctrl ) == -1
Jon Hall39570262020-11-17 12:18:19 -08003309 if not nodeCheck:
3310 main.log.debug( "node Check Failed" )
3311 SCCsCheck = ( int( SCCs ) == int( numoSCCs ) ) or int( numoSCCs ) == -1
3312 if not SCCsCheck:
3313 main.log.debug( "SCCs Check Failed" )
3314 if switchCheck and linkCheck and nodeCheck and SCCsCheck:
kelvin8ec71442015-01-15 16:57:00 -08003315 # We expected the correct numbers
Jon Hall39570262020-11-17 12:18:19 -08003316 output = output + "The number of links, switches, nodes, and SCCs match "\
You Wang24139872016-05-03 11:48:47 -07003317 + "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003318 result = main.TRUE
3319 else:
You Wang24139872016-05-03 11:48:47 -07003320 output = output + \
Jon Hall39570262020-11-17 12:18:19 -08003321 "The number of links, switches, nodes, and SCCs does not match " + \
You Wang24139872016-05-03 11:48:47 -07003322 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003323 result = main.FALSE
Jon Hall39570262020-11-17 12:18:19 -08003324 output = output + "\n ONOS sees %i devices " % int( devices )
3325 output = output + "(%i expected) " % int( numoswitch )
3326 if int( numolink ) >= 0:
Pier6a0c4de2018-03-18 16:01:30 -07003327 output = output + "and %i links " % int( links )
Jon Hall39570262020-11-17 12:18:19 -08003328 output = output + "(%i expected) " % int( numolink )
3329 if int( numoctrl ) >= 0:
Flavio Castro82ee2f62016-06-07 15:04:12 -07003330 output = output + "and %i controllers " % int( nodes )
Jon Hall39570262020-11-17 12:18:19 -08003331 output = output + "(%i expected) " % int( numoctrl )
3332 if int( numoSCCs ) >= 0:
3333 output = output + "and %i SCCs " % int( SCCs )
3334 output = output + "(%i expected)" % int( numoSCCs )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003335 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08003336 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003337 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08003338 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04003339 else:
You Wang24139872016-05-03 11:48:47 -07003340 main.log.info( output )
Jon Hall39570262020-11-17 12:18:19 -08003341 main.TOPOOUTPUT = output
kelvin8ec71442015-01-15 16:57:00 -08003342 return result
Jon Hall42db6dc2014-10-24 19:03:48 -04003343 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003344 main.log.error( self.name + ": EOF exception found" )
3345 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003346 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003347 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003348 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003349 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003350
kelvin-onlabd3b64892015-01-20 13:26:24 -08003351 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08003352 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003353 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08003354 deviceId must be the id of a device as seen in the onos devices command
3355 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04003356 role must be either master, standby, or none
3357
Jon Halle3f39ff2015-01-13 11:50:53 -08003358 Returns:
3359 main.TRUE or main.FALSE based on argument verification and
3360 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003361 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003362 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003363 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04003364 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08003365 cmdStr = "device-role " +\
3366 str( deviceId ) + " " +\
3367 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003368 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003369 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003370 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003371 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08003372 if re.search( "Error", handle ):
3373 # end color output to escape any colours
3374 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08003375 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003376 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08003377 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08003378 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04003379 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003380 main.log.error( "Invalid 'role' given to device_role(). " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003381 "Value was '" + str( role ) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04003382 return main.FALSE
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 Hall1c9e8732014-10-27 19:29:27 -04003389 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 Hall1c9e8732014-10-27 19:29:27 -04003396
kelvin-onlabd3b64892015-01-20 13:26:24 -08003397 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08003398 """
Jon Hall0dd09952018-04-19 09:59:11 -07003399 Lists all topology clusters
Jon Hallffb386d2014-11-21 13:43:38 -08003400 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003401 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08003402 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08003403 try:
Jon Hall0dd09952018-04-19 09:59:11 -07003404 cmdStr = "topo-clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003405 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003406 cmdStr += " -j"
3407 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003408 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003409 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07003410 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003411 except AssertionError:
3412 main.log.exception( "" )
3413 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003414 except TypeError:
3415 main.log.exception( self.name + ": Object not as expected" )
3416 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08003417 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003418 main.log.error( self.name + ": EOF exception found" )
3419 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003420 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003421 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003422 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003423 main.cleanAndExit()
Jon Hall73cf9cc2014-11-20 22:28:38 -08003424
kelvin-onlabd3b64892015-01-20 13:26:24 -08003425 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003426 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003427 CLI command to get the current leader for the Election test application
3428 NOTE: Requires installation of the onos-app-election feature
3429 Returns: Node IP of the leader if one exists
3430 None if none exists
3431 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003432 """
Jon Hall94fd0472014-12-08 11:52:42 -08003433 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003434 cmdStr = "election-test-leader"
3435 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003436 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003437 assert "Command not found:" not in response, response
Jon Halle3f39ff2015-01-13 11:50:53 -08003438 # Leader
3439 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003440 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08003441 nodeSearch = re.search( leaderPattern, response )
3442 if nodeSearch:
3443 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08003444 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003445 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08003446 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08003447 # no leader
3448 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003449 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003450 nullSearch = re.search( nullPattern, response )
3451 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08003452 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003453 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08003454 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08003455 # error
Jon Hall0e240372018-05-02 11:21:57 -07003456 main.log.error( self.name + ": Error in electionTestLeader on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003457 ": " + "unexpected response" )
3458 main.log.error( repr( response ) )
3459 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003460 except AssertionError:
3461 main.log.exception( "" )
3462 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003463 except TypeError:
3464 main.log.exception( self.name + ": Object not as expected" )
3465 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003466 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003467 main.log.error( self.name + ": EOF exception found" )
3468 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003469 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003470 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003471 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003472 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003473
kelvin-onlabd3b64892015-01-20 13:26:24 -08003474 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003475 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003476 CLI command to run for leadership of the Election test application.
3477 NOTE: Requires installation of the onos-app-election feature
3478 Returns: Main.TRUE on success
3479 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003480 """
Jon Hall94fd0472014-12-08 11:52:42 -08003481 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003482 cmdStr = "election-test-run"
3483 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003484 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003485 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003486 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003487 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003488 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003489 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08003490 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08003491 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003492 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003493 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003494 # error
Jon Hall0e240372018-05-02 11:21:57 -07003495 main.log.error( self.name + ": Error in electionTestRun on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003496 ": " + "unexpected response" )
3497 main.log.error( repr( response ) )
3498 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003499 except AssertionError:
3500 main.log.exception( "" )
3501 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003502 except TypeError:
3503 main.log.exception( self.name + ": Object not as expected" )
3504 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003505 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003506 main.log.error( self.name + ": EOF exception found" )
3507 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003508 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003509 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003510 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003511 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003512
kelvin-onlabd3b64892015-01-20 13:26:24 -08003513 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08003514 """
Jon Hall94fd0472014-12-08 11:52:42 -08003515 * CLI command to withdraw the local node from leadership election for
3516 * the Election test application.
3517 #NOTE: Requires installation of the onos-app-election feature
3518 Returns: Main.TRUE on success
3519 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08003520 """
Jon Hall94fd0472014-12-08 11:52:42 -08003521 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003522 cmdStr = "election-test-withdraw"
3523 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003524 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003525 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003526 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003527 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003528 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003529 if re.search( successPattern, response ):
3530 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003531 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003532 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003533 # error
Jon Hall0e240372018-05-02 11:21:57 -07003534 main.log.error( self.name + ": Error in electionTestWithdraw on " +
Jon Hall97cf84a2016-06-20 13:35:58 -07003535 self.name + ": " + "unexpected response" )
3536 main.log.error( repr( response ) )
3537 return main.FALSE
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 main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -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()
Jon Hall1c9e8732014-10-27 19:29:27 -04003551
kelvin8ec71442015-01-15 16:57:00 -08003552 def getDevicePortsEnabledCount( 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:
Jon Halle3f39ff2015-01-13 11:50:53 -08003557 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003558 cmdStr = "onos:ports -e " + dpid + " | 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" )
Jon Halle3f39ff2015-01-13 11:50: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 getDeviceLinksActiveCount( self, dpid ):
3581 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003582 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003583 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003584 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003585 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003586 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003587 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003588 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003589 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003590 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003591 main.log.error( self.name + ": Error in getting ports " )
kelvin-onlab898a6c62015-01-16 14:13:53 -08003592 return ( output, "Error " )
Jon Halla495f562016-05-16 18:03:26 -07003593 return output
Jon Hallc6793552016-01-19 14:18:37 -08003594 except AssertionError:
3595 main.log.exception( "" )
3596 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003597 except TypeError:
3598 main.log.exception( self.name + ": Object not as expected" )
3599 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003600 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003601 main.log.error( self.name + ": EOF exception found" )
3602 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003603 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003604 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003605 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003606 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003607
kelvin8ec71442015-01-15 16:57:00 -08003608 def getAllIntentIds( self ):
3609 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003610 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08003611 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003612 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003613 cmdStr = "onos:intents | grep id="
3614 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003615 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003616 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003617 if re.search( "Error", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003618 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003619 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003620 return output
Jon Hallc6793552016-01-19 14:18:37 -08003621 except AssertionError:
3622 main.log.exception( "" )
3623 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003624 except TypeError:
3625 main.log.exception( self.name + ": Object not as expected" )
3626 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003627 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003628 main.log.error( self.name + ": EOF exception found" )
3629 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003630 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003631 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003632 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003633 main.cleanAndExit()
Jon Halld4d4b372015-01-28 16:02:41 -08003634
Jon Hall73509952015-02-24 16:42:56 -08003635 def intentSummary( self ):
3636 """
Jon Hallefbd9792015-03-05 16:11:36 -08003637 Returns a dictionary containing the current intent states and the count
Jon Hall73509952015-02-24 16:42:56 -08003638 """
3639 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003640 intents = self.intents( )
Jon Hall08f61bc2015-04-13 16:00:30 -07003641 states = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003642 for intent in json.loads( intents ):
Jon Hall08f61bc2015-04-13 16:00:30 -07003643 states.append( intent.get( 'state', None ) )
3644 out = [ ( i, states.count( i ) ) for i in set( states ) ]
Jon Hall63604932015-02-26 17:09:50 -08003645 main.log.info( dict( out ) )
Jon Hall73509952015-02-24 16:42:56 -08003646 return dict( out )
Jon Hallc6793552016-01-19 14:18:37 -08003647 except ( TypeError, ValueError ):
3648 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intents ) )
Jon Hall73509952015-02-24 16:42:56 -08003649 return None
3650 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 Hallfebb1c72015-03-05 13:30:09 -08003654 except Exception:
Jon Hall73509952015-02-24 16:42:56 -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
Jon Hall61282e32015-03-19 11:34:11 -07003658 def leaders( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003659 """
3660 Returns the output of the leaders command.
Jon Hall61282e32015-03-19 11:34:11 -07003661 Optional argument:
3662 * jsonFormat - boolean indicating if you want output in json
Jon Hall63604932015-02-26 17:09:50 -08003663 """
Jon Hall63604932015-02-26 17:09:50 -08003664 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003665 cmdStr = "onos:leaders"
Jon Hall61282e32015-03-19 11:34:11 -07003666 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003667 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
Jon Hallc6358dd2015-04-10 12:44:28 -07003671 return output
Jon Hallc6793552016-01-19 14:18:37 -08003672 except AssertionError:
3673 main.log.exception( "" )
3674 return None
Jon Hall63604932015-02-26 17:09:50 -08003675 except TypeError:
3676 main.log.exception( self.name + ": Object not as expected" )
3677 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003678 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()
Jon Hall77ba41c2015-04-06 10:25:40 -07003682 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003683 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003684 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003685
acsmarsa4a4d1e2015-07-10 16:01:24 -07003686 def leaderCandidates( self, jsonFormat=True ):
3687 """
3688 Returns the output of the leaders -c command.
3689 Optional argument:
3690 * jsonFormat - boolean indicating if you want output in json
3691 """
3692 try:
3693 cmdStr = "onos:leaders -c"
3694 if jsonFormat:
3695 cmdStr += " -j"
3696 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003697 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003698 assert "Command not found:" not in output, output
acsmarsa4a4d1e2015-07-10 16:01:24 -07003699 return output
Jon Hallc6793552016-01-19 14:18:37 -08003700 except AssertionError:
3701 main.log.exception( "" )
3702 return None
acsmarsa4a4d1e2015-07-10 16:01:24 -07003703 except TypeError:
3704 main.log.exception( self.name + ": Object not as expected" )
3705 return None
3706 except pexpect.EOF:
3707 main.log.error( self.name + ": EOF exception found" )
3708 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003709 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003710 except Exception:
3711 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003712 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003713
Jon Hallc6793552016-01-19 14:18:37 -08003714 def specificLeaderCandidate( self, topic ):
acsmarsa4a4d1e2015-07-10 16:01:24 -07003715 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003716 Returns a list in format [leader,candidate1,candidate2,...] for a given
acsmarsa4a4d1e2015-07-10 16:01:24 -07003717 topic parameter and an empty list if the topic doesn't exist
3718 If no leader is elected leader in the returned list will be "none"
3719 Returns None if there is a type error processing the json object
3720 """
3721 try:
Jon Hall6e709752016-02-01 13:38:46 -08003722 cmdStr = "onos:leaders -j"
Jon Hallc6793552016-01-19 14:18:37 -08003723 rawOutput = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003724 assert rawOutput is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003725 assert "Command not found:" not in rawOutput, rawOutput
3726 output = json.loads( rawOutput )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003727 results = []
3728 for dict in output:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003729 if dict[ "topic" ] == topic:
3730 leader = dict[ "leader" ]
3731 candidates = re.split( ", ", dict[ "candidates" ][ 1:-1 ] )
Jon Hallc6793552016-01-19 14:18:37 -08003732 results.append( leader )
3733 results.extend( candidates )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003734 return results
Jon Hallc6793552016-01-19 14:18:37 -08003735 except AssertionError:
3736 main.log.exception( "" )
3737 return None
3738 except ( TypeError, ValueError ):
3739 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawOutput ) )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003740 return None
3741 except pexpect.EOF:
3742 main.log.error( self.name + ": EOF exception found" )
3743 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003744 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003745 except Exception:
3746 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003747 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003748
Jon Hall61282e32015-03-19 11:34:11 -07003749 def pendingMap( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003750 """
3751 Returns the output of the intent Pending map.
3752 """
Jon Hall63604932015-02-26 17:09:50 -08003753 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003754 cmdStr = "onos:intents -p"
Jon Hall61282e32015-03-19 11:34:11 -07003755 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003756 cmdStr += " -j"
3757 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003758 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003759 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003760 return output
Jon Hallc6793552016-01-19 14:18:37 -08003761 except AssertionError:
3762 main.log.exception( "" )
3763 return None
Jon Hall63604932015-02-26 17:09:50 -08003764 except TypeError:
3765 main.log.exception( self.name + ": Object not as expected" )
3766 return None
3767 except pexpect.EOF:
3768 main.log.error( self.name + ": EOF exception found" )
3769 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003770 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003771 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003772 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003773 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003774
Jon Hall2c8959e2016-12-16 12:17:34 -08003775 def partitions( self, candidates=False, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003776 """
3777 Returns the output of the raft partitions command for ONOS.
3778 """
Jon Hall61282e32015-03-19 11:34:11 -07003779 # Sample JSON
3780 # {
3781 # "leader": "tcp://10.128.30.11:7238",
3782 # "members": [
3783 # "tcp://10.128.30.11:7238",
3784 # "tcp://10.128.30.17:7238",
3785 # "tcp://10.128.30.13:7238",
3786 # ],
3787 # "name": "p1",
3788 # "term": 3
3789 # },
Jon Hall63604932015-02-26 17:09:50 -08003790 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003791 cmdStr = "onos:partitions"
Jon Hall2c8959e2016-12-16 12:17:34 -08003792 if candidates:
3793 cmdStr += " -c"
Jon Hall61282e32015-03-19 11:34:11 -07003794 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003795 cmdStr += " -j"
3796 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003797 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003798 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003799 return output
Jon Hallc6793552016-01-19 14:18:37 -08003800 except AssertionError:
3801 main.log.exception( "" )
3802 return None
Jon Hall63604932015-02-26 17:09:50 -08003803 except TypeError:
3804 main.log.exception( self.name + ": Object not as expected" )
3805 return None
3806 except pexpect.EOF:
3807 main.log.error( self.name + ": EOF exception found" )
3808 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003809 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003810 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003811 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003812 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003813
Jon Halle9f909e2016-09-23 10:43:12 -07003814 def apps( self, summary=False, active=False, jsonFormat=True ):
Jon Hallbe379602015-03-24 13:39:32 -07003815 """
3816 Returns the output of the apps command for ONOS. This command lists
3817 information about installed ONOS applications
3818 """
3819 # Sample JSON object
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003820 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
Jon Hallbe379602015-03-24 13:39:32 -07003821 # "description":"ONOS OpenFlow protocol southbound providers",
3822 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003823 # "features":"[onos-openflow]","state":"ACTIVE"}]
Jon Hallbe379602015-03-24 13:39:32 -07003824 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003825 cmdStr = "onos:apps"
Jon Hallf03ae762019-01-22 13:25:27 -08003826 expectJson = False
Jon Halle9f909e2016-09-23 10:43:12 -07003827 if summary:
3828 cmdStr += " -s"
3829 if active:
3830 cmdStr += " -a"
Jon Hallbe379602015-03-24 13:39:32 -07003831 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003832 cmdStr += " -j"
Jon Hallf03ae762019-01-22 13:25:27 -08003833 expectJson = True
3834 output = self.sendline( cmdStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07003835 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003836 assert "Command not found:" not in output, output
3837 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003838 return output
Jon Hallbe379602015-03-24 13:39:32 -07003839 # FIXME: look at specific exceptions/Errors
3840 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07003841 main.log.exception( self.name + ": Error in processing onos:app command." )
Jon Hallbe379602015-03-24 13:39:32 -07003842 return None
3843 except TypeError:
3844 main.log.exception( self.name + ": Object not as expected" )
3845 return None
3846 except pexpect.EOF:
3847 main.log.error( self.name + ": EOF exception found" )
3848 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003849 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003850 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003851 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003852 main.cleanAndExit()
Jon Hallbe379602015-03-24 13:39:32 -07003853
You Wangcdc51fe2018-08-12 17:14:56 -07003854 def appStatus( self, appName ):
Jon Hall146f1522015-03-24 15:33:24 -07003855 """
3856 Uses the onos:apps cli command to return the status of an application.
3857 Returns:
3858 "ACTIVE" - If app is installed and activated
3859 "INSTALLED" - If app is installed and deactivated
3860 "UNINSTALLED" - If app is not installed
3861 None - on error
3862 """
Jon Hall146f1522015-03-24 15:33:24 -07003863 try:
3864 if not isinstance( appName, types.StringType ):
3865 main.log.error( self.name + ".appStatus(): appName must be" +
3866 " a string" )
3867 return None
3868 output = self.apps( jsonFormat=True )
3869 appsJson = json.loads( output )
3870 state = None
3871 for app in appsJson:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003872 if appName == app.get( 'name' ):
3873 state = app.get( 'state' )
Jon Hall146f1522015-03-24 15:33:24 -07003874 break
3875 if state == "ACTIVE" or state == "INSTALLED":
3876 return state
3877 elif state is None:
You Wang0d9f2c02018-08-10 14:56:32 -07003878 main.log.warn( "{} app not found".format( appName ) )
Jon Hall146f1522015-03-24 15:33:24 -07003879 return "UNINSTALLED"
3880 elif state:
3881 main.log.error( "Unexpected state from 'onos:apps': " +
3882 str( state ) )
3883 return state
Jon Hallc6793552016-01-19 14:18:37 -08003884 except ( TypeError, ValueError ):
3885 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003886 return None
3887 except pexpect.EOF:
3888 main.log.error( self.name + ": EOF exception found" )
3889 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003890 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003891 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003892 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003893 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003894
Jon Hallbe379602015-03-24 13:39:32 -07003895 def app( self, appName, option ):
3896 """
3897 Interacts with the app command for ONOS. This command manages
3898 application inventory.
3899 """
Jon Hallbe379602015-03-24 13:39:32 -07003900 try:
Jon Hallbd16b922015-03-26 17:53:15 -07003901 # Validate argument types
3902 valid = True
3903 if not isinstance( appName, types.StringType ):
3904 main.log.error( self.name + ".app(): appName must be a " +
3905 "string" )
3906 valid = False
3907 if not isinstance( option, types.StringType ):
3908 main.log.error( self.name + ".app(): option must be a string" )
3909 valid = False
3910 if not valid:
3911 return main.FALSE
3912 # Validate Option
3913 option = option.lower()
3914 # NOTE: Install may become a valid option
3915 if option == "activate":
3916 pass
3917 elif option == "deactivate":
3918 pass
3919 elif option == "uninstall":
3920 pass
3921 else:
3922 # Invalid option
3923 main.log.error( "The ONOS app command argument only takes " +
3924 "the values: (activate|deactivate|uninstall)" +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003925 "; was given '" + option + "'" )
Jon Hallbd16b922015-03-26 17:53:15 -07003926 return main.FALSE
Jon Hall146f1522015-03-24 15:33:24 -07003927 cmdStr = "onos:app " + option + " " + appName
Jon Hallbe379602015-03-24 13:39:32 -07003928 output = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003929 assert output is not None, "Error in sendline"
3930 assert "Command not found:" not in output, output
Jon Hallbe379602015-03-24 13:39:32 -07003931 if "Error executing command" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003932 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hallbe379602015-03-24 13:39:32 -07003933 str( output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003934 return main.FALSE
Jon Hallbe379602015-03-24 13:39:32 -07003935 elif "No such application" in output:
3936 main.log.error( "The application '" + appName +
3937 "' is not installed in ONOS" )
Jon Hall146f1522015-03-24 15:33:24 -07003938 return main.FALSE
3939 elif "Command not found:" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003940 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hall146f1522015-03-24 15:33:24 -07003941 str( output ) )
3942 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003943 elif "Unsupported command:" in output:
3944 main.log.error( "Incorrect command given to 'app': " +
3945 str( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003946 # NOTE: we may need to add more checks here
Jon Hallbd16b922015-03-26 17:53:15 -07003947 # else: Command was successful
Jon Hall08f61bc2015-04-13 16:00:30 -07003948 # main.log.debug( "app response: " + repr( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003949 return main.TRUE
You Wangb5a55f72017-03-03 12:51:05 -08003950 except AssertionError:
3951 main.log.exception( self.name + ": AssertionError exception found" )
3952 return main.ERROR
Jon Hallbe379602015-03-24 13:39:32 -07003953 except TypeError:
3954 main.log.exception( self.name + ": Object not as expected" )
3955 return main.ERROR
3956 except pexpect.EOF:
3957 main.log.error( self.name + ": EOF exception found" )
3958 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003959 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003960 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003961 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003962 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003963
Jon Hallbd16b922015-03-26 17:53:15 -07003964 def activateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003965 """
3966 Activate an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003967 appName is the hierarchical app name, not the feature name
3968 If check is True, method will check the status of the app after the
3969 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003970 Returns main.TRUE if the command was successfully sent
3971 main.FALSE if the cli responded with an error or given
3972 incorrect input
3973 """
3974 try:
3975 if not isinstance( appName, types.StringType ):
3976 main.log.error( self.name + ".activateApp(): appName must be" +
3977 " a string" )
3978 return main.FALSE
3979 status = self.appStatus( appName )
3980 if status == "INSTALLED":
3981 response = self.app( appName, "activate" )
Jon Hallbd16b922015-03-26 17:53:15 -07003982 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003983 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07003984 status = self.appStatus( appName )
3985 if status == "ACTIVE":
3986 return main.TRUE
3987 else:
Jon Hall050e1bd2015-03-30 13:33:02 -07003988 main.log.debug( "The state of application " +
3989 appName + " is " + status )
Jon Hallbd16b922015-03-26 17:53:15 -07003990 time.sleep( 1 )
3991 return main.FALSE
3992 else: # not 'check' or command didn't succeed
3993 return response
Jon Hall146f1522015-03-24 15:33:24 -07003994 elif status == "ACTIVE":
3995 return main.TRUE
3996 elif status == "UNINSTALLED":
3997 main.log.error( self.name + ": Tried to activate the " +
3998 "application '" + appName + "' which is not " +
3999 "installed." )
4000 else:
4001 main.log.error( "Unexpected return value from appStatus: " +
4002 str( status ) )
4003 return main.ERROR
4004 except TypeError:
4005 main.log.exception( self.name + ": Object not as expected" )
4006 return main.ERROR
4007 except pexpect.EOF:
4008 main.log.error( self.name + ": EOF exception found" )
4009 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004010 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004011 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004012 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004013 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004014
Jon Hallbd16b922015-03-26 17:53:15 -07004015 def deactivateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004016 """
4017 Deactivate an app that is already activated in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004018 appName is the hierarchical app name, not the feature name
4019 If check is True, method will check the status of the app after the
4020 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004021 Returns main.TRUE if the command was successfully sent
4022 main.FALSE if the cli responded with an error or given
4023 incorrect input
4024 """
4025 try:
4026 if not isinstance( appName, types.StringType ):
4027 main.log.error( self.name + ".deactivateApp(): appName must " +
4028 "be a string" )
4029 return main.FALSE
4030 status = self.appStatus( appName )
4031 if status == "INSTALLED":
4032 return main.TRUE
4033 elif status == "ACTIVE":
4034 response = self.app( appName, "deactivate" )
Jon Hallbd16b922015-03-26 17:53:15 -07004035 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004036 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004037 status = self.appStatus( appName )
4038 if status == "INSTALLED":
4039 return main.TRUE
4040 else:
4041 time.sleep( 1 )
4042 return main.FALSE
4043 else: # not check or command didn't succeed
4044 return response
Jon Hall146f1522015-03-24 15:33:24 -07004045 elif status == "UNINSTALLED":
4046 main.log.warn( self.name + ": Tried to deactivate the " +
4047 "application '" + appName + "' which is not " +
4048 "installed." )
4049 return main.TRUE
4050 else:
4051 main.log.error( "Unexpected return value from appStatus: " +
4052 str( status ) )
4053 return main.ERROR
4054 except TypeError:
4055 main.log.exception( self.name + ": Object not as expected" )
4056 return main.ERROR
4057 except pexpect.EOF:
4058 main.log.error( self.name + ": EOF exception found" )
4059 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004060 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004061 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004062 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004063 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004064
Jon Hallbd16b922015-03-26 17:53:15 -07004065 def uninstallApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004066 """
4067 Uninstall an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004068 appName is the hierarchical app name, not the feature name
4069 If check is True, method will check the status of the app after the
4070 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004071 Returns main.TRUE if the command was successfully sent
4072 main.FALSE if the cli responded with an error or given
4073 incorrect input
4074 """
4075 # TODO: check with Thomas about the state machine for apps
4076 try:
4077 if not isinstance( appName, types.StringType ):
4078 main.log.error( self.name + ".uninstallApp(): appName must " +
4079 "be a string" )
4080 return main.FALSE
4081 status = self.appStatus( appName )
4082 if status == "INSTALLED":
4083 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004084 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004085 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004086 status = self.appStatus( appName )
4087 if status == "UNINSTALLED":
4088 return main.TRUE
4089 else:
4090 time.sleep( 1 )
4091 return main.FALSE
4092 else: # not check or command didn't succeed
4093 return response
Jon Hall146f1522015-03-24 15:33:24 -07004094 elif status == "ACTIVE":
4095 main.log.warn( self.name + ": Tried to uninstall the " +
4096 "application '" + appName + "' which is " +
4097 "currently active." )
4098 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004099 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004100 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004101 status = self.appStatus( appName )
4102 if status == "UNINSTALLED":
4103 return main.TRUE
4104 else:
4105 time.sleep( 1 )
4106 return main.FALSE
4107 else: # not check or command didn't succeed
4108 return response
Jon Hall146f1522015-03-24 15:33:24 -07004109 elif status == "UNINSTALLED":
4110 return main.TRUE
4111 else:
4112 main.log.error( "Unexpected return value from appStatus: " +
4113 str( status ) )
4114 return main.ERROR
4115 except TypeError:
4116 main.log.exception( self.name + ": Object not as expected" )
4117 return main.ERROR
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 Hall146f1522015-03-24 15:33:24 -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 appIDs( self, jsonFormat=True ):
4127 """
4128 Show the mappings between app id and app names given by the 'app-ids'
4129 cli command
4130 """
4131 try:
4132 cmdStr = "app-ids"
4133 if jsonFormat:
4134 cmdStr += " -j"
Jon Hallc6358dd2015-04-10 12:44:28 -07004135 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004136 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004137 assert "Command not found:" not in output, output
4138 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07004139 return output
Jon Hallbd16b922015-03-26 17:53:15 -07004140 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004141 main.log.exception( self.name + ": Error in processing onos:app-ids command." )
Jon Hallbd16b922015-03-26 17:53:15 -07004142 return None
4143 except TypeError:
4144 main.log.exception( self.name + ": Object not as expected" )
4145 return None
4146 except pexpect.EOF:
4147 main.log.error( self.name + ": EOF exception found" )
4148 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004149 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004150 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004151 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004152 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004153
4154 def appToIDCheck( self ):
4155 """
4156 This method will check that each application's ID listed in 'apps' is
4157 the same as the ID listed in 'app-ids'. The check will also check that
4158 there are no duplicate IDs issued. Note that an app ID should be
4159 a globaly unique numerical identifier for app/app-like features. Once
4160 an ID is registered, the ID is never freed up so that if an app is
4161 reinstalled it will have the same ID.
4162
4163 Returns: main.TRUE if the check passes and
4164 main.FALSE if the check fails or
4165 main.ERROR if there is some error in processing the test
4166 """
4167 try:
Jon Hall0e240372018-05-02 11:21:57 -07004168 # Grab IDs
Jon Hallc6793552016-01-19 14:18:37 -08004169 rawJson = self.appIDs( jsonFormat=True )
4170 if rawJson:
4171 ids = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004172 else:
Jon Hall0e240372018-05-02 11:21:57 -07004173 main.log.error( "app-ids returned nothing: " + repr( rawJson ) )
4174 return main.FALSE
4175
4176 # Grab Apps
Jon Hallc6793552016-01-19 14:18:37 -08004177 rawJson = self.apps( jsonFormat=True )
4178 if rawJson:
4179 apps = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004180 else:
Jon Hallc6793552016-01-19 14:18:37 -08004181 main.log.error( "apps returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07004182 return main.FALSE
Jon Hall0e240372018-05-02 11:21:57 -07004183
Jon Hallbd16b922015-03-26 17:53:15 -07004184 result = main.TRUE
4185 for app in apps:
4186 appID = app.get( 'id' )
4187 if appID is None:
4188 main.log.error( "Error parsing app: " + str( app ) )
4189 result = main.FALSE
4190 appName = app.get( 'name' )
4191 if appName is None:
4192 main.log.error( "Error parsing app: " + str( app ) )
4193 result = main.FALSE
4194 # get the entry in ids that has the same appID
Jon Hall390696c2015-05-05 17:13:41 -07004195 current = filter( lambda item: item[ 'id' ] == appID, ids )
Jon Hallbd16b922015-03-26 17:53:15 -07004196 if not current: # if ids doesn't have this id
4197 result = main.FALSE
4198 main.log.error( "'app-ids' does not have the ID for " +
4199 str( appName ) + " that apps does." )
Jon Hallb9d381e2018-02-05 12:02:10 -08004200 main.log.debug( "apps command returned: " + str( app ) +
4201 "; app-ids has: " + str( ids ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004202 elif len( current ) > 1:
4203 # there is more than one app with this ID
4204 result = main.FALSE
4205 # We will log this later in the method
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004206 elif not current[ 0 ][ 'name' ] == appName:
4207 currentName = current[ 0 ][ 'name' ]
Jon Hallbd16b922015-03-26 17:53:15 -07004208 result = main.FALSE
4209 main.log.error( "'app-ids' has " + str( currentName ) +
4210 " registered under id:" + str( appID ) +
4211 " but 'apps' has " + str( appName ) )
4212 else:
4213 pass # id and name match!
Jon Hall0e240372018-05-02 11:21:57 -07004214
Jon Hallbd16b922015-03-26 17:53:15 -07004215 # now make sure that app-ids has no duplicates
4216 idsList = []
4217 namesList = []
4218 for item in ids:
4219 idsList.append( item[ 'id' ] )
4220 namesList.append( item[ 'name' ] )
4221 if len( idsList ) != len( set( idsList ) ) or\
4222 len( namesList ) != len( set( namesList ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004223 main.log.error( "'app-ids' has some duplicate entries: \n"
4224 + json.dumps( ids,
4225 sort_keys=True,
4226 indent=4,
4227 separators=( ',', ': ' ) ) )
4228 result = main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07004229 return result
Jon Hallc6793552016-01-19 14:18:37 -08004230 except ( TypeError, ValueError ):
4231 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004232 return main.ERROR
4233 except pexpect.EOF:
4234 main.log.error( self.name + ": EOF exception found" )
4235 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004236 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004237 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004238 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004239 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004240
Jon Hallfb760a02015-04-13 15:35:03 -07004241 def getCfg( self, component=None, propName=None, short=False,
4242 jsonFormat=True ):
4243 """
4244 Get configuration settings from onos cli
4245 Optional arguments:
4246 component - Optionally only list configurations for a specific
4247 component. If None, all components with configurations
4248 are displayed. Case Sensitive string.
4249 propName - If component is specified, propName option will show
4250 only this specific configuration from that component.
4251 Case Sensitive string.
4252 jsonFormat - Returns output as json. Note that this will override
4253 the short option
4254 short - Short, less verbose, version of configurations.
4255 This is overridden by the json option
4256 returns:
4257 Output from cli as a string or None on error
4258 """
4259 try:
4260 baseStr = "cfg"
4261 cmdStr = " get"
4262 componentStr = ""
4263 if component:
4264 componentStr += " " + component
4265 if propName:
4266 componentStr += " " + propName
4267 if jsonFormat:
4268 baseStr += " -j"
Jon Hall22e94ce2019-01-15 14:52:17 -08004269 expectJson = True
Jon Hallfb760a02015-04-13 15:35:03 -07004270 elif short:
4271 baseStr += " -s"
Jon Hall22e94ce2019-01-15 14:52:17 -08004272 expectJson = False
4273 output = self.sendline( baseStr + cmdStr + componentStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07004274 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004275 assert "Command not found:" not in output, output
4276 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004277 return output
4278 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004279 main.log.exception( self.name + ": Error in processing 'cfg get' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004280 return None
4281 except TypeError:
4282 main.log.exception( self.name + ": Object not as expected" )
4283 return None
4284 except pexpect.EOF:
4285 main.log.error( self.name + ": EOF exception found" )
4286 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004287 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004288 except Exception:
4289 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004290 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004291
4292 def setCfg( self, component, propName, value=None, check=True ):
4293 """
4294 Set/Unset configuration settings from ONOS cli
Jon Hall390696c2015-05-05 17:13:41 -07004295 Required arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004296 component - The case sensitive name of the component whose
4297 property is to be set
4298 propName - The case sensitive name of the property to be set/unset
Jon Hall390696c2015-05-05 17:13:41 -07004299 Optional arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004300 value - The value to set the property to. If None, will unset the
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004301 property and revert it to it's default value(if applicable)
Jon Hallfb760a02015-04-13 15:35:03 -07004302 check - Boolean, Check whether the option was successfully set this
4303 only applies when a value is given.
4304 returns:
4305 main.TRUE on success or main.FALSE on failure. If check is False,
4306 will return main.TRUE unless there is an error
4307 """
4308 try:
4309 baseStr = "cfg"
4310 cmdStr = " set " + str( component ) + " " + str( propName )
4311 if value is not None:
4312 cmdStr += " " + str( value )
4313 output = self.sendline( baseStr + cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004314 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004315 assert "Command not found:" not in output, output
4316 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004317 if value and check:
4318 results = self.getCfg( component=str( component ),
4319 propName=str( propName ),
4320 jsonFormat=True )
4321 # Check if current value is what we just set
4322 try:
4323 jsonOutput = json.loads( results )
4324 current = jsonOutput[ 'value' ]
Jon Hallc6793552016-01-19 14:18:37 -08004325 except ( TypeError, ValueError ):
Jon Hallfb760a02015-04-13 15:35:03 -07004326 main.log.exception( "Error parsing cfg output" )
4327 main.log.error( "output:" + repr( results ) )
4328 return main.FALSE
4329 if current == str( value ):
4330 return main.TRUE
4331 return main.FALSE
4332 return main.TRUE
4333 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004334 main.log.exception( self.name + ": Error in processing 'cfg set' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004335 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08004336 except ( TypeError, ValueError ):
4337 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, results ) )
Jon Hallfb760a02015-04-13 15:35:03 -07004338 return main.FALSE
4339 except pexpect.EOF:
4340 main.log.error( self.name + ": EOF exception found" )
4341 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004342 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004343 except Exception:
4344 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004345 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004346
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004347 def distPrimitivesSend( self, cmd ):
4348 """
4349 Function to handle sending cli commands for the distributed primitives test app
4350
4351 This command will catch some exceptions and retry the command on some
4352 specific store exceptions.
4353
4354 Required arguments:
4355 cmd - The command to send to the cli
4356 returns:
4357 string containing the cli output
4358 None on Error
4359 """
4360 try:
4361 output = self.sendline( cmd )
4362 try:
4363 assert output is not None, "Error in sendline"
4364 # TODO: Maybe make this less hardcoded
4365 # ConsistentMap Exceptions
4366 assert "org.onosproject.store.service" not in output
4367 # Node not leader
4368 assert "java.lang.IllegalStateException" not in output
4369 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004370 main.log.error( self.name + ": Error in processing '" + cmd + "' " +
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004371 "command: " + str( output ) )
4372 retryTime = 30 # Conservative time, given by Madan
4373 main.log.info( "Waiting " + str( retryTime ) +
4374 "seconds before retrying." )
4375 time.sleep( retryTime ) # Due to change in mastership
4376 output = self.sendline( cmd )
4377 assert output is not None, "Error in sendline"
4378 assert "Command not found:" not in output, output
4379 assert "Error executing command" not in output, output
4380 main.log.info( self.name + ": " + output )
4381 return output
4382 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004383 main.log.exception( self.name + ": Error in processing '" + cmd + "' command." )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004384 return None
4385 except TypeError:
4386 main.log.exception( self.name + ": Object not as expected" )
4387 return None
4388 except pexpect.EOF:
4389 main.log.error( self.name + ": EOF exception found" )
4390 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004391 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004392 except Exception:
4393 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004394 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004395
Jon Hall390696c2015-05-05 17:13:41 -07004396 def setTestAdd( self, setName, values ):
4397 """
4398 CLI command to add elements to a distributed set.
4399 Arguments:
4400 setName - The name of the set to add to.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004401 values - The value(s) to add to the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004402 Example usages:
4403 setTestAdd( "set1", "a b c" )
4404 setTestAdd( "set2", "1" )
4405 returns:
4406 main.TRUE on success OR
4407 main.FALSE if elements were already in the set OR
4408 main.ERROR on error
4409 """
4410 try:
4411 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004412 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004413 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
4414 negativeMatch = "\[(.*)\] was already in set " + str( setName )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004415 if re.search( positiveMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004416 return main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004417 elif re.search( negativeMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004418 return main.FALSE
4419 else:
4420 main.log.error( self.name + ": setTestAdd did not" +
4421 " match expected output" )
Jon Hall390696c2015-05-05 17:13:41 -07004422 main.log.debug( self.name + " actual: " + repr( output ) )
4423 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004424 except TypeError:
4425 main.log.exception( self.name + ": Object not as expected" )
4426 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004427 except Exception:
4428 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004429 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004430
4431 def setTestRemove( self, setName, values, clear=False, retain=False ):
4432 """
4433 CLI command to remove elements from a distributed set.
4434 Required arguments:
4435 setName - The name of the set to remove from.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004436 values - The value(s) to remove from the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004437 Optional arguments:
4438 clear - Clear all elements from the set
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004439 retain - Retain only the given values. (intersection of the
4440 original set and the given set)
Jon Hall390696c2015-05-05 17:13:41 -07004441 returns:
4442 main.TRUE on success OR
4443 main.FALSE if the set was not changed OR
4444 main.ERROR on error
4445 """
4446 try:
4447 cmdStr = "set-test-remove "
4448 if clear:
4449 cmdStr += "-c " + str( setName )
4450 elif retain:
4451 cmdStr += "-r " + str( setName ) + " " + str( values )
4452 else:
4453 cmdStr += str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004454 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004455 if clear:
4456 pattern = "Set " + str( setName ) + " cleared"
4457 if re.search( pattern, output ):
4458 return main.TRUE
4459 elif retain:
4460 positivePattern = str( setName ) + " was pruned to contain " +\
4461 "only elements of set \[(.*)\]"
4462 negativePattern = str( setName ) + " was not changed by " +\
4463 "retaining only elements of the set " +\
4464 "\[(.*)\]"
4465 if re.search( positivePattern, output ):
4466 return main.TRUE
4467 elif re.search( negativePattern, output ):
4468 return main.FALSE
4469 else:
4470 positivePattern = "\[(.*)\] was removed from the set " +\
4471 str( setName )
4472 if ( len( values.split() ) == 1 ):
4473 negativePattern = "\[(.*)\] was not in set " +\
4474 str( setName )
4475 else:
4476 negativePattern = "No element of \[(.*)\] was in set " +\
4477 str( setName )
4478 if re.search( positivePattern, output ):
4479 return main.TRUE
4480 elif re.search( negativePattern, output ):
4481 return main.FALSE
4482 main.log.error( self.name + ": setTestRemove did not" +
4483 " match expected output" )
4484 main.log.debug( self.name + " expected: " + pattern )
4485 main.log.debug( self.name + " actual: " + repr( output ) )
4486 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004487 except TypeError:
4488 main.log.exception( self.name + ": Object not as expected" )
4489 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004490 except Exception:
4491 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004492 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004493
4494 def setTestGet( self, setName, values="" ):
4495 """
4496 CLI command to get the elements in a distributed set.
4497 Required arguments:
4498 setName - The name of the set to remove from.
4499 Optional arguments:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004500 values - The value(s) to check if in the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004501 returns:
4502 main.ERROR on error OR
4503 A list of elements in the set if no optional arguments are
4504 supplied OR
4505 A tuple containing the list then:
4506 main.FALSE if the given values are not in the set OR
4507 main.TRUE if the given values are in the set OR
4508 """
4509 try:
4510 values = str( values ).strip()
4511 setName = str( setName ).strip()
4512 length = len( values.split() )
4513 containsCheck = None
4514 # Patterns to match
4515 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004516 pattern = "Items in set " + setName + ":\r\n" + setPattern
Jon Hall390696c2015-05-05 17:13:41 -07004517 containsTrue = "Set " + setName + " contains the value " + values
4518 containsFalse = "Set " + setName + " did not contain the value " +\
4519 values
4520 containsAllTrue = "Set " + setName + " contains the the subset " +\
4521 setPattern
4522 containsAllFalse = "Set " + setName + " did not contain the the" +\
4523 " subset " + setPattern
4524
4525 cmdStr = "set-test-get "
4526 cmdStr += setName + " " + values
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004527 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004528 if length == 0:
4529 match = re.search( pattern, output )
4530 else: # if given values
4531 if length == 1: # Contains output
Jon Hall54b994f2016-12-05 10:48:59 -08004532 patternTrue = pattern + "\r\n" + containsTrue
4533 patternFalse = pattern + "\r\n" + containsFalse
Jon Hall390696c2015-05-05 17:13:41 -07004534 else: # ContainsAll output
Jon Hall54b994f2016-12-05 10:48:59 -08004535 patternTrue = pattern + "\r\n" + containsAllTrue
4536 patternFalse = pattern + "\r\n" + containsAllFalse
Jon Hall390696c2015-05-05 17:13:41 -07004537 matchTrue = re.search( patternTrue, output )
4538 matchFalse = re.search( patternFalse, output )
4539 if matchTrue:
4540 containsCheck = main.TRUE
4541 match = matchTrue
4542 elif matchFalse:
4543 containsCheck = main.FALSE
4544 match = matchFalse
4545 else:
Jon Halle0f0b342017-04-18 11:43:47 -07004546 main.log.error( self.name + " setTestGet did not match " +
Jon Hall390696c2015-05-05 17:13:41 -07004547 "expected output" )
4548 main.log.debug( self.name + " expected: " + pattern )
4549 main.log.debug( self.name + " actual: " + repr( output ) )
4550 match = None
4551 if match:
4552 setMatch = match.group( 1 )
4553 if setMatch == '':
4554 setList = []
4555 else:
4556 setList = setMatch.split( ", " )
4557 if length > 0:
4558 return ( setList, containsCheck )
4559 else:
4560 return setList
4561 else: # no match
4562 main.log.error( self.name + ": setTestGet did not" +
4563 " match expected output" )
4564 main.log.debug( self.name + " expected: " + pattern )
4565 main.log.debug( self.name + " actual: " + repr( output ) )
4566 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004567 except TypeError:
4568 main.log.exception( self.name + ": Object not as expected" )
4569 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004570 except Exception:
4571 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004572 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004573
4574 def setTestSize( self, setName ):
4575 """
4576 CLI command to get the elements in a distributed set.
4577 Required arguments:
4578 setName - The name of the set to remove from.
4579 returns:
Jon Hallfeff3082015-05-19 10:23:26 -07004580 The integer value of the size returned or
Jon Hall390696c2015-05-05 17:13:41 -07004581 None on error
4582 """
4583 try:
4584 # TODO: Should this check against the number of elements returned
4585 # and then return true/false based on that?
4586 setName = str( setName ).strip()
4587 # Patterns to match
4588 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004589 pattern = "There are (\d+) items in set " + setName + ":\r\n" +\
Jon Hall390696c2015-05-05 17:13:41 -07004590 setPattern
4591 cmdStr = "set-test-get -s "
4592 cmdStr += setName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004593 output = self.distPrimitivesSend( cmdStr )
Jon Hall0e240372018-05-02 11:21:57 -07004594 if output:
4595 match = re.search( pattern, output )
4596 if match:
4597 setSize = int( match.group( 1 ) )
4598 setMatch = match.group( 2 )
4599 if len( setMatch.split() ) == setSize:
4600 main.log.info( "The size returned by " + self.name +
4601 " matches the number of elements in " +
4602 "the returned set" )
4603 else:
4604 main.log.error( "The size returned by " + self.name +
4605 " does not match the number of " +
4606 "elements in the returned set." )
4607 return setSize
Jon Hall390696c2015-05-05 17:13:41 -07004608 else: # no match
4609 main.log.error( self.name + ": setTestGet did not" +
4610 " match expected output" )
4611 main.log.debug( self.name + " expected: " + pattern )
4612 main.log.debug( self.name + " actual: " + repr( output ) )
4613 return None
Jon Hall390696c2015-05-05 17:13:41 -07004614 except TypeError:
4615 main.log.exception( self.name + ": Object not as expected" )
4616 return None
Jon Hall390696c2015-05-05 17:13:41 -07004617 except Exception:
4618 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004619 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004620
Jon Hall80daded2015-05-27 16:07:00 -07004621 def counters( self, jsonFormat=True ):
Jon Hall390696c2015-05-05 17:13:41 -07004622 """
4623 Command to list the various counters in the system.
4624 returns:
Jon Hall80daded2015-05-27 16:07:00 -07004625 if jsonFormat, a string of the json object returned by the cli
4626 command
4627 if not jsonFormat, the normal string output of the cli command
Jon Hall390696c2015-05-05 17:13:41 -07004628 None on error
4629 """
Jon Hall390696c2015-05-05 17:13:41 -07004630 try:
Jon Hall390696c2015-05-05 17:13:41 -07004631 cmdStr = "counters"
Jon Hall80daded2015-05-27 16:07:00 -07004632 if jsonFormat:
4633 cmdStr += " -j"
Jon Hall390696c2015-05-05 17:13:41 -07004634 output = self.sendline( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004635 main.log.debug( self.name + ": Counters unparsed: " + output )
4636 output = output.split( "\r\n" )[ -1 ]
4637 main.log.debug( self.name + ": Counters parsed: " + output )
Jon Halla495f562016-05-16 18:03:26 -07004638 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004639 assert "Command not found:" not in output, output
4640 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004641 main.log.info( self.name + ": " + output )
Jon Hall80daded2015-05-27 16:07:00 -07004642 return output
Jon Hall390696c2015-05-05 17:13:41 -07004643 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004644 main.log.exception( self.name + ": Error in processing 'counters' command." )
Jon Hall80daded2015-05-27 16:07:00 -07004645 return None
Jon Hall390696c2015-05-05 17:13:41 -07004646 except TypeError:
4647 main.log.exception( self.name + ": Object not as expected" )
Jon Hall80daded2015-05-27 16:07:00 -07004648 return None
Jon Hall390696c2015-05-05 17:13:41 -07004649 except pexpect.EOF:
4650 main.log.error( self.name + ": EOF exception found" )
4651 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004652 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004653 except Exception:
4654 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004655 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004656
Jon Hall935db192016-04-19 00:22:04 -07004657 def counterTestAddAndGet( self, counter, delta=1 ):
Jon Hall390696c2015-05-05 17:13:41 -07004658 """
Jon Halle1a3b752015-07-22 13:02:46 -07004659 CLI command to add a delta to then get a distributed counter.
Jon Hall390696c2015-05-05 17:13:41 -07004660 Required arguments:
4661 counter - The name of the counter to increment.
4662 Optional arguments:
Jon Halle1a3b752015-07-22 13:02:46 -07004663 delta - The long to add to the counter
Jon Hall390696c2015-05-05 17:13:41 -07004664 returns:
4665 integer value of the counter or
4666 None on Error
4667 """
4668 try:
4669 counter = str( counter )
Jon Halle1a3b752015-07-22 13:02:46 -07004670 delta = int( delta )
Jon Hall390696c2015-05-05 17:13:41 -07004671 cmdStr = "counter-test-increment "
Jon Hall390696c2015-05-05 17:13:41 -07004672 cmdStr += counter
Jon Halle1a3b752015-07-22 13:02:46 -07004673 if delta != 1:
4674 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004675 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004676 pattern = counter + " was updated to (-?\d+)"
Jon Hall390696c2015-05-05 17:13:41 -07004677 match = re.search( pattern, output )
4678 if match:
4679 return int( match.group( 1 ) )
4680 else:
Jon Halle1a3b752015-07-22 13:02:46 -07004681 main.log.error( self.name + ": counterTestAddAndGet did not" +
Jon Hall390696c2015-05-05 17:13:41 -07004682 " match expected output." )
4683 main.log.debug( self.name + " expected: " + pattern )
4684 main.log.debug( self.name + " actual: " + repr( output ) )
4685 return None
Jon Hall390696c2015-05-05 17:13:41 -07004686 except TypeError:
4687 main.log.exception( self.name + ": Object not as expected" )
4688 return None
Jon Hall390696c2015-05-05 17:13:41 -07004689 except Exception:
4690 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004691 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004692
Jon Hall935db192016-04-19 00:22:04 -07004693 def counterTestGetAndAdd( self, counter, delta=1 ):
Jon Halle1a3b752015-07-22 13:02:46 -07004694 """
4695 CLI command to get a distributed counter then add a delta to it.
4696 Required arguments:
4697 counter - The name of the counter to increment.
4698 Optional arguments:
4699 delta - The long to add to the counter
Jon Halle1a3b752015-07-22 13:02:46 -07004700 returns:
4701 integer value of the counter or
4702 None on Error
4703 """
4704 try:
4705 counter = str( counter )
4706 delta = int( delta )
4707 cmdStr = "counter-test-increment -g "
Jon Halle1a3b752015-07-22 13:02:46 -07004708 cmdStr += counter
4709 if delta != 1:
4710 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004711 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004712 pattern = counter + " was updated to (-?\d+)"
4713 match = re.search( pattern, output )
4714 if match:
4715 return int( match.group( 1 ) )
4716 else:
4717 main.log.error( self.name + ": counterTestGetAndAdd did not" +
4718 " match expected output." )
4719 main.log.debug( self.name + " expected: " + pattern )
4720 main.log.debug( self.name + " actual: " + repr( output ) )
4721 return None
Jon Halle1a3b752015-07-22 13:02:46 -07004722 except TypeError:
4723 main.log.exception( self.name + ": Object not as expected" )
4724 return None
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004725 except Exception:
4726 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004727 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004728
4729 def valueTestGet( self, valueName ):
4730 """
4731 CLI command to get the value of an atomic value.
4732 Required arguments:
4733 valueName - The name of the value to get.
4734 returns:
4735 string value of the value or
4736 None on Error
4737 """
4738 try:
4739 valueName = str( valueName )
4740 cmdStr = "value-test "
4741 operation = "get"
4742 cmdStr = "value-test {} {}".format( valueName,
4743 operation )
4744 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004745 main.log.debug( self.name + ": value test unparsed: " + output )
4746 output = output.split( "\r\n" )[ -1 ]
4747 main.log.debug( self.name + ": value test parsed: " + output )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004748 pattern = "(\w+)"
4749 match = re.search( pattern, output )
4750 if match:
4751 return match.group( 1 )
4752 else:
4753 main.log.error( self.name + ": valueTestGet did not" +
4754 " match expected output." )
4755 main.log.debug( self.name + " expected: " + pattern )
4756 main.log.debug( self.name + " actual: " + repr( output ) )
4757 return None
4758 except TypeError:
4759 main.log.exception( self.name + ": Object not as expected" )
4760 return None
4761 except Exception:
4762 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004763 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004764
4765 def valueTestSet( self, valueName, newValue ):
4766 """
4767 CLI command to set the value of an atomic value.
4768 Required arguments:
4769 valueName - The name of the value to set.
4770 newValue - The value to assign to the given value.
4771 returns:
4772 main.TRUE on success or
4773 main.ERROR on Error
4774 """
4775 try:
4776 valueName = str( valueName )
4777 newValue = str( newValue )
4778 operation = "set"
4779 cmdStr = "value-test {} {} {}".format( valueName,
4780 operation,
4781 newValue )
4782 output = self.distPrimitivesSend( cmdStr )
4783 if output is not None:
4784 return main.TRUE
4785 else:
4786 return main.ERROR
4787 except TypeError:
4788 main.log.exception( self.name + ": Object not as expected" )
4789 return main.ERROR
4790 except Exception:
4791 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004792 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004793
4794 def valueTestCompareAndSet( self, valueName, oldValue, newValue ):
4795 """
4796 CLI command to compareAndSet the value of an atomic value.
4797 Required arguments:
4798 valueName - The name of the value.
4799 oldValue - Compare the current value of the atomic value to this
4800 newValue - If the value equals oldValue, set the value to newValue
4801 returns:
4802 main.TRUE on success or
4803 main.FALSE on failure or
4804 main.ERROR on Error
4805 """
4806 try:
4807 valueName = str( valueName )
4808 oldValue = str( oldValue )
4809 newValue = str( newValue )
4810 operation = "compareAndSet"
4811 cmdStr = "value-test {} {} {} {}".format( valueName,
4812 operation,
4813 oldValue,
4814 newValue )
4815 output = self.distPrimitivesSend( cmdStr )
4816 pattern = "(\w+)"
4817 match = re.search( pattern, output )
4818 if match:
4819 result = match.group( 1 )
4820 if result == "true":
4821 return main.TRUE
4822 elif result == "false":
4823 return main.FALSE
4824 else:
4825 main.log.error( self.name + ": valueTestCompareAndSet did not" +
4826 " match expected output." )
4827 main.log.debug( self.name + " expected: " + pattern )
4828 main.log.debug( self.name + " actual: " + repr( output ) )
4829 return main.ERROR
4830 except TypeError:
4831 main.log.exception( self.name + ": Object not as expected" )
4832 return main.ERROR
4833 except Exception:
4834 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004835 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004836
4837 def valueTestGetAndSet( self, valueName, newValue ):
4838 """
4839 CLI command to getAndSet the value of an atomic value.
4840 Required arguments:
4841 valueName - The name of the value to get.
4842 newValue - The value to assign to the given value
4843 returns:
4844 string value of the value or
4845 None on Error
4846 """
4847 try:
4848 valueName = str( valueName )
4849 cmdStr = "value-test "
4850 operation = "getAndSet"
4851 cmdStr += valueName + " " + operation
4852 cmdStr = "value-test {} {} {}".format( valueName,
4853 operation,
4854 newValue )
4855 output = self.distPrimitivesSend( cmdStr )
4856 pattern = "(\w+)"
4857 match = re.search( pattern, output )
4858 if match:
4859 return match.group( 1 )
4860 else:
4861 main.log.error( self.name + ": valueTestGetAndSet did not" +
4862 " match expected output." )
4863 main.log.debug( self.name + " expected: " + pattern )
4864 main.log.debug( self.name + " actual: " + repr( output ) )
4865 return None
4866 except TypeError:
4867 main.log.exception( self.name + ": Object not as expected" )
4868 return None
4869 except Exception:
4870 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004871 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004872
4873 def valueTestDestroy( self, valueName ):
4874 """
4875 CLI command to destroy an atomic value.
4876 Required arguments:
4877 valueName - The name of the value to destroy.
4878 returns:
4879 main.TRUE on success or
4880 main.ERROR on Error
4881 """
4882 try:
4883 valueName = str( valueName )
4884 cmdStr = "value-test "
4885 operation = "destroy"
4886 cmdStr += valueName + " " + operation
4887 output = self.distPrimitivesSend( cmdStr )
4888 if output is not None:
4889 return main.TRUE
4890 else:
4891 return main.ERROR
4892 except TypeError:
4893 main.log.exception( self.name + ": Object not as expected" )
4894 return main.ERROR
Jon Halle1a3b752015-07-22 13:02:46 -07004895 except Exception:
4896 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004897 main.cleanAndExit()
Jon Halle1a3b752015-07-22 13:02:46 -07004898
YPZhangfebf7302016-05-24 16:45:56 -07004899 def summary( self, jsonFormat=True, timeout=30 ):
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004900 """
4901 Description: Execute summary command in onos
4902 Returns: json object ( summary -j ), returns main.FALSE if there is
4903 no output
4904
4905 """
4906 try:
4907 cmdStr = "summary"
4908 if jsonFormat:
4909 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07004910 handle = self.sendline( cmdStr, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07004911 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004912 assert "Command not found:" not in handle, handle
Jon Hall6e709752016-02-01 13:38:46 -08004913 assert "Error:" not in handle, handle
Devin Lima7cfdbd2017-09-29 15:02:22 -07004914 assert "Error executing" not in handle, handle
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004915 if not handle:
4916 main.log.error( self.name + ": There is no output in " +
4917 "summary command" )
4918 return main.FALSE
4919 return handle
Jon Hallc6793552016-01-19 14:18:37 -08004920 except AssertionError:
Jon Hall6e709752016-02-01 13:38:46 -08004921 main.log.exception( "{} Error in summary output:".format( self.name ) )
Jon Hallc6793552016-01-19 14:18:37 -08004922 return None
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004923 except TypeError:
4924 main.log.exception( self.name + ": Object not as expected" )
4925 return None
4926 except pexpect.EOF:
4927 main.log.error( self.name + ": EOF exception found" )
4928 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004929 main.cleanAndExit()
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004930 except Exception:
4931 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004932 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004933
Jon Hall935db192016-04-19 00:22:04 -07004934 def transactionalMapGet( self, keyName ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004935 """
4936 CLI command to get the value of a key in a consistent map using
4937 transactions. This a test function and can only get keys from the
4938 test map hard coded into the cli command
4939 Required arguments:
4940 keyName - The name of the key to get
Jon Hall2a5002c2015-08-21 16:49:11 -07004941 returns:
4942 The string value of the key or
4943 None on Error
4944 """
4945 try:
4946 keyName = str( keyName )
4947 cmdStr = "transactional-map-test-get "
Jon Hall2a5002c2015-08-21 16:49:11 -07004948 cmdStr += keyName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004949 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07004950 pattern = "Key-value pair \(" + keyName + ", (?P<value>.+)\) found."
4951 if "Key " + keyName + " not found." in output:
Jon Hall9bfadd22016-05-11 14:48:07 -07004952 main.log.warn( output )
Jon Hall2a5002c2015-08-21 16:49:11 -07004953 return None
4954 else:
4955 match = re.search( pattern, output )
4956 if match:
4957 return match.groupdict()[ 'value' ]
4958 else:
4959 main.log.error( self.name + ": transactionlMapGet did not" +
4960 " match expected output." )
4961 main.log.debug( self.name + " expected: " + pattern )
4962 main.log.debug( self.name + " actual: " + repr( output ) )
4963 return None
4964 except TypeError:
4965 main.log.exception( self.name + ": Object not as expected" )
4966 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004967 except Exception:
4968 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004969 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004970
Jon Hall935db192016-04-19 00:22:04 -07004971 def transactionalMapPut( self, numKeys, value ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004972 """
4973 CLI command to put a value into 'numKeys' number of keys in a
4974 consistent map using transactions. This a test function and can only
4975 put into keys named 'Key#' of the test map hard coded into the cli command
4976 Required arguments:
4977 numKeys - Number of keys to add the value to
4978 value - The string value to put into the keys
Jon Hall2a5002c2015-08-21 16:49:11 -07004979 returns:
4980 A dictionary whose keys are the name of the keys put into the map
4981 and the values of the keys are dictionaries whose key-values are
4982 'value': value put into map and optionaly
4983 'oldValue': Previous value in the key or
4984 None on Error
4985
4986 Example output
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004987 { 'Key1': {'oldValue': 'oldTestValue', 'value': 'Testing'},
4988 'Key2': {'value': 'Testing'} }
Jon Hall2a5002c2015-08-21 16:49:11 -07004989 """
4990 try:
4991 numKeys = str( numKeys )
4992 value = str( value )
4993 cmdStr = "transactional-map-test-put "
Jon Hall2a5002c2015-08-21 16:49:11 -07004994 cmdStr += numKeys + " " + value
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004995 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07004996 newPattern = 'Created Key (?P<key>(\w)+) with value (?P<value>(.)+)\.'
4997 updatedPattern = "Put (?P<value>(.)+) into key (?P<key>(\w)+)\. The old value was (?P<oldValue>(.)+)\."
4998 results = {}
4999 for line in output.splitlines():
5000 new = re.search( newPattern, line )
5001 updated = re.search( updatedPattern, line )
5002 if new:
5003 results[ new.groupdict()[ 'key' ] ] = { 'value': new.groupdict()[ 'value' ] }
5004 elif updated:
5005 results[ updated.groupdict()[ 'key' ] ] = { 'value': updated.groupdict()[ 'value' ],
Jon Hallc6793552016-01-19 14:18:37 -08005006 'oldValue': updated.groupdict()[ 'oldValue' ] }
Jon Hall2a5002c2015-08-21 16:49:11 -07005007 else:
5008 main.log.error( self.name + ": transactionlMapGet did not" +
5009 " match expected output." )
Jon Hallc6793552016-01-19 14:18:37 -08005010 main.log.debug( "{} expected: {!r} or {!r}".format( self.name,
5011 newPattern,
5012 updatedPattern ) )
Jon Hall2a5002c2015-08-21 16:49:11 -07005013 main.log.debug( self.name + " actual: " + repr( output ) )
5014 return results
Jon Hall0e240372018-05-02 11:21:57 -07005015 except ( TypeError, AttributeError ):
Jon Hall2a5002c2015-08-21 16:49:11 -07005016 main.log.exception( self.name + ": Object not as expected" )
5017 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07005018 except Exception:
5019 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005020 main.cleanAndExit()
Jon Hallc6793552016-01-19 14:18:37 -08005021
acsmarsdaea66c2015-09-03 11:44:06 -07005022 def maps( self, jsonFormat=True ):
5023 """
5024 Description: Returns result of onos:maps
5025 Optional:
5026 * jsonFormat: enable json formatting of output
5027 """
5028 try:
5029 cmdStr = "maps"
5030 if jsonFormat:
5031 cmdStr += " -j"
5032 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07005033 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005034 assert "Command not found:" not in handle, handle
acsmarsdaea66c2015-09-03 11:44:06 -07005035 return handle
Jon Hallc6793552016-01-19 14:18:37 -08005036 except AssertionError:
5037 main.log.exception( "" )
5038 return None
acsmarsdaea66c2015-09-03 11:44:06 -07005039 except TypeError:
5040 main.log.exception( self.name + ": Object not as expected" )
5041 return None
5042 except pexpect.EOF:
5043 main.log.error( self.name + ": EOF exception found" )
5044 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005045 main.cleanAndExit()
acsmarsdaea66c2015-09-03 11:44:06 -07005046 except Exception:
5047 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005048 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005049
5050 def getSwController( self, uri, jsonFormat=True ):
5051 """
5052 Descrition: Gets the controller information from the device
5053 """
5054 try:
5055 cmd = "device-controllers "
5056 if jsonFormat:
5057 cmd += "-j "
5058 response = self.sendline( cmd + uri )
Jon Halla495f562016-05-16 18:03:26 -07005059 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005060 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005061 return response
Jon Hallc6793552016-01-19 14:18:37 -08005062 except AssertionError:
5063 main.log.exception( "" )
5064 return None
GlennRC050596c2015-11-18 17:06:41 -08005065 except TypeError:
5066 main.log.exception( self.name + ": Object not as expected" )
5067 return None
5068 except pexpect.EOF:
5069 main.log.error( self.name + ": EOF exception found" )
5070 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005071 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005072 except Exception:
5073 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005074 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005075
5076 def setSwController( self, uri, ip, proto="tcp", port="6653", jsonFormat=True ):
5077 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005078 Descrition: sets the controller(s) for the specified device
GlennRC050596c2015-11-18 17:06:41 -08005079
5080 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005081 Required: uri - String: The uri of the device(switch).
GlennRC050596c2015-11-18 17:06:41 -08005082 ip - String or List: The ip address of the controller.
5083 This parameter can be formed in a couple of different ways.
5084 VALID:
5085 10.0.0.1 - just the ip address
5086 tcp:10.0.0.1 - the protocol and the ip address
5087 tcp:10.0.0.1:6653 - the protocol and port can be specified,
5088 so that you can add controllers with different
5089 protocols and ports
5090 INVALID:
5091 10.0.0.1:6653 - this is not supported by ONOS
5092
5093 Optional: proto - The type of connection e.g. tcp, ssl. If a list of ips are given
5094 port - The port number.
5095 jsonFormat - If set ONOS will output in json NOTE: This is currently not supported
5096
5097 Returns: main.TRUE if ONOS returns without any errors, otherwise returns main.FALSE
5098 """
5099 try:
5100 cmd = "device-setcontrollers"
5101
5102 if jsonFormat:
5103 cmd += " -j"
5104 cmd += " " + uri
5105 if isinstance( ip, str ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005106 ip = [ ip ]
GlennRC050596c2015-11-18 17:06:41 -08005107 for item in ip:
5108 if ":" in item:
5109 sitem = item.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005110 if len( sitem ) == 3:
GlennRC050596c2015-11-18 17:06:41 -08005111 cmd += " " + item
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005112 elif "." in sitem[ 1 ]:
5113 cmd += " {}:{}".format( item, port )
GlennRC050596c2015-11-18 17:06:41 -08005114 else:
5115 main.log.error( "Malformed entry: " + item )
5116 raise TypeError
5117 else:
5118 cmd += " {}:{}:{}".format( proto, item, port )
GlennRC050596c2015-11-18 17:06:41 -08005119 response = self.sendline( cmd )
Jon Halla495f562016-05-16 18:03:26 -07005120 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005121 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005122 if "Error" in response:
5123 main.log.error( response )
5124 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005125 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005126 except AssertionError:
5127 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005128 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005129 except TypeError:
5130 main.log.exception( self.name + ": Object not as expected" )
5131 return main.FALSE
5132 except pexpect.EOF:
5133 main.log.error( self.name + ": EOF exception found" )
5134 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005135 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005136 except Exception:
5137 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005138 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005139
5140 def removeDevice( self, device ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005141 '''
GlennRC20fc6522015-12-23 23:26:57 -08005142 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005143 Remove a device from ONOS by passing the uri of the device(s).
GlennRC20fc6522015-12-23 23:26:57 -08005144 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005145 device - (str or list) the id or uri of the device ex. "of:0000000000000001"
GlennRC20fc6522015-12-23 23:26:57 -08005146 Returns:
5147 Returns main.FALSE if an exception is thrown or an error is present
5148 in the response. Otherwise, returns main.TRUE.
5149 NOTE:
5150 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005151 '''
GlennRC20fc6522015-12-23 23:26:57 -08005152 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005153 if isinstance( device, str ):
You Wang823f5022016-08-18 15:24:41 -07005154 deviceStr = device
5155 device = []
5156 device.append( deviceStr )
GlennRC20fc6522015-12-23 23:26:57 -08005157
5158 for d in device:
5159 time.sleep( 1 )
5160 response = self.sendline( "device-remove {}".format( d ) )
Jon Halla495f562016-05-16 18:03:26 -07005161 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005162 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005163 if "Error" in response:
5164 main.log.warn( "Error for device: {}\nResponse: {}".format( d, response ) )
5165 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005166 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005167 except AssertionError:
5168 main.log.exception( "" )
5169 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005170 except TypeError:
5171 main.log.exception( self.name + ": Object not as expected" )
5172 return main.FALSE
5173 except pexpect.EOF:
5174 main.log.error( self.name + ": EOF exception found" )
5175 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005176 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005177 except Exception:
5178 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005179 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005180
5181 def removeHost( self, host ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005182 '''
GlennRC20fc6522015-12-23 23:26:57 -08005183 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005184 Remove a host from ONOS by passing the id of the host(s)
GlennRC20fc6522015-12-23 23:26:57 -08005185 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005186 hostId - (str or list) the id or mac of the host ex. "00:00:00:00:00:01"
GlennRC20fc6522015-12-23 23:26:57 -08005187 Returns:
5188 Returns main.FALSE if an exception is thrown or an error is present
5189 in the response. Otherwise, returns main.TRUE.
5190 NOTE:
5191 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005192 '''
GlennRC20fc6522015-12-23 23:26:57 -08005193 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005194 if isinstance( host, str ):
GlennRC20fc6522015-12-23 23:26:57 -08005195 host = list( host )
5196
5197 for h in host:
5198 time.sleep( 1 )
5199 response = self.sendline( "host-remove {}".format( h ) )
Jon Halla495f562016-05-16 18:03:26 -07005200 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005201 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005202 if "Error" in response:
5203 main.log.warn( "Error for host: {}\nResponse: {}".format( h, response ) )
5204 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005205 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005206 except AssertionError:
5207 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005208 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005209 except TypeError:
5210 main.log.exception( self.name + ": Object not as expected" )
5211 return main.FALSE
5212 except pexpect.EOF:
5213 main.log.error( self.name + ": EOF exception found" )
5214 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005215 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005216 except Exception:
5217 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005218 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005219
YPZhangfebf7302016-05-24 16:45:56 -07005220 def link( self, begin, end, state, timeout=30, showResponse=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005221 '''
GlennRCed771242016-01-13 17:02:47 -08005222 Description:
5223 Bring link down or up in the null-provider.
5224 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005225 begin - (string) One end of a device or switch.
5226 end - (string) the other end of the device or switch
GlennRCed771242016-01-13 17:02:47 -08005227 returns:
5228 main.TRUE if no exceptions were thrown and no Errors are
5229 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005230 '''
GlennRCed771242016-01-13 17:02:47 -08005231 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005232 cmd = "null-link null:{} null:{} {}".format( begin, end, state )
YPZhangfebf7302016-05-24 16:45:56 -07005233 response = self.sendline( cmd, showResponse=showResponse, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07005234 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005235 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08005236 if "Error" in response or "Failure" in response:
5237 main.log.error( response )
5238 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005239 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005240 except AssertionError:
5241 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005242 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005243 except TypeError:
5244 main.log.exception( self.name + ": Object not as expected" )
5245 return main.FALSE
5246 except pexpect.EOF:
5247 main.log.error( self.name + ": EOF exception found" )
5248 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005249 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005250 except Exception:
5251 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005252 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005253
Jon Hall2c8959e2016-12-16 12:17:34 -08005254 def portstate( self, dpid, port, state ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005255 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005256 Description:
5257 Changes the state of port in an OF switch by means of the
5258 PORTSTATUS OF messages.
5259 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005260 dpid - (string) Datapath ID of the device. Ex: 'of:0000000000000102'
5261 port - (string) target port in the device. Ex: '2'
5262 state - (string) target state (enable or disable)
Flavio Castro82ee2f62016-06-07 15:04:12 -07005263 returns:
5264 main.TRUE if no exceptions were thrown and no Errors are
5265 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005266 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005267 try:
Jon Hall2c8959e2016-12-16 12:17:34 -08005268 state = state.lower()
5269 assert state == 'enable' or state == 'disable', "Unknown state"
Jon Halle0f0b342017-04-18 11:43:47 -07005270 cmd = "portstate {} {} {}".format( dpid, port, state )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005271 response = self.sendline( cmd, showResponse=True )
5272 assert response is not None, "Error in sendline"
5273 assert "Command not found:" not in response, response
5274 if "Error" in response or "Failure" in response:
5275 main.log.error( response )
5276 return main.FALSE
5277 return main.TRUE
5278 except AssertionError:
5279 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005280 return main.FALSE
Flavio Castro82ee2f62016-06-07 15:04:12 -07005281 except TypeError:
5282 main.log.exception( self.name + ": Object not as expected" )
5283 return main.FALSE
5284 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()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005291
5292 def logSet( self, level="INFO", app="org.onosproject" ):
5293 """
5294 Set the logging level to lvl for a specific app
5295 returns main.TRUE on success
5296 returns main.FALSE if Error occurred
5297 if noExit is True, TestON will not exit, but clean up
5298 Available level: DEBUG, TRACE, INFO, WARN, ERROR
5299 Level defaults to INFO
5300 """
5301 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005302 self.handle.sendline( "log:set %s %s" % ( level, app ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -08005303 self.handle.expect( self.karafPrompt )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005304
5305 response = self.handle.before
5306 if re.search( "Error", response ):
5307 return main.FALSE
5308 return main.TRUE
5309 except pexpect.TIMEOUT:
5310 main.log.exception( self.name + ": TIMEOUT exception found" )
Devin Lim44075962017-08-11 10:56:37 -07005311 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005312 except pexpect.EOF:
5313 main.log.error( self.name + ": EOF exception found" )
5314 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005315 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005316 except Exception:
5317 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005318 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07005319
5320 def getGraphDict( self, timeout=60, includeHost=False ):
5321 """
5322 Return a dictionary which describes the latest network topology data as a
5323 graph.
5324 An example of the dictionary:
5325 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
5326 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
5327 Each vertex should at least have an 'edges' attribute which describes the
5328 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005329 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07005330 list of attributes.
5331 An example of the edges dictionary:
5332 'edges': { vertex2: { 'port': ..., 'weight': ... },
5333 vertex3: { 'port': ..., 'weight': ... } }
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005334 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07005335 in topology data.
5336 """
5337 graphDict = {}
5338 try:
5339 links = self.links()
5340 links = json.loads( links )
5341 devices = self.devices()
5342 devices = json.loads( devices )
5343 idToDevice = {}
5344 for device in devices:
5345 idToDevice[ device[ 'id' ] ] = device
5346 if includeHost:
5347 hosts = self.hosts()
5348 # FIXME: support 'includeHost' argument
5349 for link in links:
5350 nodeA = link[ 'src' ][ 'device' ]
5351 nodeB = link[ 'dst' ][ 'device' ]
5352 assert idToDevice[ nodeA ][ 'available' ] and idToDevice[ nodeB ][ 'available' ]
Jon Halle0f0b342017-04-18 11:43:47 -07005353 if nodeA not in graphDict.keys():
5354 graphDict[ nodeA ] = { 'edges': {},
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005355 'dpid': idToDevice[ nodeA ][ 'id' ][ 3: ],
Jon Halle0f0b342017-04-18 11:43:47 -07005356 'type': idToDevice[ nodeA ][ 'type' ],
5357 'available': idToDevice[ nodeA ][ 'available' ],
5358 'role': idToDevice[ nodeA ][ 'role' ],
5359 'mfr': idToDevice[ nodeA ][ 'mfr' ],
5360 'hw': idToDevice[ nodeA ][ 'hw' ],
5361 'sw': idToDevice[ nodeA ][ 'sw' ],
5362 'serial': idToDevice[ nodeA ][ 'serial' ],
5363 'chassisId': idToDevice[ nodeA ][ 'chassisId' ],
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005364 'annotations': idToDevice[ nodeA ][ 'annotations' ]}
You Wangdb8cd0a2016-05-26 15:19:45 -07005365 else:
5366 # Assert nodeB is not connected to any current links of nodeA
You Wang7d14d642019-01-23 15:10:08 -08005367 # assert nodeB not in graphDict[ nodeA ][ 'edges' ].keys()
5368 pass
Jon Halle0f0b342017-04-18 11:43:47 -07005369 graphDict[ nodeA ][ 'edges' ][ nodeB ] = { 'port': link[ 'src' ][ 'port' ],
5370 'type': link[ 'type' ],
5371 'state': link[ 'state' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07005372 return graphDict
5373 except ( TypeError, ValueError ):
5374 main.log.exception( self.name + ": Object not as expected" )
5375 return None
5376 except KeyError:
5377 main.log.exception( self.name + ": KeyError exception found" )
5378 return None
5379 except AssertionError:
5380 main.log.exception( self.name + ": AssertionError exception found" )
5381 return None
5382 except pexpect.EOF:
5383 main.log.error( self.name + ": EOF exception found" )
5384 main.log.error( self.name + ": " + self.handle.before )
5385 return None
5386 except Exception:
5387 main.log.exception( self.name + ": Uncaught exception!" )
5388 return None
YPZhangcbc2a062016-07-11 10:55:44 -07005389
5390 def getIntentPerfSummary( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005391 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005392 Send command to check intent-perf summary
5393 Returns: dictionary for intent-perf summary
5394 if something wrong, function will return None
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005395 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005396 cmd = "intent-perf -s"
5397 respDic = {}
5398 resp = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08005399 assert resp is not None, "Error in sendline"
5400 assert "Command not found:" not in resp, resp
YPZhangcbc2a062016-07-11 10:55:44 -07005401 try:
5402 # Generate the dictionary to return
5403 for l in resp.split( "\n" ):
5404 # Delete any white space in line
5405 temp = re.sub( r'\s+', '', l )
5406 temp = temp.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005407 respDic[ temp[ 0 ] ] = temp[ 1 ]
YPZhangcbc2a062016-07-11 10:55:44 -07005408
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005409 except ( TypeError, ValueError ):
YPZhangcbc2a062016-07-11 10:55:44 -07005410 main.log.exception( self.name + ": Object not as expected" )
5411 return None
5412 except KeyError:
5413 main.log.exception( self.name + ": KeyError exception found" )
5414 return None
5415 except AssertionError:
5416 main.log.exception( self.name + ": AssertionError exception found" )
5417 return None
5418 except pexpect.EOF:
5419 main.log.error( self.name + ": EOF exception found" )
5420 main.log.error( self.name + ": " + self.handle.before )
5421 return None
5422 except Exception:
5423 main.log.exception( self.name + ": Uncaught exception!" )
5424 return None
5425 return respDic
5426
Chiyu Chengec63bde2016-11-17 18:11:36 -08005427 def logSearch( self, mode='all', searchTerm='', startLine='', logNum=1 ):
chengchiyu08303a02016-09-08 17:40:26 -07005428 """
5429 Searches the latest ONOS log file for the given search term and
5430 return a list that contains all the lines that have the search term.
YPZhangcbc2a062016-07-11 10:55:44 -07005431
chengchiyu08303a02016-09-08 17:40:26 -07005432 Arguments:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005433 searchTerm:
5434 The string to grep from the ONOS log.
5435 startLine:
5436 The term that decides which line is the start to search the searchTerm in
5437 the karaf log. For now, startTerm only works in 'first' mode.
5438 logNum:
5439 In some extreme cases, one karaf log is not big enough to contain all the
5440 information.Because of this, search mutiply logs is necessary to capture
5441 the right result. logNum is the number of karaf logs that we need to search
5442 the searchTerm.
chengchiyu08303a02016-09-08 17:40:26 -07005443 mode:
5444 all: return all the strings that contain the search term
5445 last: return the last string that contains the search term
5446 first: return the first string that contains the search term
Chiyu Chengec63bde2016-11-17 18:11:36 -08005447 num: return the number of times that the searchTerm appears in the log
5448 total: return how many lines in karaf log
chengchiyu08303a02016-09-08 17:40:26 -07005449 """
5450 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005451 assert isinstance( searchTerm, str )
Jon Halle0f0b342017-04-18 11:43:47 -07005452 # Build the log paths string
Chiyu Chengec63bde2016-11-17 18:11:36 -08005453 logPath = '/opt/onos/log/karaf.log.'
5454 logPaths = '/opt/onos/log/karaf.log'
5455 for i in range( 1, logNum ):
5456 logPaths = logPath + str( i ) + " " + logPaths
5457 cmd = "cat " + logPaths
You Wang6d301d42017-04-21 10:49:33 -07005458 if startLine:
Jon Halla478b852017-12-04 15:00:15 -08005459 # 100000000 is just a extreme large number to make sure this function can
5460 # grep all the lines after startLine
You Wang6d301d42017-04-21 10:49:33 -07005461 cmd = cmd + " | grep -A 100000000 \'" + startLine + "\'"
Chiyu Chengec63bde2016-11-17 18:11:36 -08005462 if mode == 'all':
5463 cmd = cmd + " | grep \'" + searchTerm + "\'"
You Wang6d301d42017-04-21 10:49:33 -07005464 elif mode == 'last':
Chiyu Chengec63bde2016-11-17 18:11:36 -08005465 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | tail -n 1"
You Wang6d301d42017-04-21 10:49:33 -07005466 elif mode == 'first':
5467 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | head -n 1"
5468 elif mode == 'num':
You Wangd91a70f2019-01-03 15:28:10 -08005469 cmd = cmd + " | grep \'" + searchTerm + "\' | wc -l"
5470 num = self.lineCount( cmd )
Chiyu Chengb8c2c842016-10-05 12:40:49 -07005471 return num
You Wang6d301d42017-04-21 10:49:33 -07005472 elif mode == 'total':
Jon Halld5a94fb2018-11-13 14:32:23 -08005473 totalLines = self.lineCount( "cat /opt/onos/log/karaf.log | wc -l" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005474 return int( totalLines )
You Wang6d301d42017-04-21 10:49:33 -07005475 else:
5476 main.log.error( self.name + " unsupported mode" )
5477 return main.ERROR
chengchiyu08303a02016-09-08 17:40:26 -07005478 before = self.sendline( cmd )
5479 before = before.splitlines()
5480 # make sure the returned list only contains the search term
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005481 returnLines = [ line for line in before if searchTerm in line ]
chengchiyu08303a02016-09-08 17:40:26 -07005482 return returnLines
5483 except AssertionError:
5484 main.log.error( self.name + " searchTerm is not string type" )
5485 return None
5486 except pexpect.EOF:
5487 main.log.error( self.name + ": EOF exception found" )
5488 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005489 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005490 except pexpect.TIMEOUT:
5491 main.log.error( self.name + ": TIMEOUT exception found" )
5492 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005493 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005494 except Exception:
5495 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005496 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005497
5498 def vplsShow( self, jsonFormat=True ):
5499 """
5500 Description: Returns result of onos:vpls show, which should list the
5501 configured VPLS networks and the assigned interfaces.
5502 Optional:
5503 * jsonFormat: enable json formatting of output
5504 Returns:
5505 The output of the command or None on error.
5506 """
5507 try:
5508 cmdStr = "vpls show"
5509 if jsonFormat:
5510 raise NotImplementedError
5511 cmdStr += " -j"
5512 handle = self.sendline( cmdStr )
5513 assert handle is not None, "Error in sendline"
5514 assert "Command not found:" not in handle, handle
5515 return handle
5516 except AssertionError:
5517 main.log.exception( "" )
5518 return None
5519 except TypeError:
5520 main.log.exception( self.name + ": Object not as expected" )
5521 return None
5522 except pexpect.EOF:
5523 main.log.error( self.name + ": EOF exception found" )
5524 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005525 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005526 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005527 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005528 return None
5529 except Exception:
5530 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005531 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005532
5533 def parseVplsShow( self ):
5534 """
5535 Parse the cli output of 'vpls show' into json output. This is required
5536 as there is currently no json output available.
5537 """
5538 try:
5539 output = []
5540 raw = self.vplsShow( jsonFormat=False )
5541 namePat = "VPLS name: (?P<name>\w+)"
5542 interfacesPat = "Associated interfaces: \[(?P<interfaces>.*)\]"
5543 encapPat = "Encapsulation: (?P<encap>\w+)"
5544 pattern = "\s+".join( [ namePat, interfacesPat, encapPat ] )
5545 mIter = re.finditer( pattern, raw )
5546 for match in mIter:
5547 item = {}
5548 item[ 'name' ] = match.group( 'name' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005549 ifaces = match.group( 'interfaces' ).split( ', ' )
Jon Hall2c8959e2016-12-16 12:17:34 -08005550 if ifaces == [ "" ]:
5551 ifaces = []
5552 item[ 'interfaces' ] = ifaces
5553 encap = match.group( 'encap' )
5554 if encap != 'NONE':
5555 item[ 'encapsulation' ] = encap.lower()
5556 output.append( item )
5557 return output
5558 except Exception:
5559 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005560 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005561
5562 def vplsList( self, jsonFormat=True ):
5563 """
5564 Description: Returns result of onos:vpls list, which should list the
5565 configured VPLS networks.
5566 Optional:
5567 * jsonFormat: enable json formatting of output
5568 """
5569 try:
5570 cmdStr = "vpls list"
5571 if jsonFormat:
5572 raise NotImplementedError
5573 cmdStr += " -j"
5574 handle = self.sendline( cmdStr )
5575 assert handle is not None, "Error in sendline"
5576 assert "Command not found:" not in handle, handle
5577 return handle
5578 except AssertionError:
5579 main.log.exception( "" )
5580 return None
5581 except TypeError:
5582 main.log.exception( self.name + ": Object not as expected" )
5583 return None
5584 except pexpect.EOF:
5585 main.log.error( self.name + ": EOF exception found" )
5586 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005587 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005588 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005589 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005590 return None
5591 except Exception:
5592 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005593 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005594
5595 def vplsCreate( self, network ):
5596 """
5597 CLI command to create a new VPLS network.
5598 Required arguments:
5599 network - String name of the network to create.
5600 returns:
5601 main.TRUE on success and main.FALSE on failure
5602 """
5603 try:
5604 network = str( network )
5605 cmdStr = "vpls create "
5606 cmdStr += network
5607 output = self.sendline( cmdStr )
5608 assert output is not None, "Error in sendline"
5609 assert "Command not found:" not in output, output
5610 assert "Error executing command" not in output, output
5611 assert "VPLS already exists:" not in output, output
5612 return main.TRUE
5613 except AssertionError:
5614 main.log.exception( "" )
5615 return main.FALSE
5616 except TypeError:
5617 main.log.exception( self.name + ": Object not as expected" )
5618 return main.FALSE
5619 except pexpect.EOF:
5620 main.log.error( self.name + ": EOF exception found" )
5621 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005622 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005623 except Exception:
5624 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005625 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005626
5627 def vplsDelete( self, network ):
5628 """
5629 CLI command to delete a VPLS network.
5630 Required arguments:
5631 network - Name of the network to delete.
5632 returns:
5633 main.TRUE on success and main.FALSE on failure
5634 """
5635 try:
5636 network = str( network )
5637 cmdStr = "vpls delete "
5638 cmdStr += network
5639 output = self.sendline( cmdStr )
5640 assert output is not None, "Error in sendline"
5641 assert "Command not found:" not in output, output
5642 assert "Error executing command" not in output, output
5643 assert " not found" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005644 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005645 return main.TRUE
5646 except AssertionError:
5647 main.log.exception( "" )
5648 return main.FALSE
5649 except TypeError:
5650 main.log.exception( self.name + ": Object not as expected" )
5651 return main.FALSE
5652 except pexpect.EOF:
5653 main.log.error( self.name + ": EOF exception found" )
5654 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005655 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005656 except Exception:
5657 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005658 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005659
5660 def vplsAddIface( self, network, iface ):
5661 """
5662 CLI command to add an interface to a VPLS network.
5663 Required arguments:
5664 network - Name of the network to add the interface to.
5665 iface - The ONOS name for an interface.
5666 returns:
5667 main.TRUE on success and main.FALSE on failure
5668 """
5669 try:
5670 network = str( network )
5671 iface = str( iface )
5672 cmdStr = "vpls add-if "
5673 cmdStr += network + " " + iface
5674 output = self.sendline( cmdStr )
5675 assert output is not None, "Error in sendline"
5676 assert "Command not found:" not in output, output
5677 assert "Error executing command" not in output, output
5678 assert "already associated to network" not in output, output
5679 assert "Interface cannot be added." not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005680 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005681 return main.TRUE
5682 except AssertionError:
5683 main.log.exception( "" )
5684 return main.FALSE
5685 except TypeError:
5686 main.log.exception( self.name + ": Object not as expected" )
5687 return main.FALSE
5688 except pexpect.EOF:
5689 main.log.error( self.name + ": EOF exception found" )
5690 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005691 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005692 except Exception:
5693 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005694 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005695
5696 def vplsRemIface( self, network, iface ):
5697 """
5698 CLI command to remove an interface from a VPLS network.
5699 Required arguments:
5700 network - Name of the network to remove the interface from.
5701 iface - Name of the interface to remove.
5702 returns:
5703 main.TRUE on success and main.FALSE on failure
5704 """
5705 try:
5706 iface = str( iface )
5707 cmdStr = "vpls rem-if "
5708 cmdStr += network + " " + iface
5709 output = self.sendline( cmdStr )
5710 assert output is not None, "Error in sendline"
5711 assert "Command not found:" not in output, output
5712 assert "Error executing command" not in output, output
5713 assert "is not configured" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005714 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005715 return main.TRUE
5716 except AssertionError:
5717 main.log.exception( "" )
5718 return main.FALSE
5719 except TypeError:
5720 main.log.exception( self.name + ": Object not as expected" )
5721 return main.FALSE
5722 except pexpect.EOF:
5723 main.log.error( self.name + ": EOF exception found" )
5724 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005725 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005726 except Exception:
5727 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005728 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005729
5730 def vplsClean( self ):
5731 """
5732 Description: Clears the VPLS app configuration.
5733 Returns: main.TRUE on success and main.FALSE on failure
5734 """
5735 try:
5736 cmdStr = "vpls clean"
5737 handle = self.sendline( cmdStr )
5738 assert handle is not None, "Error in sendline"
5739 assert "Command not found:" not in handle, handle
Jon Hallcf97cf12017-06-06 09:37:51 -07005740 assert "still updating" not in handle, handle
Jon Hall2c8959e2016-12-16 12:17:34 -08005741 return handle
5742 except AssertionError:
5743 main.log.exception( "" )
5744 return main.FALSE
5745 except TypeError:
5746 main.log.exception( self.name + ": Object not as expected" )
5747 return main.FALSE
5748 except pexpect.EOF:
5749 main.log.error( self.name + ": EOF exception found" )
5750 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005751 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005752 except Exception:
5753 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005754 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005755
5756 def vplsSetEncap( self, network, encapType ):
5757 """
5758 CLI command to add an interface to a VPLS network.
5759 Required arguments:
5760 network - Name of the network to create.
5761 encapType - Type of encapsulation.
5762 returns:
5763 main.TRUE on success and main.FALSE on failure
5764 """
5765 try:
5766 network = str( network )
5767 encapType = str( encapType ).upper()
5768 assert encapType in [ "MPLS", "VLAN", "NONE" ], "Incorrect type"
5769 cmdStr = "vpls set-encap "
5770 cmdStr += network + " " + encapType
5771 output = self.sendline( cmdStr )
5772 assert output is not None, "Error in sendline"
5773 assert "Command not found:" not in output, output
5774 assert "Error executing command" not in output, output
5775 assert "already associated to network" not in output, output
5776 assert "Encapsulation type " not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005777 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005778 return main.TRUE
5779 except AssertionError:
5780 main.log.exception( "" )
5781 return main.FALSE
5782 except TypeError:
5783 main.log.exception( self.name + ": Object not as expected" )
5784 return main.FALSE
5785 except pexpect.EOF:
5786 main.log.error( self.name + ": EOF exception found" )
5787 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005788 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005789 except Exception:
5790 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005791 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005792
5793 def interfaces( self, jsonFormat=True ):
5794 """
5795 Description: Returns result of interfaces command.
5796 Optional:
5797 * jsonFormat: enable json formatting of output
5798 Returns:
5799 The output of the command or None on error.
5800 """
5801 try:
5802 cmdStr = "interfaces"
5803 if jsonFormat:
Jon Halle0f0b342017-04-18 11:43:47 -07005804 raise NotImplementedError
Jon Hall2c8959e2016-12-16 12:17:34 -08005805 cmdStr += " -j"
5806 handle = self.sendline( cmdStr )
5807 assert handle is not None, "Error in sendline"
5808 assert "Command not found:" not in handle, handle
5809 return handle
5810 except AssertionError:
5811 main.log.exception( "" )
5812 return None
5813 except TypeError:
5814 main.log.exception( self.name + ": Object not as expected" )
5815 return None
5816 except pexpect.EOF:
5817 main.log.error( self.name + ": EOF exception found" )
5818 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005819 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005820 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005821 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005822 return None
5823 except Exception:
5824 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005825 main.cleanAndExit()
Chiyu Chengec63bde2016-11-17 18:11:36 -08005826
5827 def getTimeStampFromLog( self, mode, searchTerm, splitTerm_before, splitTerm_after, startLine='', logNum=1 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005828 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005829 Get the timestamp of searchTerm from karaf log.
5830
5831 Arguments:
5832 splitTerm_before and splitTerm_after:
5833
5834 The terms that split the string that contains the timeStamp of
5835 searchTerm. For example, if that string is "xxxxxxxcreationTime =
5836 1419510501xxxxxx", then the splitTerm_before is "CreationTime = "
5837 and the splitTerm_after is "x"
5838
5839 others:
Jon Halle0f0b342017-04-18 11:43:47 -07005840 Please look at the "logsearch" Function in onosclidriver.py
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005841 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005842 if logNum < 0:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005843 main.log.error( "Get wrong log number ")
Chiyu Chengec63bde2016-11-17 18:11:36 -08005844 return main.ERROR
5845 lines = self.logSearch( mode=mode, searchTerm=searchTerm, startLine=startLine, logNum=logNum )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005846 if len( lines ) == 0:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005847 main.log.warn( "Captured timestamp string is empty" )
5848 return main.ERROR
5849 lines = lines[ 0 ]
5850 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005851 assert isinstance( lines, str )
Chiyu Chengec63bde2016-11-17 18:11:36 -08005852 # get the target value
5853 line = lines.split( splitTerm_before )
5854 key = line[ 1 ].split( splitTerm_after )
5855 return int( key[ 0 ] )
5856 except IndexError:
5857 main.log.warn( "Index Error!" )
5858 return main.ERROR
5859 except AssertionError:
5860 main.log.warn( "Search Term Not Found " )
5861 return main.ERROR
Jon Halle0f0b342017-04-18 11:43:47 -07005862
5863 def workQueueAdd( self, queueName, value ):
5864 """
5865 CLI command to add a string to the specified Work Queue.
5866 This function uses the distributed primitives test app, which
5867 gives some cli access to distributed primitives for testing
5868 purposes only.
5869
5870 Required arguments:
5871 queueName - The name of the queue to add to
5872 value - The value to add to the queue
5873 returns:
5874 main.TRUE on success, main.FALSE on failure and
5875 main.ERROR on error.
5876 """
5877 try:
5878 queueName = str( queueName )
5879 value = str( value )
5880 prefix = "work-queue-test"
5881 operation = "add"
5882 cmdStr = " ".join( [ prefix, queueName, operation, value ] )
5883 output = self.distPrimitivesSend( cmdStr )
5884 if "Invalid operation name" in output:
5885 main.log.warn( output )
5886 return main.ERROR
5887 elif "Done" in output:
5888 return main.TRUE
5889 except TypeError:
5890 main.log.exception( self.name + ": Object not as expected" )
5891 return main.ERROR
5892 except Exception:
5893 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005894 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005895
5896 def workQueueAddMultiple( self, queueName, value1, value2 ):
5897 """
5898 CLI command to add two strings to the specified Work Queue.
5899 This function uses the distributed primitives test app, which
5900 gives some cli access to distributed primitives for testing
5901 purposes only.
5902
5903 Required arguments:
5904 queueName - The name of the queue to add to
5905 value1 - The first value to add to the queue
5906 value2 - The second value to add to the queue
5907 returns:
5908 main.TRUE on success, main.FALSE on failure and
5909 main.ERROR on error.
5910 """
5911 try:
5912 queueName = str( queueName )
5913 value1 = str( value1 )
5914 value2 = str( value2 )
5915 prefix = "work-queue-test"
5916 operation = "addMultiple"
5917 cmdStr = " ".join( [ prefix, queueName, operation, value1, value2 ] )
5918 output = self.distPrimitivesSend( cmdStr )
5919 if "Invalid operation name" in output:
5920 main.log.warn( output )
5921 return main.ERROR
5922 elif "Done" in output:
5923 return main.TRUE
5924 except TypeError:
5925 main.log.exception( self.name + ": Object not as expected" )
5926 return main.ERROR
5927 except Exception:
5928 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005929 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005930
5931 def workQueueTakeAndComplete( self, queueName, number=1 ):
5932 """
5933 CLI command to take a value from the specified Work Queue and compelte it.
5934 This function uses the distributed primitives test app, which
5935 gives some cli access to distributed primitives for testing
5936 purposes only.
5937
5938 Required arguments:
5939 queueName - The name of the queue to add to
5940 number - The number of items to take and complete
5941 returns:
5942 main.TRUE on success, main.FALSE on failure and
5943 main.ERROR on error.
5944 """
5945 try:
5946 queueName = str( queueName )
5947 number = str( int( number ) )
5948 prefix = "work-queue-test"
5949 operation = "takeAndComplete"
5950 cmdStr = " ".join( [ prefix, queueName, operation, number ] )
5951 output = self.distPrimitivesSend( cmdStr )
5952 if "Invalid operation name" in output:
5953 main.log.warn( output )
5954 return main.ERROR
5955 elif "Done" in output:
5956 return main.TRUE
5957 except TypeError:
5958 main.log.exception( self.name + ": Object not as expected" )
5959 return main.ERROR
5960 except Exception:
5961 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005962 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005963
5964 def workQueueDestroy( self, queueName ):
5965 """
5966 CLI command to destroy the specified Work Queue.
5967 This function uses the distributed primitives test app, which
5968 gives some cli access to distributed primitives for testing
5969 purposes only.
5970
5971 Required arguments:
5972 queueName - The name of the queue to add to
5973 returns:
5974 main.TRUE on success, main.FALSE on failure and
5975 main.ERROR on error.
5976 """
5977 try:
5978 queueName = str( queueName )
5979 prefix = "work-queue-test"
5980 operation = "destroy"
5981 cmdStr = " ".join( [ prefix, queueName, operation ] )
5982 output = self.distPrimitivesSend( cmdStr )
5983 if "Invalid operation name" in output:
5984 main.log.warn( output )
5985 return main.ERROR
5986 return main.TRUE
5987 except TypeError:
5988 main.log.exception( self.name + ": Object not as expected" )
5989 return main.ERROR
5990 except Exception:
5991 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005992 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005993
5994 def workQueueTotalPending( self, queueName ):
5995 """
5996 CLI command to get the Total Pending items of the specified Work Queue.
5997 This function uses the distributed primitives test app, which
5998 gives some cli access to distributed primitives for testing
5999 purposes only.
6000
6001 Required arguments:
6002 queueName - The name of the queue to add to
6003 returns:
6004 The number of Pending items in the specified work queue or
6005 None on error
6006 """
6007 try:
6008 queueName = str( queueName )
6009 prefix = "work-queue-test"
6010 operation = "totalPending"
6011 cmdStr = " ".join( [ prefix, queueName, operation ] )
6012 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006013 main.log.debug( self.name + ": work queue unparsed: " + output )
6014 output = output.split( "\r\n" )[ -1 ]
6015 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006016 pattern = r'\d+'
6017 if "Invalid operation name" in output:
6018 main.log.warn( output )
6019 return None
6020 else:
6021 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006022 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006023 except ( AttributeError, TypeError ):
6024 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6025 return None
6026 except Exception:
6027 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006028 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006029
6030 def workQueueTotalCompleted( self, queueName ):
6031 """
6032 CLI command to get the Total Completed items of the specified Work Queue.
6033 This function uses the distributed primitives test app, which
6034 gives some cli access to distributed primitives for testing
6035 purposes only.
6036
6037 Required arguments:
6038 queueName - The name of the queue to add to
6039 returns:
6040 The number of complete items in the specified work queue or
6041 None on error
6042 """
6043 try:
6044 queueName = str( queueName )
6045 prefix = "work-queue-test"
6046 operation = "totalCompleted"
6047 cmdStr = " ".join( [ prefix, queueName, operation ] )
6048 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006049 main.log.debug( self.name + ": work queue unparsed: " + output )
6050 output = output.split( "\r\n" )[ -1 ]
6051 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006052 pattern = r'\d+'
6053 if "Invalid operation name" in output:
6054 main.log.warn( output )
6055 return None
6056 else:
6057 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006058 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006059 except ( AttributeError, TypeError ):
6060 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6061 return None
6062 except Exception:
6063 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006064 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006065
6066 def workQueueTotalInProgress( self, queueName ):
6067 """
6068 CLI command to get the Total In Progress items of the specified Work Queue.
6069 This function uses the distributed primitives test app, which
6070 gives some cli access to distributed primitives for testing
6071 purposes only.
6072
6073 Required arguments:
6074 queueName - The name of the queue to add to
6075 returns:
6076 The number of In Progress items in the specified work queue or
6077 None on error
6078 """
6079 try:
6080 queueName = str( queueName )
6081 prefix = "work-queue-test"
6082 operation = "totalInProgress"
6083 cmdStr = " ".join( [ prefix, queueName, operation ] )
6084 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006085 main.log.debug( self.name + ": work queue unparsed: " + output )
6086 output = output.split( "\r\n" )[ -1 ]
6087 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006088 pattern = r'\d+'
6089 if "Invalid operation name" in output:
6090 main.log.warn( output )
6091 return None
6092 else:
6093 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006094 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006095 except ( AttributeError, TypeError ):
6096 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6097 return None
6098 except Exception:
6099 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006100 main.cleanAndExit()
Jeremy Ronquillo818bc7c2017-08-09 17:14:53 +00006101
6102 def events( self, args='-a' ):
6103 """
6104 Description: Returns events -a command output
6105 Optional:
6106 add other arguments
6107 """
6108 try:
6109 cmdStr = "events"
6110 if args:
6111 cmdStr += " " + args
6112 handle = self.sendline( cmdStr )
6113 assert handle is not None, "Error in sendline"
6114 assert "Command not found:" not in handle, handle
6115 return handle
6116 except AssertionError:
6117 main.log.exception( "" )
6118 return None
6119 except TypeError:
6120 main.log.exception( self.name + ": Object not as expected" )
6121 return None
6122 except pexpect.EOF:
6123 main.log.error( self.name + ": EOF exception found" )
6124 main.log.error( self.name + ": " + self.handle.before )
6125 main.cleanAndExit()
6126 except Exception:
6127 main.log.exception( self.name + ": Uncaught exception!" )
6128 main.cleanAndExit()
6129
6130 def getMaster( self, deviceID ):
6131 """
6132 Description: Obtains current master using "roles" command for a specific deviceID
6133 """
6134 try:
6135 return str( self.getRole( deviceID )[ 'master' ] )
6136 except AssertionError:
6137 main.log.exception( "" )
6138 return None
6139 except TypeError:
6140 main.log.exception( self.name + ": Object not as expected" )
6141 return None
6142 except pexpect.EOF:
6143 main.log.error( self.name + ": EOF exception found" )
6144 main.log.error( self.name + ": " + self.handle.before )
6145 main.cleanAndExit()
6146 except Exception:
6147 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lime6fe3c42017-10-18 16:28:40 -07006148 main.cleanAndExit()
Jon Halla478b852017-12-04 15:00:15 -08006149
6150 def issu( self ):
6151 """
6152 Short summary of In-Service Software Upgrade status
6153
6154 Returns the output of the cli command or None on Error
6155 """
6156 try:
6157 cmdStr = "issu"
6158 handle = self.sendline( cmdStr )
6159 assert handle is not None, "Error in sendline"
6160 assert "Command not found:" not in handle, handle
6161 assert "Unsupported command:" not in handle, handle
6162 return handle
6163 except AssertionError:
6164 main.log.exception( "" )
6165 return None
6166 except TypeError:
6167 main.log.exception( self.name + ": Object not as expected" )
6168 return None
6169 except pexpect.EOF:
6170 main.log.error( self.name + ": EOF exception found" )
6171 main.log.error( self.name + ": " + self.handle.before )
6172 main.cleanAndExit()
6173 except Exception:
6174 main.log.exception( self.name + ": Uncaught exception!" )
6175 main.cleanAndExit()
6176
6177 def issuInit( self ):
6178 """
6179 Initiates an In-Service Software Upgrade
6180
6181 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6182 """
6183 try:
6184 cmdStr = "issu init"
6185 handle = self.sendline( cmdStr )
6186 assert handle is not None, "Error in sendline"
6187 assert "Command not found:" not in handle, handle
6188 assert "Unsupported command:" not in handle, handle
6189 if "Initialized" in handle:
6190 return main.TRUE
6191 else:
6192 return main.FALSE
6193 except AssertionError:
6194 main.log.exception( "" )
6195 return main.ERROR
6196 except TypeError:
6197 main.log.exception( self.name + ": Object not as expected" )
6198 return main.ERROR
6199 except pexpect.EOF:
6200 main.log.error( self.name + ": EOF exception found" )
6201 main.log.error( self.name + ": " + self.handle.before )
6202 main.cleanAndExit()
6203 except Exception:
6204 main.log.exception( self.name + ": Uncaught exception!" )
6205 main.cleanAndExit()
6206
6207 def issuUpgrade( self ):
6208 """
6209 Transitions stores to upgraded nodes
6210
6211 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6212 """
6213 try:
6214 cmdStr = "issu upgrade"
6215 handle = self.sendline( cmdStr )
6216 assert handle is not None, "Error in sendline"
6217 assert "Command not found:" not in handle, handle
6218 assert "Unsupported command:" not in handle, handle
6219 if "Upgraded" in handle:
6220 return main.TRUE
6221 else:
6222 return main.FALSE
6223 except AssertionError:
6224 main.log.exception( "" )
6225 return main.ERROR
6226 except TypeError:
6227 main.log.exception( self.name + ": Object not as expected" )
6228 return main.ERROR
6229 except pexpect.EOF:
6230 main.log.error( self.name + ": EOF exception found" )
6231 main.log.error( self.name + ": " + self.handle.before )
6232 main.cleanAndExit()
6233 except Exception:
6234 main.log.exception( self.name + ": Uncaught exception!" )
6235 main.cleanAndExit()
6236
6237 def issuCommit( self ):
6238 """
6239 Finalizes an In-Service Software Upgrade
6240
6241 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6242 """
6243 try:
6244 cmdStr = "issu commit"
6245 handle = self.sendline( cmdStr )
6246 assert handle is not None, "Error in sendline"
6247 assert "Command not found:" not in handle, handle
6248 assert "Unsupported command:" not in handle, handle
6249 # TODO: Check the version returned by this command
6250 if "Committed version" in handle:
6251 return main.TRUE
6252 else:
6253 return main.FALSE
6254 except AssertionError:
6255 main.log.exception( "" )
6256 return main.ERROR
6257 except TypeError:
6258 main.log.exception( self.name + ": Object not as expected" )
6259 return main.ERROR
6260 except pexpect.EOF:
6261 main.log.error( self.name + ": EOF exception found" )
6262 main.log.error( self.name + ": " + self.handle.before )
6263 main.cleanAndExit()
6264 except Exception:
6265 main.log.exception( self.name + ": Uncaught exception!" )
6266 main.cleanAndExit()
6267
6268 def issuRollback( self ):
6269 """
6270 Rolls back an In-Service Software Upgrade
6271
6272 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6273 """
6274 try:
6275 cmdStr = "issu rollback"
6276 handle = self.sendline( cmdStr )
6277 assert handle is not None, "Error in sendline"
6278 assert "Command not found:" not in handle, handle
6279 assert "Unsupported command:" not in handle, handle
6280 # TODO: Check the version returned by this command
6281 if "Rolled back to version" in handle:
6282 return main.TRUE
6283 else:
6284 return main.FALSE
6285 except AssertionError:
6286 main.log.exception( "" )
6287 return main.ERROR
6288 except TypeError:
6289 main.log.exception( self.name + ": Object not as expected" )
6290 return main.ERROR
6291 except pexpect.EOF:
6292 main.log.error( self.name + ": EOF exception found" )
6293 main.log.error( self.name + ": " + self.handle.before )
6294 main.cleanAndExit()
6295 except Exception:
6296 main.log.exception( self.name + ": Uncaught exception!" )
6297 main.cleanAndExit()
6298
6299 def issuReset( self ):
6300 """
6301 Resets the In-Service Software Upgrade status after a rollback
6302
6303 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6304 """
6305 try:
6306 cmdStr = "issu reset"
6307 handle = self.sendline( cmdStr )
6308 assert handle is not None, "Error in sendline"
6309 assert "Command not found:" not in handle, handle
6310 assert "Unsupported command:" not in handle, handle
6311 # TODO: Check the version returned by this command
6312 if "Reset version" in handle:
6313 return main.TRUE
6314 else:
6315 return main.FALSE
6316 except AssertionError:
6317 main.log.exception( "" )
6318 return main.ERROR
6319 except TypeError:
6320 main.log.exception( self.name + ": Object not as expected" )
6321 return main.ERROR
6322 except pexpect.EOF:
6323 main.log.error( self.name + ": EOF exception found" )
6324 main.log.error( self.name + ": " + self.handle.before )
6325 main.cleanAndExit()
6326 except Exception:
6327 main.log.exception( self.name + ": Uncaught exception!" )
6328 main.cleanAndExit()
6329
6330 def issuStatus( self ):
6331 """
6332 Status of an In-Service Software Upgrade
6333
6334 Returns the output of the cli command or None on Error
6335 """
6336 try:
6337 cmdStr = "issu status"
6338 handle = self.sendline( cmdStr )
6339 assert handle is not None, "Error in sendline"
6340 assert "Command not found:" not in handle, handle
6341 assert "Unsupported command:" not in handle, handle
6342 return handle
6343 except AssertionError:
6344 main.log.exception( "" )
6345 return None
6346 except TypeError:
6347 main.log.exception( self.name + ": Object not as expected" )
6348 return None
6349 except pexpect.EOF:
6350 main.log.error( self.name + ": EOF exception found" )
6351 main.log.error( self.name + ": " + self.handle.before )
6352 main.cleanAndExit()
6353 except Exception:
6354 main.log.exception( self.name + ": Uncaught exception!" )
6355 main.cleanAndExit()
6356
6357 def issuVersion( self ):
6358 """
6359 Get the version of an In-Service Software Upgrade
6360
6361 Returns the output of the cli command or None on Error
6362 """
6363 try:
6364 cmdStr = "issu version"
6365 handle = self.sendline( cmdStr )
6366 assert handle is not None, "Error in sendline"
6367 assert "Command not found:" not in handle, handle
6368 assert "Unsupported command:" not in handle, handle
6369 return handle
6370 except AssertionError:
6371 main.log.exception( "" )
6372 return None
6373 except TypeError:
6374 main.log.exception( self.name + ": Object not as expected" )
6375 return None
6376 except pexpect.EOF:
6377 main.log.error( self.name + ": EOF exception found" )
6378 main.log.error( self.name + ": " + self.handle.before )
6379 main.cleanAndExit()
6380 except Exception:
6381 main.log.exception( self.name + ": Uncaught exception!" )
6382 main.cleanAndExit()
You Wange24d6272018-03-27 21:18:50 -07006383
6384 def mcastJoin( self, sIP, groupIP, sPort, dPorts ):
6385 """
6386 Create a multicast route by calling 'mcast-join' command
6387 sIP: source IP of the multicast route
6388 groupIP: group IP of the multicast route
6389 sPort: source port (e.g. of:0000000000000001/3 ) of the multicast route
6390 dPorts: a list of destination ports of the multicast route
6391 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6392 """
6393 try:
6394 cmdStr = "mcast-join"
6395 cmdStr += " " + str( sIP )
6396 cmdStr += " " + str( groupIP )
6397 cmdStr += " " + str( sPort )
6398 assert isinstance( dPorts, list )
6399 for dPort in dPorts:
6400 cmdStr += " " + str( dPort )
6401 handle = self.sendline( cmdStr )
6402 assert handle is not None, "Error in sendline"
6403 assert "Command not found:" not in handle, handle
6404 assert "Unsupported command:" not in handle, handle
6405 assert "Error executing command" not in handle, handle
6406 if "Added the mcast route" in handle:
6407 return main.TRUE
6408 else:
6409 return main.FALSE
6410 except AssertionError:
6411 main.log.exception( "" )
6412 return None
6413 except TypeError:
6414 main.log.exception( self.name + ": Object not as expected" )
6415 return None
6416 except pexpect.EOF:
6417 main.log.error( self.name + ": EOF exception found" )
6418 main.log.error( self.name + ": " + self.handle.before )
6419 main.cleanAndExit()
6420 except Exception:
6421 main.log.exception( self.name + ": Uncaught exception!" )
6422 main.cleanAndExit()
6423
6424 def mcastDelete( self, sIP, groupIP, dPorts ):
6425 """
6426 Delete a multicast route by calling 'mcast-delete' command
6427 sIP: source IP of the multicast route
6428 groupIP: group IP of the multicast route
6429 dPorts: a list of destination ports of the multicast route
6430 Returns main.TRUE if mcast route is deleted; Otherwise main.FALSE
6431 """
6432 try:
6433 cmdStr = "mcast-delete"
6434 cmdStr += " " + str( sIP )
6435 cmdStr += " " + str( groupIP )
6436 assert isinstance( dPorts, list )
6437 for dPort in dPorts:
6438 cmdStr += " " + str( dPort )
6439 handle = self.sendline( cmdStr )
6440 assert handle is not None, "Error in sendline"
6441 assert "Command not found:" not in handle, handle
6442 assert "Unsupported command:" not in handle, handle
6443 assert "Error executing command" not in handle, handle
6444 if "Updated the mcast route" in handle:
6445 return main.TRUE
6446 else:
6447 return main.FALSE
6448 except AssertionError:
6449 main.log.exception( "" )
6450 return None
6451 except TypeError:
6452 main.log.exception( self.name + ": Object not as expected" )
6453 return None
6454 except pexpect.EOF:
6455 main.log.error( self.name + ": EOF exception found" )
6456 main.log.error( self.name + ": " + self.handle.before )
6457 main.cleanAndExit()
6458 except Exception:
6459 main.log.exception( self.name + ": Uncaught exception!" )
6460 main.cleanAndExit()
6461
6462 def mcastHostJoin( self, sAddr, gAddr, srcs, sinks ):
6463 """
6464 Create a multicast route by calling 'mcast-host-join' command
6465 sAddr: we can provide * for ASM or a specific address for SSM
6466 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006467 srcs: a list of HostId of the sources e.g. ["00:AA:00:00:00:01/None"]
You Wange24d6272018-03-27 21:18:50 -07006468 sinks: a list of HostId of the sinks e.g. ["00:AA:00:00:01:05/40"]
6469 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6470 """
6471 try:
6472 cmdStr = "mcast-host-join"
6473 cmdStr += " -sAddr " + str( sAddr )
6474 cmdStr += " -gAddr " + str( gAddr )
6475 assert isinstance( srcs, list )
6476 for src in srcs:
6477 cmdStr += " -srcs " + str( src )
6478 assert isinstance( sinks, list )
6479 for sink in sinks:
6480 cmdStr += " -sinks " + str( sink )
6481 handle = self.sendline( cmdStr )
6482 assert handle is not None, "Error in sendline"
6483 assert "Command not found:" not in handle, handle
6484 assert "Unsupported command:" not in handle, handle
6485 assert "Error executing command" not in handle, handle
6486 if "Added the mcast route" in handle:
6487 return main.TRUE
6488 else:
6489 return main.FALSE
6490 except AssertionError:
6491 main.log.exception( "" )
6492 return None
6493 except TypeError:
6494 main.log.exception( self.name + ": Object not as expected" )
6495 return None
6496 except pexpect.EOF:
6497 main.log.error( self.name + ": EOF exception found" )
6498 main.log.error( self.name + ": " + self.handle.before )
6499 main.cleanAndExit()
6500 except Exception:
6501 main.log.exception( self.name + ": Uncaught exception!" )
6502 main.cleanAndExit()
6503
6504 def mcastHostDelete( self, sAddr, gAddr, host=None ):
6505 """
6506 Delete multicast sink(s) by calling 'mcast-host-delete' command
6507 sAddr: we can provide * for ASM or a specific address for SSM
6508 gAddr: specifies multicast group address
You Wangc02d8352018-04-17 16:42:10 -07006509 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
You Wange24d6272018-03-27 21:18:50 -07006510 will delete the route if not specified
6511 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6512 """
6513 try:
6514 cmdStr = "mcast-host-delete"
6515 cmdStr += " -sAddr " + str( sAddr )
6516 cmdStr += " -gAddr " + str( gAddr )
6517 if host:
6518 cmdStr += " -h " + str( host )
6519 handle = self.sendline( cmdStr )
6520 assert handle is not None, "Error in sendline"
6521 assert "Command not found:" not in handle, handle
6522 assert "Unsupported command:" not in handle, handle
6523 assert "Error executing command" not in handle, handle
6524 if "Updated the mcast route" in handle:
6525 return main.TRUE
6526 elif "Deleted the mcast route" in handle:
6527 return main.TRUE
6528 else:
6529 return main.FALSE
6530 except AssertionError:
6531 main.log.exception( "" )
6532 return None
6533 except TypeError:
6534 main.log.exception( self.name + ": Object not as expected" )
6535 return None
6536 except pexpect.EOF:
6537 main.log.error( self.name + ": EOF exception found" )
6538 main.log.error( self.name + ": " + self.handle.before )
6539 main.cleanAndExit()
6540 except Exception:
6541 main.log.exception( self.name + ": Uncaught exception!" )
6542 main.cleanAndExit()
6543
You Wang547893e2018-05-08 13:34:59 -07006544 def mcastSinkDelete( self, sAddr, gAddr, sink=None ):
6545 """
6546 Delete multicast sink(s) by calling 'mcast-sink-delete' command
6547 sAddr: we can provide * for ASM or a specific address for SSM
6548 gAddr: specifies multicast group address
6549 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
6550 will delete the route if not specified
6551 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6552 """
6553 try:
6554 cmdStr = "mcast-sink-delete"
6555 cmdStr += " -sAddr " + str( sAddr )
6556 cmdStr += " -gAddr " + str( gAddr )
6557 if sink:
6558 cmdStr += " -s " + str( sink )
6559 handle = self.sendline( cmdStr )
6560 assert handle is not None, "Error in sendline"
6561 assert "Command not found:" not in handle, handle
6562 assert "Unsupported command:" not in handle, handle
6563 assert "Error executing command" not in handle, handle
6564 if "Updated the mcast route" in handle:
6565 return main.TRUE
6566 elif "Deleted the mcast route" in handle:
6567 return main.TRUE
6568 else:
6569 return main.FALSE
6570 except AssertionError:
6571 main.log.exception( "" )
6572 return None
6573 except TypeError:
6574 main.log.exception( self.name + ": Object not as expected" )
6575 return None
6576 except pexpect.EOF:
6577 main.log.error( self.name + ": EOF exception found" )
6578 main.log.error( self.name + ": " + self.handle.before )
6579 main.cleanAndExit()
6580 except Exception:
6581 main.log.exception( self.name + ": Uncaught exception!" )
6582 main.cleanAndExit()
6583
You Wange24d6272018-03-27 21:18:50 -07006584 def mcastSourceDelete( self, sAddr, gAddr, srcs=None ):
6585 """
6586 Delete multicast src(s) by calling 'mcast-source-delete' command
6587 sAddr: we can provide * for ASM or a specific address for SSM
6588 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006589 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 -07006590 will delete the route if not specified
6591 Returns main.TRUE if mcast sink is deleted; Otherwise main.FALSE
6592 """
6593 try:
6594 cmdStr = "mcast-source-delete"
6595 cmdStr += " -sAddr " + str( sAddr )
6596 cmdStr += " -gAddr " + str( gAddr )
6597 if srcs:
6598 assert isinstance( srcs, list )
6599 for src in srcs:
6600 cmdStr += " -src " + str( src )
6601 handle = self.sendline( cmdStr )
6602 assert handle is not None, "Error in sendline"
6603 assert "Command not found:" not in handle, handle
6604 assert "Unsupported command:" not in handle, handle
6605 assert "Error executing command" not in handle, handle
6606 if "Updated the mcast route" in handle:
6607 return main.TRUE
6608 elif "Deleted the mcast route" in handle:
6609 return main.TRUE
6610 else:
6611 return main.FALSE
6612 except AssertionError:
6613 main.log.exception( "" )
6614 return None
6615 except TypeError:
6616 main.log.exception( self.name + ": Object not as expected" )
6617 return None
6618 except pexpect.EOF:
6619 main.log.error( self.name + ": EOF exception found" )
6620 main.log.error( self.name + ": " + self.handle.before )
6621 main.cleanAndExit()
6622 except Exception:
6623 main.log.exception( self.name + ": Uncaught exception!" )
6624 main.cleanAndExit()
You Wang5da39c82018-04-26 22:55:08 -07006625
6626 def netcfg( self, jsonFormat=True, args="" ):
6627 """
6628 Run netcfg cli command with given args
6629 """
6630 try:
6631 cmdStr = "netcfg"
6632 if jsonFormat:
6633 cmdStr = cmdStr + " -j"
6634 if args:
6635 cmdStr = cmdStr + " " + str( args )
6636 handle = self.sendline( cmdStr )
6637 assert handle is not None, "Error in sendline"
6638 assert "Command not found:" not in handle, handle
6639 assert "Unsupported command:" not in handle, handle
6640 assert "Error executing command" not in handle, handle
6641 return handle
6642 except AssertionError:
6643 main.log.exception( "" )
6644 return None
6645 except TypeError:
6646 main.log.exception( self.name + ": Object not as expected" )
6647 return None
6648 except pexpect.EOF:
6649 main.log.error( self.name + ": EOF exception found" )
6650 main.log.error( self.name + ": " + self.handle.before )
6651 main.cleanAndExit()
6652 except Exception:
6653 main.log.exception( self.name + ": Uncaught exception!" )
6654 main.cleanAndExit()
6655
You Wang0fa76e72018-05-18 11:33:25 -07006656 def composeT3Command( self, sAddr, dAddr, ipv6=False, verbose=True, simple=False ):
You Wang5da39c82018-04-26 22:55:08 -07006657 """
You Wang54b1d672018-06-11 16:44:13 -07006658 Compose and return a list of t3-troubleshoot cli commands for given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006659 Options:
6660 sAddr: IP address of the source host
6661 dAddr: IP address of the destination host
You Wang0fa76e72018-05-18 11:33:25 -07006662 ipv6: True if hosts are IPv6
6663 verbose: return verbose t3 output if True
6664 simple: compose command for t3-troubleshoot-simple if True
You Wang5da39c82018-04-26 22:55:08 -07006665 """
6666 try:
6667 # Collect information of both hosts from onos
6668 hosts = self.hosts()
6669 hosts = json.loads( hosts )
6670 sHost = None
6671 dHost = None
6672 for host in hosts:
6673 if sAddr in host[ "ipAddresses" ]:
6674 sHost = host
6675 elif dAddr in host[ "ipAddresses" ]:
6676 dHost = host
6677 if sHost and dHost:
6678 break
6679 assert sHost, "Not able to find host with IP {}".format( sAddr )
You Wang54b1d672018-06-11 16:44:13 -07006680 cmdList = []
You Wang5d9527b2018-05-29 17:08:54 -07006681 if simple:
6682 assert dHost, "Not able to find host with IP {}".format( dAddr )
You Wang54b1d672018-06-11 16:44:13 -07006683 cmdStr = "t3-troubleshoot-simple"
6684 if verbose:
6685 cmdStr += " -vv"
6686 if ipv6:
6687 cmdStr += " -et ipv6"
You Wang0fa76e72018-05-18 11:33:25 -07006688 cmdStr += " {}/{} {}/{}".format( sHost[ "mac" ], sHost[ "vlan" ], dHost[ "mac" ], dHost[ "vlan" ] )
You Wang54b1d672018-06-11 16:44:13 -07006689 cmdList.append( cmdStr )
You Wang0fa76e72018-05-18 11:33:25 -07006690 else:
You Wang54b1d672018-06-11 16:44:13 -07006691 for location in sHost[ "locations" ]:
6692 cmdStr = "t3-troubleshoot"
6693 if verbose:
6694 cmdStr += " -vv"
6695 if ipv6:
6696 cmdStr += " -et ipv6"
6697 cmdStr += " -s " + str( sAddr )
6698 cmdStr += " -sp " + str( location[ "elementId" ] ) + "/" + str( location[ "port" ] )
6699 cmdStr += " -sm " + str( sHost[ "mac" ] )
6700 if sHost[ "vlan" ] != "None":
6701 cmdStr += " -vid " + sHost[ "vlan" ]
6702 cmdStr += " -d " + str( dAddr )
6703 netcfg = self.netcfg( args="devices {}".format( location[ "elementId" ] ) )
6704 netcfg = json.loads( netcfg )
6705 assert netcfg, "Failed to get netcfg"
6706 cmdStr += " -dm " + str( netcfg[ "segmentrouting" ][ "routerMac" ] )
6707 cmdList.append( cmdStr )
6708 return cmdList
You Wang5da39c82018-04-26 22:55:08 -07006709 except AssertionError:
6710 main.log.exception( "" )
6711 return None
6712 except ( KeyError, TypeError ):
6713 main.log.exception( self.name + ": Object not as expected" )
6714 return None
6715 except Exception:
6716 main.log.exception( self.name + ": Uncaught exception!" )
6717 main.cleanAndExit()
6718
6719 def t3( self, sAddr, dAddr, ipv6=False ):
6720 """
You Wang54b1d672018-06-11 16:44:13 -07006721 Run t3-troubleshoot cli commands for all posible routes given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006722 Options:
6723 sAddr: IP address of the source host
6724 dAddr: IP address of the destination host
6725 """
6726 try:
You Wang54b1d672018-06-11 16:44:13 -07006727 cmdList = self.composeT3Command( sAddr, dAddr, ipv6 )
6728 assert cmdList is not None, "composeT3Command returned None"
6729 t3Output = ""
6730 for cmdStr in cmdList:
6731 handle = self.sendline( cmdStr )
6732 assert handle is not None, "Error in sendline"
6733 assert "Command not found:" not in handle, handle
6734 assert "Unsupported command:" not in handle, handle
6735 assert "Error executing command" not in handle, handle
6736 assert "Tracing packet" in handle
6737 t3Output += handle
6738 return t3Output
You Wang5da39c82018-04-26 22:55:08 -07006739 except AssertionError:
6740 main.log.exception( "" )
6741 return None
6742 except pexpect.EOF:
6743 main.log.error( self.name + ": EOF exception found" )
6744 main.log.error( self.name + ": " + self.handle.before )
6745 main.cleanAndExit()
6746 except Exception:
6747 main.log.exception( self.name + ": Uncaught exception!" )
6748 main.cleanAndExit()
Jon Hall3c0114c2020-08-11 15:07:42 -07006749
6750 def prepareForCLI( self, debug=True, maxRetries=120 ):
6751 """
6752 Prepare docker container to connect to onos cli
6753 """
6754 try:
6755 # Wait for log files to be created
6756 ready = 0
6757 retries = 0
6758 while not ready and retries < maxRetries:
6759 retries += 1
6760 self.handle.sendline( "ls -al /root/onos/apache-karaf-*/data/log" )
6761 ready = self.handle.expect( [ "No such file or directory", self.dockerPrompt ] )
6762 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6763 if not ready:
6764 self.handle.expect( self.dockerPrompt )
6765 time.sleep( 1 )
Jon Hall3c0114c2020-08-11 15:07:42 -07006766
6767 cmdList = []
6768 cmdList.append( "apt-get update" )
6769 cmdList.append( "apt-get install -y openssh-server" )
6770 # Some built in scripts are hardcoded
6771 cmdList.append( "ln -s /root/onos /opt/onos" )
6772 cmdList.append( "ln -s /root/onos/apache-karaf-*/data/log /opt/onos/log" )
6773 cmdList.append( "ls -al /opt/onos" )
6774 output = ""
6775 for cmdStr in cmdList:
6776 self.handle.sendline( cmdStr )
Jon Hall39570262020-11-17 12:18:19 -08006777 self.handle.expect( self.dockerPrompt, timeout=120 )
Jon Hall3c0114c2020-08-11 15:07:42 -07006778 self.handle.sendline( "" )
6779 self.handle.expect( self.dockerPrompt )
6780 handle = self.handle.before
6781 assert "command not found" not in handle, handle
6782 assert "No such file or directory" not in handle, handle
6783 output += handle
6784 if debug:
6785 main.log.debug( "%s: %s" % ( self.name, output ) )
6786 return output
6787 except AssertionError:
6788 main.log.exception( "" )
6789 return None
6790 except pexpect.EOF:
6791 main.log.error( self.name + ": EOF exception found" )
6792 main.log.error( self.name + ": " + self.handle.before )
6793 main.cleanAndExit()
6794 except Exception:
6795 main.log.exception( self.name + ": Uncaught exception!" )
6796 main.cleanAndExit()
6797
6798 def onosSecureSSH( self, userName="onos", userPWD="rocks" ):
6799 """
6800 Enables secure access to ONOS console
6801 by removing default users & keys.
6802
6803 bin/onos-user-password onos rocks
6804
6805 Returns: main.TRUE on success and main.FALSE on failure
6806 """
6807
6808 try:
6809 self.handle.sendline( "" )
6810 self.handle.expect( self.dockerPrompt )
6811
6812 self.handle.sendline( "[ ! -f ~/.ssh/id_rsa.pub ] && ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' -q" )
6813 self.handle.expect( self.dockerPrompt )
6814 main.log.debug( "%s: %s%s" % ( self.name, self.handle.before, self.handle.after ) )
6815
6816 self.handle.sendline( "bin/onos-user-key $(id -un) $(cut -d\\\\ -f2 ~/.ssh/id_rsa.pub)" )
6817 self.handle.expect( pexpect.TIMEOUT, timeout=10 )
6818 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6819
6820 self.handle.sendline( "bin/onos-user-password %s %s" % ( userName, userPWD ) )
6821 i = self.handle.expect( [ "usage",
6822 self.dockerPrompt,
6823 pexpect.TIMEOUT ] )
6824 if i == 0:
6825 # malformed command
6826 main.log.warn( self.name + ": Could not parse onos-user-password command" )
6827 self.handle.expect( self.dockerPrompt )
6828 return main.FALSE
6829 elif i == 1:
6830 # Process started
6831 main.log.info( self.name + ": SSH password added for user " + userName )
6832 return main.TRUE
6833 elif i == 2:
6834 # timeout
6835 main.log.error( self.name + ": Failed to secure onos ssh " )
6836 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6837 except pexpect.EOF:
6838 main.log.error( self.name + ": EOF exception found" )
6839 main.log.error( self.name + ": " + self.handle.before )
6840 main.cleanAndExit()
6841 except Exception:
6842 main.log.exception( self.name + ": Uncaught exception!" )
6843 main.cleanAndExit()