blob: 72ed62c720d0c1fce8343b3ed4a251382a8789d9 [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 Hall9b0de1f2020-08-24 15:38:04 -0700304 setTimeout = 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 Hall9b0de1f2020-08-24 15:38:04 -0700312 if setTimeout:
313 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" )
321 self.handle.sendline( startCliCommand )
322 setTimeout = True
Jon Hall3c0114c2020-08-11 15:07:42 -0700323 elif i == 1:
324 main.log.info( str( ONOSIp ) + " CLI asking for password" )
325 main.log.debug( "Sending %s" % self.karafPass )
326 self.handle.sendline( self.karafPass )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400327 else:
Jon Hall3c0114c2020-08-11 15:07:42 -0700328 # If failed, send ctrl+c to process and try again
329 main.log.info( "Starting CLI failed. Retrying..." )
330 self.handle.send( "\x03" )
331 self.handle.sendline( startCliCommand )
332 tries += 1
333 main.log.error( "Connection to CLI " + str( ONOSIp ) + " timeout" )
334 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -0800335 except TypeError:
336 main.log.exception( self.name + ": Object not as expected" )
337 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400338 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800339 main.log.error( self.name + ": EOF exception found" )
340 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700341 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800342 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800343 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700344 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400345
suibin zhang116647a2016-05-06 16:30:09 -0700346 def startCellCli( self, karafTimeout="",
347 commandlineTimeout=10, onosStartTimeout=60 ):
348 """
Jon Hall3c0114c2020-08-11 15:07:42 -0700349 Start CLI on onos cell handle.
suibin zhang116647a2016-05-06 16:30:09 -0700350
351 karafTimeout is an optional argument. karafTimeout value passed
352 by user would be used to set the current karaf shell idle timeout.
353 Note that when ever this property is modified the shell will exit and
354 the subsequent login would reflect new idle timeout.
355 Below is an example to start a session with 60 seconds idle timeout
356 ( input value is in milliseconds ):
357
358 tValue = "60000"
359
360 Note: karafTimeout is left as str so that this could be read
361 and passed to startOnosCli from PARAMS file as str.
362 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000363
suibin zhang116647a2016-05-06 16:30:09 -0700364 try:
365 self.handle.sendline( "" )
366 x = self.handle.expect( [
Jon Hall3c0114c2020-08-11 15:07:42 -0700367 self.Prompt(), self.karafPrompt ], commandlineTimeout )
suibin zhang116647a2016-05-06 16:30:09 -0700368
369 if x == 1:
370 main.log.info( "ONOS cli is already running" )
371 return main.TRUE
372
Jeremy Ronquilloec916a42018-02-02 13:05:57 -0800373 # Wait for onos start ( onos-wait-for-start ) and enter onos cli
suibin zhang116647a2016-05-06 16:30:09 -0700374 self.handle.sendline( "/opt/onos/bin/onos" )
375 i = self.handle.expect( [
Jon Hall6c9e2da2018-11-06 12:01:23 -0800376 self.karafPrompt,
suibin zhang116647a2016-05-06 16:30:09 -0700377 pexpect.TIMEOUT ], onosStartTimeout )
378
379 if i == 0:
380 main.log.info( self.name + " CLI Started successfully" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800381 if karafTimeout: # FIXME: This doesn't look right
suibin zhang116647a2016-05-06 16:30:09 -0700382 self.handle.sendline(
383 "config:property-set -p org.apache.karaf.shell\
384 sshIdleTimeout " +
385 karafTimeout )
Jon Hall3c0114c2020-08-11 15:07:42 -0700386 self.handle.expect( self.Prompt() )
suibin zhang116647a2016-05-06 16:30:09 -0700387 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800388 self.handle.expect( self.karafPrompt )
suibin zhang116647a2016-05-06 16:30:09 -0700389 return main.TRUE
390 else:
391 # If failed, send ctrl+c to process and try again
392 main.log.info( "Starting CLI failed. Retrying..." )
393 self.handle.send( "\x03" )
394 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800395 i = self.handle.expect( [ self.karafPrompt, pexpect.TIMEOUT ],
suibin zhang116647a2016-05-06 16:30:09 -0700396 timeout=30 )
397 if i == 0:
398 main.log.info( self.name + " CLI Started " +
399 "successfully after retry attempt" )
400 if karafTimeout:
401 self.handle.sendline(
402 "config:property-set -p org.apache.karaf.shell\
403 sshIdleTimeout " +
404 karafTimeout )
Jon Hall3c0114c2020-08-11 15:07:42 -0700405 self.handle.expect( self.Prompt() )
suibin zhang116647a2016-05-06 16:30:09 -0700406 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800407 self.handle.expect( self.karafPrompt )
suibin zhang116647a2016-05-06 16:30:09 -0700408 return main.TRUE
409 else:
410 main.log.error( "Connection to CLI " +
411 self.name + " timeout" )
412 return main.FALSE
413
414 except TypeError:
415 main.log.exception( self.name + ": Object not as expected" )
416 return None
417 except pexpect.EOF:
418 main.log.error( self.name + ": EOF exception found" )
419 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700420 main.cleanAndExit()
suibin zhang116647a2016-05-06 16:30:09 -0700421 except Exception:
422 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700423 main.cleanAndExit()
suibin zhang116647a2016-05-06 16:30:09 -0700424
Pratik Parab3b2ab5a2017-02-14 13:15:14 -0800425 def log( self, cmdStr, level="", noExit=False ):
kelvin-onlab9f541032015-02-04 16:19:53 -0800426 """
427 log the commands in the onos CLI.
kelvin-onlab338f5512015-02-06 10:53:16 -0800428 returns main.TRUE on success
Jon Hallefbd9792015-03-05 16:11:36 -0800429 returns main.FALSE if Error occurred
YPZhangebf9eb52016-05-12 15:20:24 -0700430 if noExit is True, TestON will not exit, but clean up
kelvin-onlab338f5512015-02-06 10:53:16 -0800431 Available level: DEBUG, TRACE, INFO, WARN, ERROR
432 Level defaults to INFO
Pratik Parab3b2ab5a2017-02-14 13:15:14 -0800433 if cmdStr has spaces then put quotes in the passed string
kelvin-onlab9f541032015-02-04 16:19:53 -0800434 """
435 try:
kelvin-onlab338f5512015-02-06 10:53:16 -0800436 lvlStr = ""
437 if level:
438 lvlStr = "--level=" + level
439
kelvin-onlab338f5512015-02-06 10:53:16 -0800440 self.handle.sendline( "log:log " + lvlStr + " " + cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -0700441 self.handle.expect( "log:log" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800442 self.handle.expect( self.karafPrompt )
kelvin-onlabfb521662015-02-27 09:52:40 -0800443
kelvin-onlab9f541032015-02-04 16:19:53 -0800444 response = self.handle.before
445 if re.search( "Error", response ):
Jon Halldac3eae2020-06-05 12:04:06 -0700446 main.log.debug( response )
kelvin-onlab9f541032015-02-04 16:19:53 -0800447 return main.FALSE
448 return main.TRUE
Jon Hall80daded2015-05-27 16:07:00 -0700449 except pexpect.TIMEOUT:
450 main.log.exception( self.name + ": TIMEOUT exception found" )
Jon Hall43060f62020-06-23 13:13:33 -0700451 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700452 if noExit:
453 main.cleanup()
454 return None
455 else:
Devin Lim44075962017-08-11 10:56:37 -0700456 main.cleanAndExit()
kelvin-onlab9f541032015-02-04 16:19:53 -0800457 except pexpect.EOF:
458 main.log.error( self.name + ": EOF exception found" )
459 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700460 if noExit:
461 main.cleanup()
462 return None
463 else:
Devin Lim44075962017-08-11 10:56:37 -0700464 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800465 except Exception:
kelvin-onlabfb521662015-02-27 09:52:40 -0800466 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700467 if noExit:
468 main.cleanup()
469 return None
470 else:
Devin Lim44075962017-08-11 10:56:37 -0700471 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400472
Jon Hall0e240372018-05-02 11:21:57 -0700473 def clearBuffer( self, debug=False, timeout=10, noExit=False ):
kelvin8ec71442015-01-15 16:57:00 -0800474 """
Jon Hall0e240372018-05-02 11:21:57 -0700475 Test cli connection and clear any left over output in the buffer
476 Optional Arguments:
477 debug - Defaults to False. If True, will enable debug logging.
478 timeout - Defaults to 10. Amount of time in seconds for a command to return
479 before a timeout.
480 noExit - Defaults to False. If True, will not exit TestON in the event of a
kelvin8ec71442015-01-15 16:57:00 -0800481 """
andrewonlaba18f6bf2014-10-13 19:31:54 -0400482 try:
Jon Halla495f562016-05-16 18:03:26 -0700483 # Try to reconnect if disconnected from cli
484 self.handle.sendline( "" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700485 i = self.handle.expect( [ self.karafPrompt,
486 self.Prompt(),
487 pexpect.TIMEOUT ] )
Jon Hall0e240372018-05-02 11:21:57 -0700488 response = self.handle.before
Jon Halla495f562016-05-16 18:03:26 -0700489 if i == 1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700490 main.log.error( self.name + ": onos cli session closed. " )
Jon Halla495f562016-05-16 18:03:26 -0700491 if self.onosIp:
492 main.log.warn( "Trying to reconnect " + self.onosIp )
493 reconnectResult = self.startOnosCli( self.onosIp )
494 if reconnectResult:
495 main.log.info( self.name + ": onos cli session reconnected." )
496 else:
497 main.log.error( self.name + ": reconnection failed." )
YPZhang14a4aa92016-07-15 13:37:15 -0700498 if noExit:
499 return None
500 else:
Devin Lim44075962017-08-11 10:56:37 -0700501 main.cleanAndExit()
Jon Halla495f562016-05-16 18:03:26 -0700502 else:
Devin Lim44075962017-08-11 10:56:37 -0700503 main.cleanAndExit()
Jon Halla495f562016-05-16 18:03:26 -0700504 if i == 2:
Jon Hall7a6ebfd2017-03-13 10:58:58 -0700505 main.log.warn( "Timeout when testing cli responsiveness" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700506 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
Jon Hall7a6ebfd2017-03-13 10:58:58 -0700507 self.handle.send( "\x03" ) # Send ctrl-c to clear previous output
Jon Hall6c9e2da2018-11-06 12:01:23 -0800508 self.handle.expect( self.karafPrompt )
Jon Halla495f562016-05-16 18:03:26 -0700509
Jon Hall0e240372018-05-02 11:21:57 -0700510 response += self.handle.before
Jon Hall14a03b52016-05-11 12:07:30 -0700511 if debug:
Jon Hall0e240372018-05-02 11:21:57 -0700512 main.log.debug( self.name + ": Raw output from sending ''" )
513 main.log.debug( self.name + ": " + repr( response ) )
514 except pexpect.TIMEOUT:
515 main.log.error( self.name + ": ONOS timeout" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700516 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
You Wang141b43b2018-06-26 16:50:18 -0700517 self.handle.send( "\x03" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800518 self.handle.expect( self.karafPrompt )
Jon Hall0e240372018-05-02 11:21:57 -0700519 return None
520 except pexpect.EOF:
521 main.log.error( self.name + ": EOF exception found" )
522 main.log.error( self.name + ": " + self.handle.before )
523 if noExit:
524 return None
525 else:
526 main.cleanAndExit()
527 except Exception:
528 main.log.exception( self.name + ": Uncaught exception!" )
529 if noExit:
530 return None
531 else:
532 main.cleanAndExit()
533
Jon Hall22e94ce2019-01-15 14:52:17 -0800534 def sendline( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False, relaxedRegex=True, expectJson=False ):
Jon Hall0e240372018-05-02 11:21:57 -0700535 """
536 A wrapper around pexpect's sendline/expect. Will return all the output from a given command
537
538 Required Arguments:
539 cmdStr - String to send to the pexpect session
540
541 Optional Arguments:
542 showResponse - Defaults to False. If True will log the response.
543 debug - Defaults to False. If True, will enable debug logging.
544 timeout - Defaults to 10. Amount of time in seconds for a command to return
545 before a timeout.
546 noExit - Defaults to False. If True, will not exit TestON in the event of a
547 closed channel, but instead return None
Jon Hall6c9e2da2018-11-06 12:01:23 -0800548 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 -0700549
550 Warning: There are no sanity checking to commands sent using this method.
551
552 """
553 try:
554 # Try to reconnect if disconnected from cli
555 self.clearBuffer( debug=debug, timeout=timeout, noExit=noExit )
556 if debug:
557 # NOTE: This adds an average of .4 seconds per call
Jon Hall14a03b52016-05-11 12:07:30 -0700558 logStr = "\"Sending CLI command: '" + cmdStr + "'\""
Jon Halle0f0b342017-04-18 11:43:47 -0700559 self.log( logStr, noExit=noExit )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800560 self.handle.sendline( cmdStr )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800561 self.handle.expect( self.karafPrompt, timeout )
Jon Hall63604932015-02-26 17:09:50 -0800562 response = self.handle.before
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000563 main.log.info( "Command '" + str( cmdStr ) + "' sent to "
Jon Hallc6793552016-01-19 14:18:37 -0800564 + self.name + "." )
Jon Hallc6358dd2015-04-10 12:44:28 -0700565 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700566 main.log.debug( self.name + ": Raw output" )
567 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700568
Jon Hall3c0114c2020-08-11 15:07:42 -0700569 response = self.cleanOutput( response, debug=debug )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800570 # Remove control codes from karaf 4.2.1
Jon Hall3c0114c2020-08-11 15:07:42 -0700571 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 -0800572 response = karafEscape.sub( '', response )
573 if debug:
574 main.log.debug( self.name + ": karafEscape output" )
575 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700576 # Remove ANSI color control strings from output
Jon Hall43060f62020-06-23 13:13:33 -0700577 response = self.cleanOutput( response, debug )
Jon Hallc6358dd2015-04-10 12:44:28 -0700578
Jon Hall6c9e2da2018-11-06 12:01:23 -0800579 # Remove ANSI color control strings from output
Jon Hallcf31d0f2018-12-13 11:18:48 -0800580 # NOTE: karaf is sometimes adding a single character then two
581 # backspaces and sometimes adding 2 characters with 2 backspaces??
Jon Hall3c0114c2020-08-11 15:07:42 -0700582 backspaceEscape = re.compile( r'((.|\s)\x08)' )
583 unchanged = False
584 while not unchanged:
585 old = response
586 response = backspaceEscape.sub( '', response, count=1 )
587 if debug:
588 main.log.debug( self.name + ": backspaceEscape output" )
589 main.log.debug( self.name + ": " + repr( response ) )
590 unchanged = old == response
Jon Hall6c9e2da2018-11-06 12:01:23 -0800591
kelvin-onlabfb521662015-02-27 09:52:40 -0800592 # Remove extra return chars that get added
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000593 response = re.sub( r"\s\r", "", response )
Jon Hallc6358dd2015-04-10 12:44:28 -0700594 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700595 main.log.debug( self.name + ": Removed extra returns " +
596 "from output" )
597 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700598
599 # Strip excess whitespace
Jon Hall63604932015-02-26 17:09:50 -0800600 response = response.strip()
Jon Hallc6358dd2015-04-10 12:44:28 -0700601 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700602 main.log.debug( self.name + ": parsed and stripped output" )
603 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700604
Jon Hall63604932015-02-26 17:09:50 -0800605 # parse for just the output, remove the cmd from response
Jon Hallce0d70b2018-12-11 11:01:32 -0800606 cmdPattern = cmdStr.strip()
607 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
608 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800609 if relaxedRegex:
Jon Hallce0d70b2018-12-11 11:01:32 -0800610 cmdPattern = cmdPattern.split( '|' )[ -1 ].strip()
611 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
612 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800613 # This was added because karaf 4.2 is stripping some characters from the command echo
Jon Hallce0d70b2018-12-11 11:01:32 -0800614 output = response.split( cmdPattern, 1 )
Jon Hall22e94ce2019-01-15 14:52:17 -0800615 if expectJson:
616 main.log.warn( "Relaxed Regex: Searching for a json string amongst the output" )
617 jsonPattern = r'\{.*\}'
618 match = re.search( jsonPattern, output[ 0 ] )
619 if match:
620 output = [ '' , match.group( 0 ) ] # We expect a list with the second element to be the output
Jon Hall39e3ffe2018-12-05 11:40:29 -0800621 if len( output ) < 2:
622 main.log.warn( "Relaxing regex match to last 5 characters of the sent command" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800623 cmdPattern = cmdPattern[ -5: ]
624 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
625 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
626 output = response.split( cmdPattern, 1 )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800627 else:
Jon Hallce0d70b2018-12-11 11:01:32 -0800628 output = response.split( cmdPattern, 1 )
629 if len( output ) < 2: # TODO: Should we do this without the relaxedRegex flag?
Jon Hall8c9dd1c2018-11-14 15:40:39 -0800630 main.log.warn( "Relaxing regex match to last 5 characters of the sent command" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800631 output = response.split( cmdPattern[ -5: ], 1 )
Jon Hall0e240372018-05-02 11:21:57 -0700632 if output:
633 if debug:
634 main.log.debug( self.name + ": split output" )
635 for r in output:
636 main.log.debug( self.name + ": " + repr( r ) )
Jon Hallce0d70b2018-12-11 11:01:32 -0800637 if len( output ) == 1:
638 main.log.error( "Could not remove sent command echo from output" )
639 return output
Jon Hall0e240372018-05-02 11:21:57 -0700640 output = output[ 1 ].strip()
GlennRC85870432015-11-23 11:45:51 -0800641 if showResponse:
GlennRCed771242016-01-13 17:02:47 -0800642 main.log.info( "Response from ONOS: {}".format( output ) )
Jon Hall0e240372018-05-02 11:21:57 -0700643 self.clearBuffer( debug=debug, timeout=timeout, noExit=noExit )
GlennRC85870432015-11-23 11:45:51 -0800644 return output
GlennRCed771242016-01-13 17:02:47 -0800645 except pexpect.TIMEOUT:
Jon Hall0e240372018-05-02 11:21:57 -0700646 main.log.error( self.name + ": ONOS timeout" )
GlennRCed771242016-01-13 17:02:47 -0800647 if debug:
Jon Hall3c0114c2020-08-11 15:07:42 -0700648 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
You Wang6b5e5ba2019-01-31 15:32:40 -0800649 self.exitFromCmd( self.karafPrompt, 100 )
GlennRCed771242016-01-13 17:02:47 -0800650 return None
Jon Hallc6358dd2015-04-10 12:44:28 -0700651 except IndexError:
652 main.log.exception( self.name + ": Object not as expected" )
Jon Halla495f562016-05-16 18:03:26 -0700653 main.log.debug( "response: {}".format( repr( response ) ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700654 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800655 except TypeError:
656 main.log.exception( self.name + ": Object not as expected" )
657 return None
andrewonlaba18f6bf2014-10-13 19:31:54 -0400658 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800659 main.log.error( self.name + ": EOF exception found" )
660 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700661 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700662 return None
663 else:
Devin Lim44075962017-08-11 10:56:37 -0700664 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800665 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800666 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700667 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700668 return None
669 else:
Devin Lim44075962017-08-11 10:56:37 -0700670 main.cleanAndExit()
andrewonlaba18f6bf2014-10-13 19:31:54 -0400671
Jon Halld5a94fb2018-11-13 14:32:23 -0800672 def lineCount( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False, relaxedRegex=True ):
673 """
674 A wrapper around sendline(). Will return the number of lines returned or None on error
675
676 Required Arguments:
677 cmdStr - String to send to the pexpect session
678
679 Optional Arguments:
680 showResponse - Defaults to False. If True will log the response.
681 debug - Defaults to False. If True, will enable debug logging.
682 timeout - Defaults to 10. Amount of time in seconds for a command to return
683 before a timeout.
684 noExit - Defaults to False. If True, will not exit TestON in the event of a
685 closed channel, but instead return None
686 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.
687
688 Warning: There are no sanity checking to commands sent using this method.
689
690 """
691 try:
692 numLines = self.sendline( cmdStr, showResponse, debug, timeout, noExit, relaxedRegex )
You Wang0ce8e0c2019-02-22 12:22:26 -0800693 parsed = re.search( "(\d+)", numLines )
Jon Hall8c9dd1c2018-11-14 15:40:39 -0800694 if not parsed:
695 main.log.error( "Warning, output of karaf's wc may have changed" )
696 return None
697 return parsed.group( 1 )
Jon Halld5a94fb2018-11-13 14:32:23 -0800698 except IndexError:
699 main.log.exception( self.name + ": Object not as expected" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800700 main.log.debug( "response: {}".format( repr( numLines ) ) )
Jon Halld5a94fb2018-11-13 14:32:23 -0800701 return None
702 except TypeError:
703 main.log.exception( self.name + ": Object not as expected" )
704 return None
705 except Exception:
706 main.log.exception( self.name + ": Uncaught exception!" )
707 if noExit:
708 return None
709 else:
710 main.cleanAndExit()
711
kelvin8ec71442015-01-15 16:57:00 -0800712 # IMPORTANT NOTE:
713 # For all cli commands, naming convention should match
kelvin-onlabd3b64892015-01-20 13:26:24 -0800714 # the cli command changing 'a:b' with 'aB'.
715 # Ex ) onos:topology > onosTopology
716 # onos:links > onosLinks
717 # feature:list > featureList
Jon Halle3f39ff2015-01-13 11:50:53 -0800718
kelvin-onlabd3b64892015-01-20 13:26:24 -0800719 def addNode( self, nodeId, ONOSIp, tcpPort="" ):
kelvin8ec71442015-01-15 16:57:00 -0800720 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400721 Adds a new cluster node by ID and address information.
722 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800723 * nodeId
724 * ONOSIp
andrewonlabc2d05aa2014-10-13 16:51:10 -0400725 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800726 * tcpPort
kelvin8ec71442015-01-15 16:57:00 -0800727 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400728 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800729 cmdStr = "add-node " + str( nodeId ) + " " +\
730 str( ONOSIp ) + " " + str( tcpPort )
731 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700732 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800733 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -0800734 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700735 main.log.error( self.name + ": Error in adding node" )
kelvin8ec71442015-01-15 16:57:00 -0800736 main.log.error( handle )
Jon Halle3f39ff2015-01-13 11:50:53 -0800737 return main.FALSE
andrewonlabc2d05aa2014-10-13 16:51:10 -0400738 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800739 main.log.info( "Node " + str( ONOSIp ) + " added" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400740 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800741 except AssertionError:
742 main.log.exception( "" )
743 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800744 except TypeError:
745 main.log.exception( self.name + ": Object not as expected" )
746 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400747 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800748 main.log.error( self.name + ": EOF exception found" )
749 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700750 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800751 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800752 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700753 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400754
kelvin-onlabd3b64892015-01-20 13:26:24 -0800755 def removeNode( self, nodeId ):
kelvin8ec71442015-01-15 16:57:00 -0800756 """
andrewonlab86dc3082014-10-13 18:18:38 -0400757 Removes a cluster by ID
758 Issues command: 'remove-node [<node-id>]'
759 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800760 * nodeId
kelvin8ec71442015-01-15 16:57:00 -0800761 """
andrewonlab86dc3082014-10-13 18:18:38 -0400762 try:
andrewonlab86dc3082014-10-13 18:18:38 -0400763
kelvin-onlabd3b64892015-01-20 13:26:24 -0800764 cmdStr = "remove-node " + str( nodeId )
Jon Hall08f61bc2015-04-13 16:00:30 -0700765 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700766 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800767 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700768 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700769 main.log.error( self.name + ": Error in removing node" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700770 main.log.error( handle )
771 return main.FALSE
772 else:
773 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800774 except AssertionError:
775 main.log.exception( "" )
776 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800777 except TypeError:
778 main.log.exception( self.name + ": Object not as expected" )
779 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400780 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800781 main.log.error( self.name + ": EOF exception found" )
782 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700783 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800784 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800785 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700786 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400787
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700788 def nodes( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800789 """
andrewonlab7c211572014-10-15 16:45:20 -0400790 List the nodes currently visible
791 Issues command: 'nodes'
Jon Hall61282e32015-03-19 11:34:11 -0700792 Optional argument:
793 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800794 """
andrewonlab7c211572014-10-15 16:45:20 -0400795 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700796 cmdStr = "nodes"
Jon Hall61282e32015-03-19 11:34:11 -0700797 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700798 cmdStr += " -j"
799 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700800 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800801 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -0700802 return output
Jon Hallc6793552016-01-19 14:18:37 -0800803 except AssertionError:
804 main.log.exception( "" )
805 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800806 except TypeError:
807 main.log.exception( self.name + ": Object not as expected" )
808 return None
andrewonlab7c211572014-10-15 16:45:20 -0400809 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800810 main.log.error( self.name + ": EOF exception found" )
811 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700812 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800813 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800814 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700815 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400816
kelvin8ec71442015-01-15 16:57:00 -0800817 def topology( self ):
818 """
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700819 Definition:
Jon Hall390696c2015-05-05 17:13:41 -0700820 Returns the output of topology command.
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700821 Return:
822 topology = current ONOS topology
kelvin8ec71442015-01-15 16:57:00 -0800823 """
andrewonlab95ce8322014-10-13 14:12:04 -0400824 try:
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700825 cmdStr = "topology -j"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800826 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800827 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800828 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700829 main.log.info( cmdStr + " returned: " + str( handle ) )
andrewonlab95ce8322014-10-13 14:12:04 -0400830 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800831 except AssertionError:
832 main.log.exception( "" )
Jon Halld4d4b372015-01-28 16:02:41 -0800833 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800834 except TypeError:
835 main.log.exception( self.name + ": Object not as expected" )
836 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400837 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800838 main.log.error( self.name + ": EOF exception found" )
839 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700840 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800841 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800842 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700843 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -0800844
jenkins7ead5a82015-03-13 10:28:21 -0700845 def deviceRemove( self, deviceId ):
846 """
847 Removes particular device from storage
848
849 TODO: refactor this function
850 """
851 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700852 cmdStr = "device-remove " + str( deviceId )
853 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800854 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800855 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700856 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700857 main.log.error( self.name + ": Error in removing device" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700858 main.log.error( handle )
859 return main.FALSE
860 else:
861 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800862 except AssertionError:
863 main.log.exception( "" )
864 return None
jenkins7ead5a82015-03-13 10:28:21 -0700865 except TypeError:
866 main.log.exception( self.name + ": Object not as expected" )
867 return None
868 except pexpect.EOF:
869 main.log.error( self.name + ": EOF exception found" )
870 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700871 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700872 except Exception:
873 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700874 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700875
You Wang3b9689a2018-08-30 12:24:00 -0700876 def devices( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -0800877 """
Jon Hall7b02d952014-10-17 20:14:54 -0400878 Lists all infrastructure devices or switches
andrewonlab86dc3082014-10-13 18:18:38 -0400879 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800880 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800881 """
andrewonlab86dc3082014-10-13 18:18:38 -0400882 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700883 cmdStr = "devices"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800884 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700885 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -0700886 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -0800887 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800888 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700889 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800890 except AssertionError:
891 main.log.exception( "" )
892 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800893 except TypeError:
894 main.log.exception( self.name + ": Object not as expected" )
895 return None
andrewonlab7c211572014-10-15 16:45:20 -0400896 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800897 main.log.error( self.name + ": EOF exception found" )
898 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700899 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800900 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800901 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700902 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400903
kelvin-onlabd3b64892015-01-20 13:26:24 -0800904 def balanceMasters( self ):
kelvin8ec71442015-01-15 16:57:00 -0800905 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800906 This balances the devices across all controllers
907 by issuing command: 'onos> onos:balance-masters'
908 If required this could be extended to return devices balanced output.
kelvin8ec71442015-01-15 16:57:00 -0800909 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800910 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800911 cmdStr = "onos:balance-masters"
Jon Hallc6358dd2015-04-10 12:44:28 -0700912 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800913 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800914 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700915 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700916 main.log.error( self.name + ": Error in balancing masters" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700917 main.log.error( handle )
918 return main.FALSE
919 else:
920 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800921 except AssertionError:
922 main.log.exception( "" )
923 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800924 except TypeError:
925 main.log.exception( self.name + ": Object not as expected" )
926 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800927 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800928 main.log.error( self.name + ": EOF exception found" )
929 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700930 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800931 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800932 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700933 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800934
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000935 def checkMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700936 """
937 Returns the output of the masters command.
938 Optional argument:
939 * jsonFormat - boolean indicating if you want output in json
940 """
941 try:
942 cmdStr = "onos:masters"
943 if jsonFormat:
944 cmdStr += " -j"
945 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700946 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800947 assert "Command not found:" not in output, output
acsmars24950022015-07-30 18:00:43 -0700948 return output
Jon Hallc6793552016-01-19 14:18:37 -0800949 except AssertionError:
950 main.log.exception( "" )
951 return None
acsmars24950022015-07-30 18:00:43 -0700952 except TypeError:
953 main.log.exception( self.name + ": Object not as expected" )
954 return None
955 except pexpect.EOF:
956 main.log.error( self.name + ": EOF exception found" )
957 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700958 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700959 except Exception:
960 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700961 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700962
Jon Hallc6793552016-01-19 14:18:37 -0800963 def checkBalanceMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700964 """
965 Uses the master command to check that the devices' leadership
966 is evenly divided
967
968 Dependencies: checkMasters() and summary()
969
Jon Hall6509dbf2016-06-21 17:01:17 -0700970 Returns main.TRUE if the devices are balanced
971 Returns main.FALSE if the devices are unbalanced
acsmars24950022015-07-30 18:00:43 -0700972 Exits on Exception
973 Returns None on TypeError
974 """
975 try:
Jon Hallc6793552016-01-19 14:18:37 -0800976 summaryOutput = self.summary()
977 totalDevices = json.loads( summaryOutput )[ "devices" ]
978 except ( TypeError, ValueError ):
979 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summaryOutput ) )
980 return None
981 try:
acsmars24950022015-07-30 18:00:43 -0700982 totalOwnedDevices = 0
Jon Hallc6793552016-01-19 14:18:37 -0800983 mastersOutput = self.checkMasters()
984 masters = json.loads( mastersOutput )
acsmars24950022015-07-30 18:00:43 -0700985 first = masters[ 0 ][ "size" ]
986 for master in masters:
987 totalOwnedDevices += master[ "size" ]
988 if master[ "size" ] > first + 1 or master[ "size" ] < first - 1:
989 main.log.error( "Mastership not balanced" )
990 main.log.info( "\n" + self.checkMasters( False ) )
991 return main.FALSE
Jon Halle0f0b342017-04-18 11:43:47 -0700992 main.log.info( "Mastership balanced between " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700993 str( len( masters ) ) + " masters" )
acsmars24950022015-07-30 18:00:43 -0700994 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800995 except ( TypeError, ValueError ):
996 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, mastersOutput ) )
acsmars24950022015-07-30 18:00:43 -0700997 return None
998 except pexpect.EOF:
999 main.log.error( self.name + ": EOF exception found" )
1000 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001001 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -07001002 except Exception:
1003 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001004 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -07001005
YPZhangfebf7302016-05-24 16:45:56 -07001006 def links( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -08001007 """
Jon Halle8217482014-10-17 13:49:14 -04001008 Lists all core links
1009 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001010 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001011 """
Jon Halle8217482014-10-17 13:49:14 -04001012 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001013 cmdStr = "links"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001014 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001015 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07001016 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001017 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001018 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001019 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001020 except AssertionError:
1021 main.log.exception( "" )
1022 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001023 except TypeError:
1024 main.log.exception( self.name + ": Object not as expected" )
1025 return None
Jon Halle8217482014-10-17 13:49:14 -04001026 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001027 main.log.error( self.name + ": EOF exception found" )
1028 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001029 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001030 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001031 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001032 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001033
You Wang3b9689a2018-08-30 12:24:00 -07001034 def ports( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -08001035 """
Jon Halle8217482014-10-17 13:49:14 -04001036 Lists all ports
1037 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001038 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001039 """
Jon Halle8217482014-10-17 13:49:14 -04001040 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001041 cmdStr = "ports"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001042 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001043 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -07001044 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001045 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001046 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001047 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001048 except AssertionError:
1049 main.log.exception( "" )
1050 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001051 except TypeError:
1052 main.log.exception( self.name + ": Object not as expected" )
1053 return None
Jon Halle8217482014-10-17 13:49:14 -04001054 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001055 main.log.error( self.name + ": EOF exception found" )
1056 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001057 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001058 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001059 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001060 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001061
kelvin-onlabd3b64892015-01-20 13:26:24 -08001062 def roles( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001063 """
Jon Hall983a1702014-10-28 18:44:22 -04001064 Lists all devices and the controllers with roles assigned to them
1065 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001066 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001067 """
andrewonlab7c211572014-10-15 16:45:20 -04001068 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001069 cmdStr = "roles"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001070 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001071 cmdStr += " -j"
1072 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001073 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001074 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001075 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001076 except AssertionError:
1077 main.log.exception( "" )
1078 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001079 except TypeError:
1080 main.log.exception( self.name + ": Object not as expected" )
1081 return None
Jon Hall983a1702014-10-28 18:44:22 -04001082 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001083 main.log.error( self.name + ": EOF exception found" )
1084 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001085 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001086 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001087 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001088 main.cleanAndExit()
Jon Hall983a1702014-10-28 18:44:22 -04001089
kelvin-onlabd3b64892015-01-20 13:26:24 -08001090 def getRole( self, deviceId ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001091 """
Jon Halle3f39ff2015-01-13 11:50:53 -08001092 Given the a string containing the json representation of the "roles"
1093 cli command and a partial or whole device id, returns a json object
1094 containing the roles output for the first device whose id contains
1095 "device_id"
Jon Hall983a1702014-10-28 18:44:22 -04001096
1097 Returns:
Jon Halle3f39ff2015-01-13 11:50:53 -08001098 A dict of the role assignments for the given device or
1099 None if no match
kelvin8ec71442015-01-15 16:57:00 -08001100 """
Jon Hall983a1702014-10-28 18:44:22 -04001101 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001102 if deviceId is None:
Jon Hall983a1702014-10-28 18:44:22 -04001103 return None
1104 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001105 rawRoles = self.roles()
1106 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001107 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001108 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001109 # print device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001110 if str( deviceId ) in device[ 'id' ]:
Jon Hall983a1702014-10-28 18:44:22 -04001111 return device
1112 return None
Jon Hallc6793552016-01-19 14:18:37 -08001113 except ( TypeError, ValueError ):
1114 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001115 return None
andrewonlab86dc3082014-10-13 18:18:38 -04001116 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001117 main.log.error( self.name + ": EOF exception found" )
1118 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001119 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001120 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001121 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001122 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001123
kelvin-onlabd3b64892015-01-20 13:26:24 -08001124 def rolesNotNull( self ):
kelvin8ec71442015-01-15 16:57:00 -08001125 """
Jon Hall94fd0472014-12-08 11:52:42 -08001126 Iterates through each device and checks if there is a master assigned
1127 Returns: main.TRUE if each device has a master
1128 main.FALSE any device has no master
kelvin8ec71442015-01-15 16:57:00 -08001129 """
Jon Hall94fd0472014-12-08 11:52:42 -08001130 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001131 rawRoles = self.roles()
1132 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001133 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001134 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001135 # print device
1136 if device[ 'master' ] == "none":
1137 main.log.warn( "Device has no master: " + str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08001138 return main.FALSE
1139 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08001140 except ( TypeError, ValueError ):
1141 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001142 return None
Jon Hall94fd0472014-12-08 11:52:42 -08001143 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001144 main.log.error( self.name + ": EOF exception found" )
1145 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001146 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001147 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001148 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001149 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001150
kelvin-onlabd3b64892015-01-20 13:26:24 -08001151 def paths( self, srcId, dstId ):
kelvin8ec71442015-01-15 16:57:00 -08001152 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001153 Returns string of paths, and the cost.
1154 Issues command: onos:paths <src> <dst>
kelvin8ec71442015-01-15 16:57:00 -08001155 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001156 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001157 cmdStr = "onos:paths " + str( srcId ) + " " + str( dstId )
1158 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001159 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001160 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08001161 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001162 main.log.error( self.name + ": Error in getting paths" )
kelvin8ec71442015-01-15 16:57:00 -08001163 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001164 else:
kelvin8ec71442015-01-15 16:57:00 -08001165 path = handle.split( ";" )[ 0 ]
1166 cost = handle.split( ";" )[ 1 ]
1167 return ( path, cost )
Jon Hallc6793552016-01-19 14:18:37 -08001168 except AssertionError:
1169 main.log.exception( "" )
1170 return ( handle, "Error" )
Jon Halld4d4b372015-01-28 16:02:41 -08001171 except TypeError:
1172 main.log.exception( self.name + ": Object not as expected" )
1173 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001174 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001175 main.log.error( self.name + ": EOF exception found" )
1176 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001177 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001178 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001179 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001180 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -08001181
kelvin-onlabd3b64892015-01-20 13:26:24 -08001182 def hosts( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001183 """
Jon Hallffb386d2014-11-21 13:43:38 -08001184 Lists all discovered hosts
Jon Hall42db6dc2014-10-24 19:03:48 -04001185 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001186 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001187 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001188 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001189 cmdStr = "hosts"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001190 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001191 cmdStr += " -j"
1192 handle = self.sendline( cmdStr )
Jeremyd9e4eb12016-04-13 12:09:06 -07001193 if handle:
1194 assert "Command not found:" not in handle, handle
Jon Hallbaf53162015-12-17 17:04:34 -08001195 # TODO: Maybe make this less hardcoded
1196 # ConsistentMap Exceptions
1197 assert "org.onosproject.store.service" not in handle
1198 # Node not leader
1199 assert "java.lang.IllegalStateException" not in handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001200 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001201 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07001202 main.log.exception( self.name + ": Error in processing '" + cmdStr + "' " +
Jeremy Songster6949cea2016-04-19 18:13:18 -07001203 "command: " + str( handle ) )
Jon Hallc6793552016-01-19 14:18:37 -08001204 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001205 except TypeError:
1206 main.log.exception( self.name + ": Object not as expected" )
1207 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001208 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001209 main.log.error( self.name + ": EOF exception found" )
1210 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001211 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001212 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001213 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001214 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001215
kelvin-onlabd3b64892015-01-20 13:26:24 -08001216 def getHost( self, mac ):
kelvin8ec71442015-01-15 16:57:00 -08001217 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001218 Return the first host from the hosts api whose 'id' contains 'mac'
Jon Halle3f39ff2015-01-13 11:50:53 -08001219
Jon Hallefbd9792015-03-05 16:11:36 -08001220 Note: mac must be a colon separated mac address, but could be a
Jon Halle3f39ff2015-01-13 11:50:53 -08001221 partial mac address
1222
Jon Hall42db6dc2014-10-24 19:03:48 -04001223 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08001224 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001225 try:
kelvin8ec71442015-01-15 16:57:00 -08001226 if mac is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04001227 return None
1228 else:
1229 mac = mac
kelvin-onlabd3b64892015-01-20 13:26:24 -08001230 rawHosts = self.hosts()
1231 hostsJson = json.loads( rawHosts )
kelvin8ec71442015-01-15 16:57:00 -08001232 # search json for the host with mac then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001233 for host in hostsJson:
kelvin8ec71442015-01-15 16:57:00 -08001234 # print "%s in %s?" % ( mac, host[ 'id' ] )
Jon Halld4d4b372015-01-28 16:02:41 -08001235 if not host:
1236 pass
1237 elif mac in host[ 'id' ]:
Jon Hall42db6dc2014-10-24 19:03:48 -04001238 return host
1239 return None
Jon Hallc6793552016-01-19 14:18:37 -08001240 except ( TypeError, ValueError ):
1241 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawHosts ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001242 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001243 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001244 main.log.error( self.name + ": EOF exception found" )
1245 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001246 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001247 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001248 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001249 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001250
kelvin-onlabd3b64892015-01-20 13:26:24 -08001251 def getHostsId( self, hostList ):
kelvin8ec71442015-01-15 16:57:00 -08001252 """
1253 Obtain list of hosts
andrewonlab3f0a4af2014-10-17 12:25:14 -04001254 Issues command: 'onos> hosts'
kelvin8ec71442015-01-15 16:57:00 -08001255
andrewonlab3f0a4af2014-10-17 12:25:14 -04001256 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001257 * hostList: List of hosts obtained by Mininet
andrewonlab3f0a4af2014-10-17 12:25:14 -04001258 IMPORTANT:
1259 This function assumes that you started your
kelvin8ec71442015-01-15 16:57:00 -08001260 topology with the option '--mac'.
andrewonlab3f0a4af2014-10-17 12:25:14 -04001261 Furthermore, it assumes that value of VLAN is '-1'
1262 Description:
kelvin8ec71442015-01-15 16:57:00 -08001263 Converts mininet hosts ( h1, h2, h3... ) into
1264 ONOS format ( 00:00:00:00:00:01/-1 , ... )
1265 """
andrewonlab3f0a4af2014-10-17 12:25:14 -04001266 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001267 onosHostList = []
andrewonlab3f0a4af2014-10-17 12:25:14 -04001268
kelvin-onlabd3b64892015-01-20 13:26:24 -08001269 for host in hostList:
kelvin8ec71442015-01-15 16:57:00 -08001270 host = host.replace( "h", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001271 hostHex = hex( int( host ) ).zfill( 12 )
1272 hostHex = str( hostHex ).replace( 'x', '0' )
1273 i = iter( str( hostHex ) )
1274 hostHex = ":".join( a + b for a, b in zip( i, i ) )
1275 hostHex = hostHex + "/-1"
1276 onosHostList.append( hostHex )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001277
kelvin-onlabd3b64892015-01-20 13:26:24 -08001278 return onosHostList
andrewonlab3f0a4af2014-10-17 12:25:14 -04001279
Jon Halld4d4b372015-01-28 16:02:41 -08001280 except TypeError:
1281 main.log.exception( self.name + ": Object not as expected" )
1282 return None
andrewonlab3f0a4af2014-10-17 12:25:14 -04001283 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001284 main.log.error( self.name + ": EOF exception found" )
1285 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001286 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001287 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001288 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001289 main.cleanAndExit()
andrewonlab3e15ead2014-10-15 14:21:34 -04001290
You Wangbc898b82018-05-03 16:22:34 -07001291 def verifyHostLocation( self, hostIp, location ):
1292 """
1293 Description:
1294 Verify the host given is discovered in all locations expected
1295 Required:
1296 hostIp: IP address of the host
1297 location: expected location(s) of the given host. ex. "of:0000000000000005/8"
1298 Could be a string or list
1299 Returns:
1300 main.TRUE if host is discovered on all locations provided
1301 main.FALSE otherwise
1302 """
You Wangbc898b82018-05-03 16:22:34 -07001303 locations = [ location ] if isinstance( location, str ) else location
1304 assert isinstance( locations, list ), "Wrong type of location: {}".format( type( location ) )
1305 try:
1306 hosts = self.hosts()
1307 hosts = json.loads( hosts )
1308 targetHost = None
1309 for host in hosts:
1310 if hostIp in host[ "ipAddresses" ]:
1311 targetHost = host
You Wangfd80ab42018-05-10 17:21:53 -07001312 assert targetHost, "Not able to find host with IP {}".format( hostIp )
You Wangbc898b82018-05-03 16:22:34 -07001313 result = main.TRUE
1314 locationsDiscovered = [ loc[ "elementId" ] + "/" + loc[ "port" ] for loc in targetHost[ "locations" ] ]
1315 for loc in locations:
1316 discovered = False
1317 for locDiscovered in locationsDiscovered:
You Wang547893e2018-05-08 13:34:59 -07001318 locToMatch = locDiscovered if "/" in loc else locDiscovered.split( "/" )[0]
1319 if loc == locToMatch:
You Wangbc898b82018-05-03 16:22:34 -07001320 main.log.debug( "Host {} discovered with location {}".format( hostIp, loc ) )
You Wang547893e2018-05-08 13:34:59 -07001321 discovered = True
You Wangbc898b82018-05-03 16:22:34 -07001322 break
1323 if discovered:
1324 locationsDiscovered.remove( locDiscovered )
1325 else:
1326 main.log.warn( "Host {} not discovered with location {}".format( hostIp, loc ) )
1327 result = main.FALSE
1328 if locationsDiscovered:
1329 main.log.warn( "Host {} is also discovered with location {}".format( hostIp, locationsDiscovered ) )
1330 result = main.FALSE
1331 return result
1332 except KeyError:
1333 main.log.exception( self.name + ": host data not as expected: " + hosts )
1334 return None
1335 except pexpect.EOF:
1336 main.log.error( self.name + ": EOF exception found" )
1337 main.log.error( self.name + ": " + self.handle.before )
1338 main.cleanAndExit()
1339 except Exception:
1340 main.log.exception( self.name + ": Uncaught exception" )
1341 return None
1342
You Wang53dba1e2018-02-02 17:45:44 -08001343 def verifyHostIp( self, hostList=[], prefix="" ):
1344 """
1345 Description:
1346 Verify that all hosts have IP address assigned to them
1347 Optional:
1348 hostList: If specified, verifications only happen to the hosts
1349 in hostList
1350 prefix: at least one of the ip address assigned to the host
1351 needs to have the specified prefix
1352 Returns:
1353 main.TRUE if all hosts have specific IP address assigned;
1354 main.FALSE otherwise
1355 """
You Wang53dba1e2018-02-02 17:45:44 -08001356 try:
1357 hosts = self.hosts()
1358 hosts = json.loads( hosts )
1359 if not hostList:
1360 hostList = [ host[ "id" ] for host in hosts ]
1361 for host in hosts:
1362 hostId = host[ "id" ]
1363 if hostId not in hostList:
1364 continue
1365 ipList = host[ "ipAddresses" ]
1366 main.log.debug( self.name + ": IP list on host " + str( hostId ) + ": " + str( ipList ) )
1367 if not ipList:
1368 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostId ) )
1369 else:
1370 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
1371 main.log.warn( self.name + ": None of the IPs on host " + str( hostId ) + " has prefix " + str( prefix ) )
1372 else:
1373 main.log.debug( self.name + ": Found matching IP on host " + str( hostId ) )
1374 hostList.remove( hostId )
1375 if hostList:
1376 main.log.warn( self.name + ": failed to verify IP on following hosts: " + str( hostList) )
Jon Hall43060f62020-06-23 13:13:33 -07001377 # Print info for debugging
1378 main.log.debug( self.name + ": hosts output: " + str( hosts ) )
You Wang53dba1e2018-02-02 17:45:44 -08001379 return main.FALSE
1380 else:
1381 return main.TRUE
1382 except KeyError:
1383 main.log.exception( self.name + ": host data not as expected: " + hosts )
1384 return None
1385 except pexpect.EOF:
1386 main.log.error( self.name + ": EOF exception found" )
1387 main.log.error( self.name + ": " + self.handle.before )
1388 main.cleanAndExit()
1389 except Exception:
1390 main.log.exception( self.name + ": Uncaught exception" )
1391 return None
1392
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001393 def addHostIntent( self, hostIdOne, hostIdTwo, vlanId="", setVlan="", encap="", bandwidth="" ):
kelvin8ec71442015-01-15 16:57:00 -08001394 """
andrewonlabe6745342014-10-17 14:29:13 -04001395 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001396 * hostIdOne: ONOS host id for host1
1397 * hostIdTwo: ONOS host id for host2
Jeremy Songster832f9e92016-05-05 14:30:49 -07001398 Optional:
1399 * vlanId: specify a VLAN id for the intent
Jeremy Songsterff553672016-05-12 17:06:23 -07001400 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001401 * encap: specify an encapsulation type
andrewonlabe6745342014-10-17 14:29:13 -04001402 Description:
Jon Hallefbd9792015-03-05 16:11:36 -08001403 Adds a host-to-host intent ( bidirectional ) by
Jon Hallb1290e82014-11-18 16:17:48 -05001404 specifying the two hosts.
kelvin-onlabfb521662015-02-27 09:52:40 -08001405 Returns:
1406 A string of the intent id or None on Error
kelvin8ec71442015-01-15 16:57:00 -08001407 """
andrewonlabe6745342014-10-17 14:29:13 -04001408 try:
Jeremy Songster832f9e92016-05-05 14:30:49 -07001409 cmdStr = "add-host-intent "
1410 if vlanId:
1411 cmdStr += "-v " + str( vlanId ) + " "
Jeremy Songsterff553672016-05-12 17:06:23 -07001412 if setVlan:
1413 cmdStr += "--setVlan " + str( vlanId ) + " "
Jeremy Songsterc032f162016-08-04 17:14:49 -07001414 if encap:
1415 cmdStr += "--encapsulation " + str( encap ) + " "
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001416 if bandwidth:
1417 cmdStr += "-b " + str( bandwidth ) + " "
Jeremy Songster832f9e92016-05-05 14:30:49 -07001418 cmdStr += str( hostIdOne ) + " " + str( hostIdTwo )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001419 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001420 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001421 assert "Command not found:" not in handle, handle
Hari Krishnaac4e1782015-01-26 12:09:12 -08001422 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001423 main.log.error( self.name + ": Error in adding Host intent" )
Jon Hall61282e32015-03-19 11:34:11 -07001424 main.log.debug( "Response from ONOS was: " + repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001425 return None
Hari Krishnaac4e1782015-01-26 12:09:12 -08001426 else:
1427 main.log.info( "Host intent installed between " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001428 str( hostIdOne ) + " and " + str( hostIdTwo ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001429 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001430 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001431 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001432 else:
1433 main.log.error( "Error, intent ID not found" )
Jon Hall61282e32015-03-19 11:34:11 -07001434 main.log.debug( "Response from ONOS was: " +
1435 repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001436 return None
Jon Hallc6793552016-01-19 14:18:37 -08001437 except AssertionError:
1438 main.log.exception( "" )
1439 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001440 except TypeError:
1441 main.log.exception( self.name + ": Object not as expected" )
1442 return None
andrewonlabe6745342014-10-17 14:29:13 -04001443 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001444 main.log.error( self.name + ": EOF exception found" )
1445 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001446 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001447 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001448 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001449 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04001450
kelvin-onlabd3b64892015-01-20 13:26:24 -08001451 def addOpticalIntent( self, ingressDevice, egressDevice ):
kelvin8ec71442015-01-15 16:57:00 -08001452 """
andrewonlab7b31d232014-10-24 13:31:47 -04001453 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001454 * ingressDevice: device id of ingress device
1455 * egressDevice: device id of egress device
andrewonlab7b31d232014-10-24 13:31:47 -04001456 Optional:
1457 TODO: Still needs to be implemented via dev side
kelvin-onlabfb521662015-02-27 09:52:40 -08001458 Description:
1459 Adds an optical intent by specifying an ingress and egress device
1460 Returns:
1461 A string of the intent id or None on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08001462 """
andrewonlab7b31d232014-10-24 13:31:47 -04001463 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001464 cmdStr = "add-optical-intent " + str( ingressDevice ) +\
1465 " " + str( egressDevice )
1466 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001467 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001468 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08001469 # If error, return error message
Jon Halle3f39ff2015-01-13 11:50:53 -08001470 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001471 main.log.error( self.name + ": Error in adding Optical intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001472 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001473 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001474 main.log.info( "Optical intent installed between " +
1475 str( ingressDevice ) + " and " +
1476 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001477 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001478 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001479 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001480 else:
1481 main.log.error( "Error, intent ID not found" )
1482 return None
Jon Hallc6793552016-01-19 14:18:37 -08001483 except AssertionError:
1484 main.log.exception( "" )
1485 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001486 except TypeError:
1487 main.log.exception( self.name + ": Object not as expected" )
1488 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001489 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001490 main.log.error( self.name + ": EOF exception found" )
1491 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001492 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001493 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001494 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001495 main.cleanAndExit()
andrewonlab7b31d232014-10-24 13:31:47 -04001496
kelvin-onlabd3b64892015-01-20 13:26:24 -08001497 def addPointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001498 self,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001499 ingressDevice,
1500 egressDevice,
1501 portIngress="",
1502 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001503 ethType="",
1504 ethSrc="",
1505 ethDst="",
1506 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001507 lambdaAlloc=False,
alisonda157272016-12-22 01:13:21 -08001508 protected=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001509 ipProto="",
1510 ipSrc="",
1511 ipDst="",
1512 tcpSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001513 tcpDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001514 vlanId="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001515 setVlan="",
1516 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001517 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001518 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001519 * ingressDevice: device id of ingress device
1520 * egressDevice: device id of egress device
andrewonlab289e4b72014-10-21 21:24:18 -04001521 Optional:
1522 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001523 * ethSrc: specify ethSrc ( i.e. src mac addr )
1524 * ethDst: specify ethDst ( i.e. dst mac addr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001525 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001526 * lambdaAlloc: if True, intent will allocate lambda
andrewonlab40ccd8b2014-11-06 16:23:34 -05001527 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001528 * ipProto: specify ip protocol
andrewonlabf77e0cb2014-11-11 17:17:59 -05001529 * ipSrc: specify ip source address
1530 * ipDst: specify ip destination address
1531 * tcpSrc: specify tcp source port
1532 * tcpDst: specify tcp destination port
Jeremy Songster832f9e92016-05-05 14:30:49 -07001533 * vlanId: specify vlan ID
Jeremy Songsterff553672016-05-12 17:06:23 -07001534 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001535 * encap: specify an Encapsulation type to use
andrewonlab4dbb4d82014-10-17 18:22:31 -04001536 Description:
kelvin8ec71442015-01-15 16:57:00 -08001537 Adds a point-to-point intent ( uni-directional ) by
andrewonlab289e4b72014-10-21 21:24:18 -04001538 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001539 Returns:
1540 A string of the intent id or None on error
andrewonlab289e4b72014-10-21 21:24:18 -04001541
Jon Halle3f39ff2015-01-13 11:50:53 -08001542 NOTE: This function may change depending on the
andrewonlab4dbb4d82014-10-17 18:22:31 -04001543 options developers provide for point-to-point
1544 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001545 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001546 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001547 cmd = "add-point-intent"
andrewonlab36af3822014-11-18 17:48:18 -05001548
Jeremy Songsterff553672016-05-12 17:06:23 -07001549 if ethType:
1550 cmd += " --ethType " + str( ethType )
1551 if ethSrc:
1552 cmd += " --ethSrc " + str( ethSrc )
1553 if ethDst:
1554 cmd += " --ethDst " + str( ethDst )
1555 if bandwidth:
1556 cmd += " --bandwidth " + str( bandwidth )
1557 if lambdaAlloc:
1558 cmd += " --lambda "
1559 if ipProto:
1560 cmd += " --ipProto " + str( ipProto )
1561 if ipSrc:
1562 cmd += " --ipSrc " + str( ipSrc )
1563 if ipDst:
1564 cmd += " --ipDst " + str( ipDst )
1565 if tcpSrc:
1566 cmd += " --tcpSrc " + str( tcpSrc )
1567 if tcpDst:
1568 cmd += " --tcpDst " + str( tcpDst )
1569 if vlanId:
1570 cmd += " -v " + str( vlanId )
1571 if setVlan:
1572 cmd += " --setVlan " + str( setVlan )
Jeremy Songsterc032f162016-08-04 17:14:49 -07001573 if encap:
1574 cmd += " --encapsulation " + str( encap )
alisonda157272016-12-22 01:13:21 -08001575 if protected:
1576 cmd += " --protect "
andrewonlab289e4b72014-10-21 21:24:18 -04001577
kelvin8ec71442015-01-15 16:57:00 -08001578 # Check whether the user appended the port
1579 # or provided it as an input
kelvin-onlabd3b64892015-01-20 13:26:24 -08001580 if "/" in ingressDevice:
1581 cmd += " " + str( ingressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001582 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001583 if not portIngress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001584 main.log.error( "You must specify the ingress port" )
kelvin8ec71442015-01-15 16:57:00 -08001585 # TODO: perhaps more meaningful return
kelvin-onlabfb521662015-02-27 09:52:40 -08001586 # Would it make sense to throw an exception and exit
1587 # the test?
1588 return None
andrewonlab36af3822014-11-18 17:48:18 -05001589
kelvin8ec71442015-01-15 16:57:00 -08001590 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001591 str( ingressDevice ) + "/" +\
1592 str( portIngress ) + " "
andrewonlab36af3822014-11-18 17:48:18 -05001593
kelvin-onlabd3b64892015-01-20 13:26:24 -08001594 if "/" in egressDevice:
1595 cmd += " " + str( egressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001596 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001597 if not portEgress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001598 main.log.error( "You must specify the egress port" )
1599 return None
Jon Halle3f39ff2015-01-13 11:50:53 -08001600
kelvin8ec71442015-01-15 16:57:00 -08001601 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001602 str( egressDevice ) + "/" +\
1603 str( portEgress )
kelvin8ec71442015-01-15 16:57:00 -08001604
kelvin-onlab898a6c62015-01-16 14:13:53 -08001605 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001606 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001607 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001608 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001609 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001610 main.log.error( self.name + ": Error in adding point-to-point intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001611 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001612 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001613 # TODO: print out all the options in this message?
1614 main.log.info( "Point-to-point intent installed between " +
1615 str( ingressDevice ) + " and " +
1616 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001617 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001618 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001619 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001620 else:
1621 main.log.error( "Error, intent ID not found" )
1622 return None
Jon Hallc6793552016-01-19 14:18:37 -08001623 except AssertionError:
1624 main.log.exception( "" )
1625 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001626 except TypeError:
1627 main.log.exception( self.name + ": Object not as expected" )
1628 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001629 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001630 main.log.error( self.name + ": EOF exception found" )
1631 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001632 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001633 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001634 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001635 main.cleanAndExit()
andrewonlab4dbb4d82014-10-17 18:22:31 -04001636
kelvin-onlabd3b64892015-01-20 13:26:24 -08001637 def addMultipointToSinglepointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001638 self,
shahshreyac2f97072015-03-19 17:04:29 -07001639 ingressDeviceList,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001640 egressDevice,
shahshreyac2f97072015-03-19 17:04:29 -07001641 portIngressList=None,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001642 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001643 ethType="",
1644 ethSrc="",
1645 ethDst="",
1646 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001647 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001648 ipProto="",
1649 ipSrc="",
1650 ipDst="",
1651 tcpSrc="",
1652 tcpDst="",
1653 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001654 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001655 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001656 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001657 partial=False,
1658 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001659 """
shahshreyad0c80432014-12-04 16:56:05 -08001660 Note:
shahshreya70622b12015-03-19 17:19:00 -07001661 This function assumes the format of all ingress devices
Jon Hallbe379602015-03-24 13:39:32 -07001662 is same. That is, all ingress devices include port numbers
1663 with a "/" or all ingress devices could specify device
1664 ids and port numbers seperately.
shahshreyad0c80432014-12-04 16:56:05 -08001665 Required:
Jon Hallbe379602015-03-24 13:39:32 -07001666 * ingressDeviceList: List of device ids of ingress device
shahshreyac2f97072015-03-19 17:04:29 -07001667 ( Atleast 2 ingress devices required in the list )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001668 * egressDevice: device id of egress device
shahshreyad0c80432014-12-04 16:56:05 -08001669 Optional:
1670 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001671 * ethSrc: specify ethSrc ( i.e. src mac addr )
1672 * ethDst: specify ethDst ( i.e. dst mac addr )
shahshreyad0c80432014-12-04 16:56:05 -08001673 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001674 * lambdaAlloc: if True, intent will allocate lambda
shahshreyad0c80432014-12-04 16:56:05 -08001675 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001676 * ipProto: specify ip protocol
shahshreyad0c80432014-12-04 16:56:05 -08001677 * ipSrc: specify ip source address
1678 * ipDst: specify ip destination address
1679 * tcpSrc: specify tcp source port
1680 * tcpDst: specify tcp destination port
1681 * setEthSrc: action to Rewrite Source MAC Address
1682 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001683 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001684 * setVlan: specify VLAN Id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001685 * encap: specify a type of encapsulation
shahshreyad0c80432014-12-04 16:56:05 -08001686 Description:
kelvin8ec71442015-01-15 16:57:00 -08001687 Adds a multipoint-to-singlepoint intent ( uni-directional ) by
shahshreyad0c80432014-12-04 16:56:05 -08001688 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001689 Returns:
1690 A string of the intent id or None on error
shahshreyad0c80432014-12-04 16:56:05 -08001691
Jon Halle3f39ff2015-01-13 11:50:53 -08001692 NOTE: This function may change depending on the
Jon Hallefbd9792015-03-05 16:11:36 -08001693 options developers provide for multipoint-to-singlepoint
shahshreyad0c80432014-12-04 16:56:05 -08001694 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001695 """
shahshreyad0c80432014-12-04 16:56:05 -08001696 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001697 cmd = "add-multi-to-single-intent"
shahshreyad0c80432014-12-04 16:56:05 -08001698
Jeremy Songsterff553672016-05-12 17:06:23 -07001699 if ethType:
1700 cmd += " --ethType " + str( ethType )
1701 if ethSrc:
1702 cmd += " --ethSrc " + str( ethSrc )
1703 if ethDst:
1704 cmd += " --ethDst " + str( ethDst )
1705 if bandwidth:
1706 cmd += " --bandwidth " + str( bandwidth )
1707 if lambdaAlloc:
1708 cmd += " --lambda "
1709 if ipProto:
1710 cmd += " --ipProto " + str( ipProto )
1711 if ipSrc:
1712 cmd += " --ipSrc " + str( ipSrc )
1713 if ipDst:
1714 cmd += " --ipDst " + str( ipDst )
1715 if tcpSrc:
1716 cmd += " --tcpSrc " + str( tcpSrc )
1717 if tcpDst:
1718 cmd += " --tcpDst " + str( tcpDst )
1719 if setEthSrc:
1720 cmd += " --setEthSrc " + str( setEthSrc )
1721 if setEthDst:
1722 cmd += " --setEthDst " + str( setEthDst )
1723 if vlanId:
1724 cmd += " -v " + str( vlanId )
1725 if setVlan:
1726 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001727 if partial:
1728 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001729 if encap:
1730 cmd += " --encapsulation " + str( encap )
shahshreyad0c80432014-12-04 16:56:05 -08001731
kelvin8ec71442015-01-15 16:57:00 -08001732 # Check whether the user appended the port
1733 # or provided it as an input
shahshreyac2f97072015-03-19 17:04:29 -07001734
1735 if portIngressList is None:
1736 for ingressDevice in ingressDeviceList:
1737 if "/" in ingressDevice:
1738 cmd += " " + str( ingressDevice )
1739 else:
1740 main.log.error( "You must specify " +
Jon Hallbe379602015-03-24 13:39:32 -07001741 "the ingress port" )
shahshreyac2f97072015-03-19 17:04:29 -07001742 # TODO: perhaps more meaningful return
1743 return main.FALSE
shahshreyad0c80432014-12-04 16:56:05 -08001744 else:
Jon Hall71ce4e72015-03-23 14:05:58 -07001745 if len( ingressDeviceList ) == len( portIngressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001746 for ingressDevice, portIngress in zip( ingressDeviceList,
1747 portIngressList ):
shahshreya70622b12015-03-19 17:19:00 -07001748 cmd += " " + \
1749 str( ingressDevice ) + "/" +\
1750 str( portIngress ) + " "
kelvin-onlab38143812015-04-01 15:03:01 -07001751 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001752 main.log.error( "Device list and port list does not " +
1753 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001754 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001755 if "/" in egressDevice:
1756 cmd += " " + str( egressDevice )
shahshreyad0c80432014-12-04 16:56:05 -08001757 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001758 if not portEgress:
kelvin8ec71442015-01-15 16:57:00 -08001759 main.log.error( "You must specify " +
1760 "the egress port" )
shahshreyad0c80432014-12-04 16:56:05 -08001761 return main.FALSE
Jon Halle3f39ff2015-01-13 11:50:53 -08001762
kelvin8ec71442015-01-15 16:57:00 -08001763 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001764 str( egressDevice ) + "/" +\
1765 str( portEgress )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001766 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001767 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001768 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001769 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001770 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001771 main.log.error( self.name + ": Error in adding multipoint-to-singlepoint " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001772 "intent" )
1773 return None
shahshreyad0c80432014-12-04 16:56:05 -08001774 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001775 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001776 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001777 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001778 else:
1779 main.log.error( "Error, intent ID not found" )
1780 return None
Jon Hallc6793552016-01-19 14:18:37 -08001781 except AssertionError:
1782 main.log.exception( "" )
1783 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001784 except TypeError:
1785 main.log.exception( self.name + ": Object not as expected" )
1786 return None
1787 except pexpect.EOF:
1788 main.log.error( self.name + ": EOF exception found" )
1789 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001790 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001791 except Exception:
1792 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001793 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001794
1795 def addSinglepointToMultipointIntent(
1796 self,
1797 ingressDevice,
1798 egressDeviceList,
1799 portIngress="",
1800 portEgressList=None,
1801 ethType="",
1802 ethSrc="",
1803 ethDst="",
1804 bandwidth="",
1805 lambdaAlloc=False,
1806 ipProto="",
1807 ipSrc="",
1808 ipDst="",
1809 tcpSrc="",
1810 tcpDst="",
1811 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001812 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001813 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001814 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001815 partial=False,
1816 encap="" ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001817 """
1818 Note:
1819 This function assumes the format of all egress devices
1820 is same. That is, all egress devices include port numbers
1821 with a "/" or all egress devices could specify device
1822 ids and port numbers seperately.
1823 Required:
1824 * EgressDeviceList: List of device ids of egress device
1825 ( Atleast 2 eress devices required in the list )
1826 * ingressDevice: device id of ingress device
1827 Optional:
1828 * ethType: specify ethType
1829 * ethSrc: specify ethSrc ( i.e. src mac addr )
1830 * ethDst: specify ethDst ( i.e. dst mac addr )
1831 * bandwidth: specify bandwidth capacity of link
1832 * lambdaAlloc: if True, intent will allocate lambda
1833 for the specified intent
1834 * ipProto: specify ip protocol
1835 * ipSrc: specify ip source address
1836 * ipDst: specify ip destination address
1837 * tcpSrc: specify tcp source port
1838 * tcpDst: specify tcp destination port
1839 * setEthSrc: action to Rewrite Source MAC Address
1840 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001841 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001842 * setVlan: specify VLAN ID treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001843 * encap: specify an encapsulation type
kelvin-onlabb9408212015-04-01 13:34:04 -07001844 Description:
1845 Adds a singlepoint-to-multipoint intent ( uni-directional ) by
1846 specifying device id's and optional fields
1847 Returns:
1848 A string of the intent id or None on error
1849
1850 NOTE: This function may change depending on the
1851 options developers provide for singlepoint-to-multipoint
1852 intent via cli
1853 """
1854 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001855 cmd = "add-single-to-multi-intent"
kelvin-onlabb9408212015-04-01 13:34:04 -07001856
Jeremy Songsterff553672016-05-12 17:06:23 -07001857 if ethType:
1858 cmd += " --ethType " + str( ethType )
1859 if ethSrc:
1860 cmd += " --ethSrc " + str( ethSrc )
1861 if ethDst:
1862 cmd += " --ethDst " + str( ethDst )
1863 if bandwidth:
1864 cmd += " --bandwidth " + str( bandwidth )
1865 if lambdaAlloc:
1866 cmd += " --lambda "
1867 if ipProto:
1868 cmd += " --ipProto " + str( ipProto )
1869 if ipSrc:
1870 cmd += " --ipSrc " + str( ipSrc )
1871 if ipDst:
1872 cmd += " --ipDst " + str( ipDst )
1873 if tcpSrc:
1874 cmd += " --tcpSrc " + str( tcpSrc )
1875 if tcpDst:
1876 cmd += " --tcpDst " + str( tcpDst )
1877 if setEthSrc:
1878 cmd += " --setEthSrc " + str( setEthSrc )
1879 if setEthDst:
1880 cmd += " --setEthDst " + str( setEthDst )
1881 if vlanId:
1882 cmd += " -v " + str( vlanId )
1883 if setVlan:
1884 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001885 if partial:
1886 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001887 if encap:
1888 cmd += " --encapsulation " + str( encap )
kelvin-onlabb9408212015-04-01 13:34:04 -07001889
1890 # Check whether the user appended the port
1891 # or provided it as an input
Jon Hall08f61bc2015-04-13 16:00:30 -07001892
kelvin-onlabb9408212015-04-01 13:34:04 -07001893 if "/" in ingressDevice:
1894 cmd += " " + str( ingressDevice )
1895 else:
1896 if not portIngress:
1897 main.log.error( "You must specify " +
1898 "the Ingress port" )
1899 return main.FALSE
1900
1901 cmd += " " +\
1902 str( ingressDevice ) + "/" +\
1903 str( portIngress )
1904
1905 if portEgressList is None:
1906 for egressDevice in egressDeviceList:
1907 if "/" in egressDevice:
1908 cmd += " " + str( egressDevice )
1909 else:
1910 main.log.error( "You must specify " +
1911 "the egress port" )
1912 # TODO: perhaps more meaningful return
1913 return main.FALSE
1914 else:
1915 if len( egressDeviceList ) == len( portEgressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001916 for egressDevice, portEgress in zip( egressDeviceList,
1917 portEgressList ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001918 cmd += " " + \
1919 str( egressDevice ) + "/" +\
1920 str( portEgress )
kelvin-onlab38143812015-04-01 15:03:01 -07001921 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001922 main.log.error( "Device list and port list does not " +
1923 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001924 return main.FALSE
kelvin-onlabb9408212015-04-01 13:34:04 -07001925 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001926 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001927 assert "Command not found:" not in handle, handle
kelvin-onlabb9408212015-04-01 13:34:04 -07001928 # If error, return error message
1929 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001930 main.log.error( self.name + ": Error in adding singlepoint-to-multipoint " +
kelvin-onlabb9408212015-04-01 13:34:04 -07001931 "intent" )
shahshreyac2f97072015-03-19 17:04:29 -07001932 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001933 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001934 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001935 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001936 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001937 else:
1938 main.log.error( "Error, intent ID not found" )
1939 return None
Jon Hallc6793552016-01-19 14:18:37 -08001940 except AssertionError:
1941 main.log.exception( "" )
1942 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001943 except TypeError:
1944 main.log.exception( self.name + ": Object not as expected" )
1945 return None
shahshreyad0c80432014-12-04 16:56:05 -08001946 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001947 main.log.error( self.name + ": EOF exception found" )
1948 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001949 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001950 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001951 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001952 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001953
Hari Krishna9e232602015-04-13 17:29:08 -07001954 def addMplsIntent(
1955 self,
1956 ingressDevice,
1957 egressDevice,
Hari Krishna87a17f12015-04-13 17:42:23 -07001958 ingressPort="",
1959 egressPort="",
Hari Krishna9e232602015-04-13 17:29:08 -07001960 ethType="",
1961 ethSrc="",
1962 ethDst="",
1963 bandwidth="",
1964 lambdaAlloc=False,
1965 ipProto="",
1966 ipSrc="",
1967 ipDst="",
1968 tcpSrc="",
1969 tcpDst="",
Hari Krishna87a17f12015-04-13 17:42:23 -07001970 ingressLabel="",
Hari Krishnadfff6672015-04-13 17:53:27 -07001971 egressLabel="",
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001972 priority="" ):
Hari Krishna9e232602015-04-13 17:29:08 -07001973 """
1974 Required:
1975 * ingressDevice: device id of ingress device
1976 * egressDevice: device id of egress device
1977 Optional:
1978 * ethType: specify ethType
1979 * ethSrc: specify ethSrc ( i.e. src mac addr )
1980 * ethDst: specify ethDst ( i.e. dst mac addr )
1981 * bandwidth: specify bandwidth capacity of link
1982 * lambdaAlloc: if True, intent will allocate lambda
1983 for the specified intent
1984 * ipProto: specify ip protocol
1985 * ipSrc: specify ip source address
1986 * ipDst: specify ip destination address
1987 * tcpSrc: specify tcp source port
1988 * tcpDst: specify tcp destination port
1989 * ingressLabel: Ingress MPLS label
1990 * egressLabel: Egress MPLS label
1991 Description:
1992 Adds MPLS intent by
1993 specifying device id's and optional fields
1994 Returns:
1995 A string of the intent id or None on error
1996
1997 NOTE: This function may change depending on the
1998 options developers provide for MPLS
1999 intent via cli
2000 """
2001 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07002002 cmd = "add-mpls-intent"
Hari Krishna9e232602015-04-13 17:29:08 -07002003
Jeremy Songsterff553672016-05-12 17:06:23 -07002004 if ethType:
2005 cmd += " --ethType " + str( ethType )
2006 if ethSrc:
2007 cmd += " --ethSrc " + str( ethSrc )
2008 if ethDst:
2009 cmd += " --ethDst " + str( ethDst )
2010 if bandwidth:
2011 cmd += " --bandwidth " + str( bandwidth )
2012 if lambdaAlloc:
2013 cmd += " --lambda "
2014 if ipProto:
2015 cmd += " --ipProto " + str( ipProto )
2016 if ipSrc:
2017 cmd += " --ipSrc " + str( ipSrc )
2018 if ipDst:
2019 cmd += " --ipDst " + str( ipDst )
2020 if tcpSrc:
2021 cmd += " --tcpSrc " + str( tcpSrc )
2022 if tcpDst:
2023 cmd += " --tcpDst " + str( tcpDst )
2024 if ingressLabel:
2025 cmd += " --ingressLabel " + str( ingressLabel )
2026 if egressLabel:
2027 cmd += " --egressLabel " + str( egressLabel )
2028 if priority:
2029 cmd += " --priority " + str( priority )
Hari Krishna9e232602015-04-13 17:29:08 -07002030
2031 # Check whether the user appended the port
2032 # or provided it as an input
2033 if "/" in ingressDevice:
2034 cmd += " " + str( ingressDevice )
2035 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002036 if not ingressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002037 main.log.error( "You must specify the ingress port" )
2038 return None
2039
2040 cmd += " " + \
2041 str( ingressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002042 str( ingressPort ) + " "
Hari Krishna9e232602015-04-13 17:29:08 -07002043
2044 if "/" in egressDevice:
2045 cmd += " " + str( egressDevice )
2046 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002047 if not egressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002048 main.log.error( "You must specify the egress port" )
2049 return None
2050
2051 cmd += " " +\
2052 str( egressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002053 str( egressPort )
Hari Krishna9e232602015-04-13 17:29:08 -07002054
2055 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08002056 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002057 assert "Command not found:" not in handle, handle
Hari Krishna9e232602015-04-13 17:29:08 -07002058 # If error, return error message
2059 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002060 main.log.error( self.name + ": Error in adding mpls intent" )
Hari Krishna9e232602015-04-13 17:29:08 -07002061 return None
2062 else:
2063 # TODO: print out all the options in this message?
2064 main.log.info( "MPLS intent installed between " +
2065 str( ingressDevice ) + " and " +
2066 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002067 match = re.search( 'id=0x([\da-f]+),', handle )
Hari Krishna9e232602015-04-13 17:29:08 -07002068 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002069 return match.group()[ 3:-1 ]
Hari Krishna9e232602015-04-13 17:29:08 -07002070 else:
2071 main.log.error( "Error, intent ID not found" )
2072 return None
Jon Hallc6793552016-01-19 14:18:37 -08002073 except AssertionError:
2074 main.log.exception( "" )
2075 return None
Hari Krishna9e232602015-04-13 17:29:08 -07002076 except TypeError:
2077 main.log.exception( self.name + ": Object not as expected" )
2078 return None
2079 except pexpect.EOF:
2080 main.log.error( self.name + ": EOF exception found" )
2081 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002082 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002083 except Exception:
2084 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002085 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002086
Jon Hallefbd9792015-03-05 16:11:36 -08002087 def removeIntent( self, intentId, app='org.onosproject.cli',
2088 purge=False, sync=False ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002089 """
shahshreya1c818fc2015-02-26 13:44:08 -08002090 Remove intent for specified application id and intent id
Jon Hall61282e32015-03-19 11:34:11 -07002091 Optional args:-
shahshreya1c818fc2015-02-26 13:44:08 -08002092 -s or --sync: Waits for the removal before returning
Jon Hall61282e32015-03-19 11:34:11 -07002093 -p or --purge: Purge the intent from the store after removal
2094
Jon Halle3f39ff2015-01-13 11:50:53 -08002095 Returns:
Jon Hall6509dbf2016-06-21 17:01:17 -07002096 main.FALSE on error and
Jon Halle3f39ff2015-01-13 11:50:53 -08002097 cli output otherwise
kelvin-onlab898a6c62015-01-16 14:13:53 -08002098 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002099 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002100 cmdStr = "remove-intent"
shahshreya1c818fc2015-02-26 13:44:08 -08002101 if purge:
2102 cmdStr += " -p"
2103 if sync:
2104 cmdStr += " -s"
2105
2106 cmdStr += " " + app + " " + str( intentId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002107 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002108 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002109 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08002110 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002111 main.log.error( self.name + ": Error in removing intent" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002112 return main.FALSE
andrewonlab9a50dfe2014-10-17 17:22:31 -04002113 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002114 # TODO: Should this be main.TRUE
2115 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002116 except AssertionError:
2117 main.log.exception( "" )
2118 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002119 except TypeError:
2120 main.log.exception( self.name + ": Object not as expected" )
2121 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002122 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002123 main.log.error( self.name + ": EOF exception found" )
2124 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002125 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002126 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002127 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002128 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04002129
YPZhangfebf7302016-05-24 16:45:56 -07002130 def removeAllIntents( self, purge=False, sync=False, app='org.onosproject.cli', timeout=30 ):
Jeremy42df2e72016-02-23 16:37:46 -08002131 """
2132 Description:
2133 Remove all the intents
2134 Optional args:-
2135 -s or --sync: Waits for the removal before returning
2136 -p or --purge: Purge the intent from the store after removal
2137 Returns:
2138 Returns main.TRUE if all intents are removed, otherwise returns
2139 main.FALSE; Returns None for exception
2140 """
2141 try:
2142 cmdStr = "remove-intent"
2143 if purge:
2144 cmdStr += " -p"
2145 if sync:
2146 cmdStr += " -s"
2147
2148 cmdStr += " " + app
YPZhangfebf7302016-05-24 16:45:56 -07002149 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08002150 assert handle is not None, "Error in sendline"
Jeremy42df2e72016-02-23 16:37:46 -08002151 assert "Command not found:" not in handle, handle
2152 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002153 main.log.error( self.name + ": Error in removing intent" )
Jeremy42df2e72016-02-23 16:37:46 -08002154 return main.FALSE
2155 else:
2156 return main.TRUE
2157 except AssertionError:
2158 main.log.exception( "" )
2159 return None
2160 except TypeError:
2161 main.log.exception( self.name + ": Object not as expected" )
2162 return None
2163 except pexpect.EOF:
2164 main.log.error( self.name + ": EOF exception found" )
2165 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002166 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002167 except Exception:
2168 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002169 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002170
Hari Krishnaacabd5a2015-07-01 17:10:19 -07002171 def purgeWithdrawnIntents( self ):
Hari Krishna0ce0e152015-06-23 09:55:29 -07002172 """
2173 Purges all WITHDRAWN Intents
2174 """
2175 try:
2176 cmdStr = "purge-intents"
2177 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002178 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002179 assert "Command not found:" not in handle, handle
Hari Krishna0ce0e152015-06-23 09:55:29 -07002180 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002181 main.log.error( self.name + ": Error in purging intents" )
Hari Krishna0ce0e152015-06-23 09:55:29 -07002182 return main.FALSE
2183 else:
2184 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002185 except AssertionError:
2186 main.log.exception( "" )
2187 return None
Hari Krishna0ce0e152015-06-23 09:55:29 -07002188 except TypeError:
2189 main.log.exception( self.name + ": Object not as expected" )
2190 return None
2191 except pexpect.EOF:
2192 main.log.error( self.name + ": EOF exception found" )
2193 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002194 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002195 except Exception:
2196 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002197 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002198
Devin Lime6fe3c42017-10-18 16:28:40 -07002199 def wipeout( self ):
2200 """
2201 Wipe out the flows,intents,links,devices,hosts, and groups from the ONOS.
2202 """
2203 try:
2204 cmdStr = "wipe-out please"
2205 handle = self.sendline( cmdStr, timeout=60 )
2206 assert handle is not None, "Error in sendline"
2207 assert "Command not found:" not in handle, handle
2208 return main.TRUE
2209 except AssertionError:
2210 main.log.exception( "" )
2211 return None
2212 except TypeError:
2213 main.log.exception( self.name + ": Object not as expected" )
2214 return None
2215 except pexpect.EOF:
2216 main.log.error( self.name + ": EOF exception found" )
2217 main.log.error( self.name + ": " + self.handle.before )
2218 main.cleanAndExit()
2219 except Exception:
2220 main.log.exception( self.name + ": Uncaught exception!" )
2221 main.cleanAndExit()
2222
kelvin-onlabd3b64892015-01-20 13:26:24 -08002223 def routes( self, jsonFormat=False ):
kelvin8ec71442015-01-15 16:57:00 -08002224 """
kelvin-onlab898a6c62015-01-16 14:13:53 -08002225 NOTE: This method should be used after installing application:
2226 onos-app-sdnip
pingping-lin8b306ac2014-11-17 18:13:51 -08002227 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002228 * jsonFormat: enable output formatting in json
pingping-lin8b306ac2014-11-17 18:13:51 -08002229 Description:
2230 Obtain all routes in the system
kelvin8ec71442015-01-15 16:57:00 -08002231 """
pingping-lin8b306ac2014-11-17 18:13:51 -08002232 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002233 cmdStr = "routes"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002234 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002235 cmdStr += " -j"
2236 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002237 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002238 assert "Command not found:" not in handle, handle
pingping-lin8b306ac2014-11-17 18:13:51 -08002239 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002240 except AssertionError:
2241 main.log.exception( "" )
2242 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002243 except TypeError:
2244 main.log.exception( self.name + ": Object not as expected" )
2245 return None
pingping-lin8b306ac2014-11-17 18:13:51 -08002246 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002247 main.log.error( self.name + ": EOF exception found" )
2248 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002249 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002250 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002251 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002252 main.cleanAndExit()
pingping-lin8b306ac2014-11-17 18:13:51 -08002253
pingping-lin54b03372015-08-13 14:43:10 -07002254 def ipv4RouteNumber( self ):
2255 """
2256 NOTE: This method should be used after installing application:
2257 onos-app-sdnip
2258 Description:
2259 Obtain the total IPv4 routes number in the system
2260 """
2261 try:
Pratik Parab57963572017-05-09 11:37:54 -07002262 cmdStr = "routes -j"
pingping-lin54b03372015-08-13 14:43:10 -07002263 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002264 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002265 assert "Command not found:" not in handle, handle
pingping-lin54b03372015-08-13 14:43:10 -07002266 jsonResult = json.loads( handle )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002267 return len( jsonResult[ 'routes4' ] )
Jon Hallc6793552016-01-19 14:18:37 -08002268 except AssertionError:
2269 main.log.exception( "" )
2270 return None
2271 except ( TypeError, ValueError ):
2272 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002273 return None
2274 except pexpect.EOF:
2275 main.log.error( self.name + ": EOF exception found" )
2276 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002277 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002278 except Exception:
2279 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002280 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002281
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002282 # =============Function to check Bandwidth allocation========
Jon Hall0e240372018-05-02 11:21:57 -07002283 def allocations( self, jsonFormat = True ):
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002284 """
2285 Description:
2286 Obtain Bandwidth Allocation Information from ONOS cli.
2287 """
2288 try:
2289 cmdStr = "allocations"
2290 if jsonFormat:
2291 cmdStr += " -j"
Jon Hall0e240372018-05-02 11:21:57 -07002292 handle = self.sendline( cmdStr, timeout=300 )
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002293 assert handle is not None, "Error in sendline"
2294 assert "Command not found:" not in handle, handle
2295 return handle
2296 except AssertionError:
2297 main.log.exception( "" )
2298 return None
2299 except ( TypeError, ValueError ):
2300 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
2301 return None
2302 except pexpect.EOF:
2303 main.log.error( self.name + ": EOF exception found" )
2304 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002305 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002306 except Exception:
2307 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002308 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002309
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002310 def intents( self, jsonFormat = True, summary = False, **intentargs ):
kelvin8ec71442015-01-15 16:57:00 -08002311 """
andrewonlabe6745342014-10-17 14:29:13 -04002312 Description:
Jon Hallff566d52016-01-15 14:45:36 -08002313 Obtain intents from the ONOS cli.
2314 Optional:
2315 * jsonFormat: Enable output formatting in json, default to True
2316 * summary: Whether only output the intent summary, defaults to False
2317 * type: Only output a certain type of intent. This options is valid
2318 only when jsonFormat is True and summary is True.
kelvin-onlab898a6c62015-01-16 14:13:53 -08002319 """
andrewonlabe6745342014-10-17 14:29:13 -04002320 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002321 cmdStr = "intents"
pingping-lin8244a3b2015-09-16 13:36:56 -07002322 if summary:
2323 cmdStr += " -s"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002324 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002325 cmdStr += " -j"
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002326 handle = self.sendline( cmdStr, timeout=300 )
You Wangb5a55f72017-03-03 12:51:05 -08002327 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002328 assert "Command not found:" not in handle, handle
pingping-lin8244a3b2015-09-16 13:36:56 -07002329 args = utilities.parse_args( [ "TYPE" ], **intentargs )
acsmars5b5fbaf2015-09-18 10:38:20 -07002330 if "TYPE" in args.keys():
Jon Hallff566d52016-01-15 14:45:36 -08002331 intentType = args[ "TYPE" ]
acsmars5b5fbaf2015-09-18 10:38:20 -07002332 else:
Jon Hallff566d52016-01-15 14:45:36 -08002333 intentType = ""
2334 # IF we want the summary of a specific intent type
2335 if jsonFormat and summary and ( intentType != "" ):
pingping-lin8244a3b2015-09-16 13:36:56 -07002336 jsonResult = json.loads( handle )
Jon Hallff566d52016-01-15 14:45:36 -08002337 if intentType in jsonResult.keys():
2338 return jsonResult[ intentType ]
pingping-lin8244a3b2015-09-16 13:36:56 -07002339 else:
Jon Hallff566d52016-01-15 14:45:36 -08002340 main.log.error( "unknown TYPE, returning all types of intents" )
pingping-lin8244a3b2015-09-16 13:36:56 -07002341 return handle
2342 else:
2343 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002344 except AssertionError:
2345 main.log.exception( "" )
2346 return None
2347 except ( TypeError, ValueError ):
2348 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002349 return None
2350 except pexpect.EOF:
2351 main.log.error( self.name + ": EOF exception found" )
2352 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002353 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002354 except Exception:
2355 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002356 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002357
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002358 def getIntentState( self, intentsId, intentsJson=None ):
kelvin-onlab54400a92015-02-26 18:05:51 -08002359 """
You Wangfdcbfc42016-05-16 12:16:53 -07002360 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002361 Gets intent state. Accepts a single intent ID (string type) or a
You Wangfdcbfc42016-05-16 12:16:53 -07002362 list of intent IDs.
2363 Parameters:
2364 intentsId: intent ID, both string type and list type are acceptable
kelvin-onlab54400a92015-02-26 18:05:51 -08002365 intentsJson: parsed json object from the onos:intents api
You Wangfdcbfc42016-05-16 12:16:53 -07002366 Returns:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002367 Returns the state (string type) of the ID if a single intent ID is
You Wangfdcbfc42016-05-16 12:16:53 -07002368 accepted.
2369 Returns a list of dictionaries if a list of intent IDs is accepted,
2370 and each dictionary maps 'id' to the Intent ID and 'state' to
2371 corresponding intent state.
kelvin-onlab54400a92015-02-26 18:05:51 -08002372 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002373
kelvin-onlab54400a92015-02-26 18:05:51 -08002374 try:
2375 state = "State is Undefined"
2376 if not intentsJson:
Jon Hallc6793552016-01-19 14:18:37 -08002377 rawJson = self.intents()
kelvin-onlab54400a92015-02-26 18:05:51 -08002378 else:
Jon Hallc6793552016-01-19 14:18:37 -08002379 rawJson = intentsJson
2380 parsedIntentsJson = json.loads( rawJson )
Jon Hallefbd9792015-03-05 16:11:36 -08002381 if isinstance( intentsId, types.StringType ):
Jon Hallc6793552016-01-19 14:18:37 -08002382 for intent in parsedIntentsJson:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002383 if intentsId == intent[ 'id' ]:
2384 state = intent[ 'state' ]
kelvin-onlab54400a92015-02-26 18:05:51 -08002385 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002386 main.log.info( "Cannot find intent ID" + str( intentsId ) +
Jon Hall53158082017-05-18 11:17:00 -07002387 " in the list" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002388 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002389 elif isinstance( intentsId, types.ListType ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002390 dictList = []
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002391 for i in xrange( len( intentsId ) ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002392 stateDict = {}
Jon Hall53158082017-05-18 11:17:00 -07002393 for intent in parsedIntentsJson:
2394 if intentsId[ i ] == intent[ 'id' ]:
2395 stateDict[ 'state' ] = intent[ 'state' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002396 stateDict[ 'id' ] = intentsId[ i ]
Jon Hallefbd9792015-03-05 16:11:36 -08002397 dictList.append( stateDict )
kelvin-onlab54400a92015-02-26 18:05:51 -08002398 break
Jon Hallefbd9792015-03-05 16:11:36 -08002399 if len( intentsId ) != len( dictList ):
Jon Hall53158082017-05-18 11:17:00 -07002400 main.log.warn( "Could not find all intents in ONOS output" )
2401 main.log.debug( "expected ids: {} \n ONOS intents: {}".format( intentsId, parsedIntentsJson ) )
kelvin-onlab07dbd012015-03-04 16:29:39 -08002402 return dictList
kelvin-onlab54400a92015-02-26 18:05:51 -08002403 else:
Jon Hall53158082017-05-18 11:17:00 -07002404 main.log.info( "Invalid type for intentsId argument" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002405 return None
Jon Hallc6793552016-01-19 14:18:37 -08002406 except ( TypeError, ValueError ):
2407 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
kelvin-onlab54400a92015-02-26 18:05:51 -08002408 return None
2409 except pexpect.EOF:
2410 main.log.error( self.name + ": EOF exception found" )
2411 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002412 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002413 except Exception:
kelvin-onlab54400a92015-02-26 18:05:51 -08002414 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002415 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07002416
Jon Hallf539eb92017-05-22 17:18:42 -07002417 def checkIntentState( self, intentsId, expectedState='INSTALLED' ):
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002418 """
2419 Description:
2420 Check intents state
2421 Required:
2422 intentsId - List of intents ID to be checked
2423 Optional:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002424 expectedState - Check the expected state(s) of each intents
kelvin-onlabf512e942015-06-08 19:42:59 -07002425 state in the list.
2426 *NOTE: You can pass in a list of expected state,
2427 Eg: expectedState = [ 'INSTALLED' , 'INSTALLING' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002428 Return:
Jon Hall53158082017-05-18 11:17:00 -07002429 Returns main.TRUE only if all intent are the same as expected states,
2430 otherwise returns main.FALSE.
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002431 """
2432 try:
kelvin-onlabf512e942015-06-08 19:42:59 -07002433 returnValue = main.TRUE
Jon Hallf539eb92017-05-22 17:18:42 -07002434 # Generating a dictionary: intent id as a key and state as value
Devin Lim752dd7b2017-06-27 14:40:03 -07002435
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002436 # intentsDict = self.getIntentState( intentsId )
Devin Lim752dd7b2017-06-27 14:40:03 -07002437 intentsDict = []
2438 for intent in json.loads( self.intents() ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002439 if isinstance( intentsId, types.StringType ) \
2440 and intent.get( 'id' ) == intentsId:
2441 intentsDict.append( intent )
2442 elif isinstance( intentsId, types.ListType ) \
Devin Lim752dd7b2017-06-27 14:40:03 -07002443 and any( intent.get( 'id' ) == ids for ids in intentsId ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002444 intentsDict.append( intent )
Devin Lim752dd7b2017-06-27 14:40:03 -07002445
2446 if not intentsDict:
Jon Hallae04e622016-01-27 10:38:05 -08002447 main.log.info( self.name + ": There is something wrong " +
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002448 "getting intents state" )
2449 return main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002450
2451 if isinstance( expectedState, types.StringType ):
2452 for intents in intentsDict:
2453 if intents.get( 'state' ) != expectedState:
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002454 main.log.debug( self.name + " : Intent ID - " +
2455 intents.get( 'id' ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002456 " actual state = " +
2457 intents.get( 'state' )
2458 + " does not equal expected state = "
2459 + expectedState )
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002460 returnValue = main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002461 elif isinstance( expectedState, types.ListType ):
2462 for intents in intentsDict:
2463 if not any( state == intents.get( 'state' ) for state in
2464 expectedState ):
2465 main.log.debug( self.name + " : Intent ID - " +
2466 intents.get( 'id' ) +
2467 " actual state = " +
2468 intents.get( 'state' ) +
2469 " does not equal expected states = "
2470 + str( expectedState ) )
2471 returnValue = main.FALSE
2472
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002473 if returnValue == main.TRUE:
2474 main.log.info( self.name + ": All " +
2475 str( len( intentsDict ) ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002476 " intents are in " + str( expectedState ) +
2477 " state" )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002478 return returnValue
2479 except TypeError:
2480 main.log.exception( self.name + ": Object not as expected" )
2481 return None
2482 except pexpect.EOF:
2483 main.log.error( self.name + ": EOF exception found" )
2484 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002485 main.cleanAndExit()
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002486 except Exception:
2487 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002488 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04002489
Jon Hallf539eb92017-05-22 17:18:42 -07002490 def compareBandwidthAllocations( self, expectedAllocations ):
2491 """
2492 Description:
2493 Compare the allocated bandwidth with the given allocations
2494 Required:
2495 expectedAllocations - The expected ONOS output of the allocations command
2496 Return:
2497 Returns main.TRUE only if all intent are the same as expected states,
2498 otherwise returns main.FALSE.
2499 """
2500 # FIXME: Convert these string comparisons to object comparisons
2501 try:
2502 returnValue = main.TRUE
2503 bandwidthFailed = False
2504 rawAlloc = self.allocations()
2505 expectedFormat = StringIO( expectedAllocations )
2506 ONOSOutput = StringIO( rawAlloc )
2507 main.log.debug( "ONOSOutput: {}\nexpected output: {}".format( str( ONOSOutput ),
2508 str( expectedFormat ) ) )
2509
2510 for actual, expected in izip( ONOSOutput, expectedFormat ):
2511 actual = actual.rstrip()
2512 expected = expected.rstrip()
2513 main.log.debug( "Expect: {}\nactual: {}".format( expected, actual ) )
2514 if actual != expected and 'allocated' in actual and 'allocated' in expected:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002515 marker1 = actual.find( 'allocated' )
2516 m1 = actual[ :marker1 ]
2517 marker2 = expected.find( 'allocated' )
2518 m2 = expected[ :marker2 ]
Jon Hallf539eb92017-05-22 17:18:42 -07002519 if m1 != m2:
2520 bandwidthFailed = True
2521 elif actual != expected and 'allocated' not in actual and 'allocated' not in expected:
2522 bandwidthFailed = True
2523 expectedFormat.close()
2524 ONOSOutput.close()
2525
2526 if bandwidthFailed:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002527 main.log.error( "Bandwidth not allocated correctly using Intents!!" )
Jon Hallf539eb92017-05-22 17:18:42 -07002528 returnValue = main.FALSE
2529 return returnValue
2530 except TypeError:
2531 main.log.exception( self.name + ": Object not as expected" )
2532 return None
2533 except pexpect.EOF:
2534 main.log.error( self.name + ": EOF exception found" )
2535 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002536 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002537 except Exception:
2538 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002539 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002540
You Wang66518af2016-05-16 15:32:59 -07002541 def compareIntent( self, intentDict ):
2542 """
2543 Description:
2544 Compare the intent ids and states provided in the argument with all intents in ONOS
2545 Return:
2546 Returns main.TRUE if the two sets of intents match exactly, otherwise main.FALSE
2547 Arguments:
2548 intentDict: a dictionary which maps intent ids to intent states
2549 """
2550 try:
2551 intentsRaw = self.intents()
2552 intentsJson = json.loads( intentsRaw )
2553 intentDictONOS = {}
2554 for intent in intentsJson:
2555 intentDictONOS[ intent[ 'id' ] ] = intent[ 'state' ]
You Wang58d04452016-09-21 15:13:05 -07002556 returnValue = main.TRUE
You Wang66518af2016-05-16 15:32:59 -07002557 if len( intentDict ) != len( intentDictONOS ):
You Wang58d04452016-09-21 15:13:05 -07002558 main.log.warn( self.name + ": expected intent count does not match that in ONOS, " +
You Wang66518af2016-05-16 15:32:59 -07002559 str( len( intentDict ) ) + " expected and " +
2560 str( len( intentDictONOS ) ) + " actual" )
You Wang58d04452016-09-21 15:13:05 -07002561 returnValue = main.FALSE
You Wang66518af2016-05-16 15:32:59 -07002562 for intentID in intentDict.keys():
Jon Halle0f0b342017-04-18 11:43:47 -07002563 if intentID not in intentDictONOS.keys():
You Wang66518af2016-05-16 15:32:59 -07002564 main.log.debug( self.name + ": intent ID - " + intentID + " is not in ONOS" )
2565 returnValue = main.FALSE
You Wang58d04452016-09-21 15:13:05 -07002566 else:
2567 if intentDict[ intentID ] != intentDictONOS[ intentID ]:
2568 main.log.debug( self.name + ": intent ID - " + intentID +
2569 " expected state is " + intentDict[ intentID ] +
2570 " but actual state is " + intentDictONOS[ intentID ] )
2571 returnValue = main.FALSE
2572 intentDictONOS.pop( intentID )
2573 if len( intentDictONOS ) > 0:
2574 returnValue = main.FALSE
2575 for intentID in intentDictONOS.keys():
2576 main.log.debug( self.name + ": find extra intent in ONOS: intent ID " + intentID )
You Wang66518af2016-05-16 15:32:59 -07002577 if returnValue == main.TRUE:
2578 main.log.info( self.name + ": all intent IDs and states match that in ONOS" )
2579 return returnValue
You Wang1be9a512016-05-26 16:54:17 -07002580 except KeyError:
2581 main.log.exception( self.name + ": KeyError exception found" )
2582 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002583 except ( TypeError, ValueError ):
2584 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intentsRaw ) )
You Wang85560372016-05-18 10:44:33 -07002585 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002586 except pexpect.EOF:
2587 main.log.error( self.name + ": EOF exception found" )
2588 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002589 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002590 except Exception:
2591 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002592 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002593
YPZhang14a4aa92016-07-15 13:37:15 -07002594 def checkIntentSummary( self, timeout=60, noExit=True ):
GlennRCed771242016-01-13 17:02:47 -08002595 """
2596 Description:
2597 Check the number of installed intents.
2598 Optional:
2599 timeout - the timeout for pexcept
YPZhang14a4aa92016-07-15 13:37:15 -07002600 noExit - If noExit, TestON will not exit if any except.
GlennRCed771242016-01-13 17:02:47 -08002601 Return:
2602 Returns main.TRUE only if the number of all installed intents are the same as total intents number
2603 , otherwise, returns main.FALSE.
2604 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002605
GlennRCed771242016-01-13 17:02:47 -08002606 try:
2607 cmd = "intents -s -j"
2608
2609 # Check response if something wrong
YPZhang14a4aa92016-07-15 13:37:15 -07002610 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002611 if response is None:
YPZhang0584d432016-06-21 15:20:13 -07002612 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002613 response = json.loads( response )
2614
2615 # get total and installed number, see if they are match
2616 allState = response.get( 'all' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002617 if allState.get( 'total' ) == allState.get( 'installed' ):
Jon Halla478b852017-12-04 15:00:15 -08002618 main.log.info( 'Total Intents: {} Installed Intents: {}'.format(
2619 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002620 return main.TRUE
Jon Halla478b852017-12-04 15:00:15 -08002621 main.log.info( 'Verified Intents failed Expected intents: {} installed intents: {}'.format(
2622 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002623 return main.FALSE
2624
Jon Hallc6793552016-01-19 14:18:37 -08002625 except ( TypeError, ValueError ):
2626 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
GlennRCed771242016-01-13 17:02:47 -08002627 return None
2628 except pexpect.EOF:
2629 main.log.error( self.name + ": EOF exception found" )
2630 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002631 if noExit:
2632 return main.FALSE
2633 else:
Devin Lim44075962017-08-11 10:56:37 -07002634 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07002635 except pexpect.TIMEOUT:
2636 main.log.error( self.name + ": ONOS timeout" )
2637 return None
GlennRCed771242016-01-13 17:02:47 -08002638 except Exception:
2639 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002640 if noExit:
2641 return main.FALSE
2642 else:
Devin Lim44075962017-08-11 10:56:37 -07002643 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002644
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002645 def flows( self, state="any", jsonFormat=True, timeout=60, noExit=False, noCore=False, device=""):
kelvin8ec71442015-01-15 16:57:00 -08002646 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002647 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002648 * jsonFormat: enable output formatting in json
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002649 * noCore: suppress core flows
Shreya Shah0f01c812014-10-26 20:15:28 -04002650 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002651 Obtain flows currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08002652 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002653 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002654 cmdStr = "flows"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002655 if jsonFormat:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002656 cmdStr += " -j"
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002657 if noCore:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002658 cmdStr += " -n"
2659 cmdStr += " " + state
2660 cmdStr += " " + device
YPZhangebf9eb52016-05-12 15:20:24 -07002661 handle = self.sendline( cmdStr, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002662 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002663 assert "Command not found:" not in handle, handle
2664 if re.search( "Error:", handle ):
2665 main.log.error( self.name + ": flows() response: " +
2666 str( handle ) )
2667 return handle
2668 except AssertionError:
2669 main.log.exception( "" )
GlennRCed771242016-01-13 17:02:47 -08002670 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002671 except TypeError:
2672 main.log.exception( self.name + ": Object not as expected" )
2673 return None
Jon Hallc6793552016-01-19 14:18:37 -08002674 except pexpect.TIMEOUT:
2675 main.log.error( self.name + ": ONOS timeout" )
2676 return None
Shreya Shah0f01c812014-10-26 20:15:28 -04002677 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002678 main.log.error( self.name + ": EOF exception found" )
2679 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002680 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002681 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002682 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002683 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002684
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002685 def checkFlowCount( self, min=0, timeout=60 ):
Flavio Castroa1286fe2016-07-25 14:48:51 -07002686 count = self.getTotalFlowsNum( timeout=timeout )
Jon Halle0f0b342017-04-18 11:43:47 -07002687 count = int( count ) if count else 0
steven30801eccfe212019-01-24 13:00:42 +08002688 main.log.debug( "found {} flows".format( count ) )
Jon Halle0f0b342017-04-18 11:43:47 -07002689 return count if ( count > min ) else False
GlennRCed771242016-01-13 17:02:47 -08002690
Jon Halle0f0b342017-04-18 11:43:47 -07002691 def checkFlowsState( self, isPENDING=True, timeout=60, noExit=False ):
kelvin-onlab4df89f22015-04-13 18:10:23 -07002692 """
2693 Description:
GlennRCed771242016-01-13 17:02:47 -08002694 Check the if all the current flows are in ADDED state
Jon Hallc6793552016-01-19 14:18:37 -08002695 We check PENDING_ADD, PENDING_REMOVE, REMOVED, and FAILED flows,
2696 if the count of those states is 0, which means all current flows
2697 are in ADDED state, and return main.TRUE otherwise return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002698 Optional:
GlennRCed771242016-01-13 17:02:47 -08002699 * isPENDING: whether the PENDING_ADD is also a correct status
kelvin-onlab4df89f22015-04-13 18:10:23 -07002700 Return:
2701 returnValue - Returns main.TRUE only if all flows are in
Jon Hallc6793552016-01-19 14:18:37 -08002702 ADDED state or PENDING_ADD if the isPENDING
pingping-linbab7f8a2015-09-21 17:33:36 -07002703 parameter is set true, return main.FALSE otherwise.
kelvin-onlab4df89f22015-04-13 18:10:23 -07002704 """
2705 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002706 states = [ "PENDING_ADD", "PENDING_REMOVE", "REMOVED", "FAILED" ]
GlennRCed771242016-01-13 17:02:47 -08002707 checkedStates = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002708 statesCount = [ 0, 0, 0, 0 ]
GlennRCed771242016-01-13 17:02:47 -08002709 for s in states:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002710 rawFlows = self.flows( state=s, timeout = timeout )
YPZhang240842b2016-05-17 12:00:50 -07002711 if rawFlows:
2712 # if we didn't get flows or flows function return None, we should return
2713 # main.Flase
2714 checkedStates.append( json.loads( rawFlows ) )
2715 else:
2716 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002717 for i in range( len( states ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002718 for c in checkedStates[ i ]:
Jon Hallc6793552016-01-19 14:18:37 -08002719 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002720 statesCount[ i ] += int( c.get( "flowCount" ) )
Jon Hallc6793552016-01-19 14:18:37 -08002721 except TypeError:
2722 main.log.exception( "Json object not as expected" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002723 main.log.info( states[ i ] + " flows: " + str( statesCount[ i ] ) )
kelvin-onlabf2ec6e02015-05-27 14:15:28 -07002724
GlennRCed771242016-01-13 17:02:47 -08002725 # We want to count PENDING_ADD if isPENDING is true
2726 if isPENDING:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002727 if statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002728 return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002729 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002730 if statesCount[ 0 ] + statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002731 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002732 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002733 except ( TypeError, ValueError ):
2734 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawFlows ) )
kelvin-onlab4df89f22015-04-13 18:10:23 -07002735 return None
Jeremy Songster9385d412016-06-02 17:57:36 -07002736
YPZhang240842b2016-05-17 12:00:50 -07002737 except AssertionError:
2738 main.log.exception( "" )
2739 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002740 except pexpect.TIMEOUT:
2741 main.log.error( self.name + ": ONOS timeout" )
2742 return None
kelvin-onlab4df89f22015-04-13 18:10:23 -07002743 except pexpect.EOF:
2744 main.log.error( self.name + ": EOF exception found" )
2745 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002746 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002747 except Exception:
2748 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002749 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002750
GlennRCed771242016-01-13 17:02:47 -08002751 def pushTestIntents( self, ingress, egress, batchSize, offset="",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002752 options="", timeout=10, background = False, noExit=False, getResponse=False ):
kelvin8ec71442015-01-15 16:57:00 -08002753 """
andrewonlab87852b02014-11-19 18:44:19 -05002754 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002755 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05002756 a specific point-to-point intent definition
2757 Required:
GlennRCed771242016-01-13 17:02:47 -08002758 * ingress: specify source dpid
2759 * egress: specify destination dpid
2760 * batchSize: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05002761 Optional:
GlennRCed771242016-01-13 17:02:47 -08002762 * offset: the keyOffset is where the next batch of intents
2763 will be installed
YPZhangb34b7e12016-06-14 14:28:19 -07002764 * noExit: If set to True, TestON will not exit if any error when issus command
2765 * getResponse: If set to True, function will return ONOS response.
2766
GlennRCed771242016-01-13 17:02:47 -08002767 Returns: If failed to push test intents, it will returen None,
2768 if successful, return true.
2769 Timeout expection will return None,
2770 TypeError will return false
2771 other expections will exit()
kelvin8ec71442015-01-15 16:57:00 -08002772 """
andrewonlab87852b02014-11-19 18:44:19 -05002773 try:
GlennRCed771242016-01-13 17:02:47 -08002774 if background:
2775 back = "&"
andrewonlab87852b02014-11-19 18:44:19 -05002776 else:
GlennRCed771242016-01-13 17:02:47 -08002777 back = ""
2778 cmd = "push-test-intents {} {} {} {} {} {}".format( options,
Jon Hallc6793552016-01-19 14:18:37 -08002779 ingress,
2780 egress,
2781 batchSize,
2782 offset,
2783 back )
YPZhangebf9eb52016-05-12 15:20:24 -07002784 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002785 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002786 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08002787 main.log.info( response )
YPZhangb34b7e12016-06-14 14:28:19 -07002788 if getResponse:
2789 return response
2790
GlennRCed771242016-01-13 17:02:47 -08002791 # TODO: We should handle if there is failure in installation
2792 return main.TRUE
2793
Jon Hallc6793552016-01-19 14:18:37 -08002794 except AssertionError:
2795 main.log.exception( "" )
2796 return None
GlennRCed771242016-01-13 17:02:47 -08002797 except pexpect.TIMEOUT:
2798 main.log.error( self.name + ": ONOS timeout" )
Jon Halld4d4b372015-01-28 16:02:41 -08002799 return None
andrewonlab87852b02014-11-19 18:44:19 -05002800 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002801 main.log.error( self.name + ": EOF exception found" )
2802 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002803 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002804 except TypeError:
2805 main.log.exception( self.name + ": Object not as expected" )
Jon Hallc6793552016-01-19 14:18:37 -08002806 return None
Jon Hallfebb1c72015-03-05 13:30:09 -08002807 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002808 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002809 main.cleanAndExit()
andrewonlab87852b02014-11-19 18:44:19 -05002810
YPZhangebf9eb52016-05-12 15:20:24 -07002811 def getTotalFlowsNum( self, timeout=60, noExit=False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002812 """
2813 Description:
YPZhangf6f14a02016-01-28 15:17:31 -08002814 Get the number of ADDED flows.
YPZhangb5d3f832016-01-23 22:54:26 -08002815 Return:
YPZhangf6f14a02016-01-28 15:17:31 -08002816 The number of ADDED flows
YPZhang14a4aa92016-07-15 13:37:15 -07002817 Or return None if any exceptions
YPZhangb5d3f832016-01-23 22:54:26 -08002818 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002819
YPZhangb5d3f832016-01-23 22:54:26 -08002820 try:
YPZhange3109a72016-02-02 11:25:37 -08002821 # get total added flows number
YPZhang14a4aa92016-07-15 13:37:15 -07002822 cmd = "flows -c added"
2823 rawFlows = self.sendline( cmd, timeout=timeout, noExit=noExit )
2824 if rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002825 rawFlows = rawFlows.split( "\n" )
YPZhange3109a72016-02-02 11:25:37 -08002826 totalFlows = 0
YPZhang14a4aa92016-07-15 13:37:15 -07002827 for l in rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002828 totalFlows += int( l.split( "Count=" )[ 1 ] )
YPZhang14a4aa92016-07-15 13:37:15 -07002829 else:
You Wang68568b12019-03-04 11:49:57 -08002830 main.log.warn( "Response not as expected!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002831 return None
2832 return totalFlows
YPZhange3109a72016-02-02 11:25:37 -08002833
You Wangd3097f72018-12-12 11:56:03 -08002834 except IndexError:
2835 main.log.exception( "{}: Object not as expected!".format( self.name ) )
2836 main.log.debug( "rawFlows: {}".format( rawFlows ) )
2837 return None
You Wangd3cb2ce2016-05-16 14:01:24 -07002838 except ( TypeError, ValueError ):
YPZhang14a4aa92016-07-15 13:37:15 -07002839 main.log.exception( "{}: Object not as expected!".format( self.name ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002840 return None
2841 except pexpect.EOF:
2842 main.log.error( self.name + ": EOF exception found" )
2843 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002844 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002845 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002846 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002847 except pexpect.TIMEOUT:
2848 main.log.error( self.name + ": ONOS timeout" )
2849 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002850 except Exception:
2851 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002852 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002853 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002854 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002855
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002856 def getTotalIntentsNum( self, timeout=60, noExit = False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002857 """
2858 Description:
2859 Get the total number of intents, include every states.
YPZhang14a4aa92016-07-15 13:37:15 -07002860 Optional:
2861 noExit - If noExit, TestON will not exit if any except.
YPZhangb5d3f832016-01-23 22:54:26 -08002862 Return:
2863 The number of intents
2864 """
2865 try:
2866 cmd = "summary -j"
YPZhang14a4aa92016-07-15 13:37:15 -07002867 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002868 if response is None:
2869 return -1
YPZhangb5d3f832016-01-23 22:54:26 -08002870 response = json.loads( response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002871 return int( response.get( "intents" ) )
You Wangd3cb2ce2016-05-16 14:01:24 -07002872 except ( TypeError, ValueError ):
2873 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002874 return None
2875 except pexpect.EOF:
2876 main.log.error( self.name + ": EOF exception found" )
2877 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002878 if noExit:
2879 return -1
2880 else:
Devin Lim44075962017-08-11 10:56:37 -07002881 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002882 except Exception:
2883 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002884 if noExit:
2885 return -1
2886 else:
Devin Lim44075962017-08-11 10:56:37 -07002887 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002888
kelvin-onlabd3b64892015-01-20 13:26:24 -08002889 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002890 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002891 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002892 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002893 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002894 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002895 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002896 cmdStr = "intents-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002897 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002898 cmdStr += " -j"
2899 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002900 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002901 assert "Command not found:" not in handle, handle
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002902 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002903 except AssertionError:
2904 main.log.exception( "" )
2905 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002906 except TypeError:
2907 main.log.exception( self.name + ": Object not as expected" )
2908 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002909 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002910 main.log.error( self.name + ": EOF exception found" )
2911 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002912 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002913 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002914 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002915 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002916
kelvin-onlabd3b64892015-01-20 13:26:24 -08002917 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002918 """
2919 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04002920 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002921 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002922 """
andrewonlab867212a2014-10-22 20:13:38 -04002923 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002924 cmdStr = "topology-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002925 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002926 cmdStr += " -j"
2927 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002928 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002929 assert "Command not found:" not in handle, handle
jenkins7ead5a82015-03-13 10:28:21 -07002930 if handle:
2931 return handle
Jon Hallc6358dd2015-04-10 12:44:28 -07002932 elif jsonFormat:
Jon Hallbe379602015-03-24 13:39:32 -07002933 # Return empty json
jenkins7ead5a82015-03-13 10:28:21 -07002934 return '{}'
Jon Hallc6358dd2015-04-10 12:44:28 -07002935 else:
2936 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002937 except AssertionError:
2938 main.log.exception( "" )
2939 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002940 except TypeError:
2941 main.log.exception( self.name + ": Object not as expected" )
2942 return None
andrewonlab867212a2014-10-22 20:13:38 -04002943 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002944 main.log.error( self.name + ": EOF exception found" )
2945 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002946 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002947 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002948 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002949 main.cleanAndExit()
andrewonlab867212a2014-10-22 20:13:38 -04002950
kelvin8ec71442015-01-15 16:57:00 -08002951 # Wrapper functions ****************
2952 # Wrapper functions use existing driver
2953 # functions and extends their use case.
2954 # For example, we may use the output of
2955 # a normal driver function, and parse it
2956 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04002957
kelvin-onlabd3b64892015-01-20 13:26:24 -08002958 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002959 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002960 Description:
2961 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08002962 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002963 try:
kelvin8ec71442015-01-15 16:57:00 -08002964 # Obtain output of intents function
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002965 intentsStr = self.intents( jsonFormat=True )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07002966 if intentsStr is None:
2967 raise TypeError
Jon Hall6021e062017-01-30 11:10:06 -08002968 # Convert to a dictionary
2969 intents = json.loads( intentsStr )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002970 intentIdList = []
Jon Hall6021e062017-01-30 11:10:06 -08002971 for intent in intents:
2972 intentIdList.append( intent[ 'id' ] )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002973 return intentIdList
Jon Halld4d4b372015-01-28 16:02:41 -08002974 except TypeError:
2975 main.log.exception( self.name + ": Object not as expected" )
2976 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002977 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002978 main.log.error( self.name + ": EOF exception found" )
2979 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002980 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002981 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002982 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002983 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04002984
You Wang3c276252016-09-21 15:21:36 -07002985 def flowAddedCount( self, deviceId, core=False ):
Jon Hall30b82fa2015-03-04 17:15:43 -08002986 """
2987 Determine the number of flow rules for the given device id that are
2988 in the added state
You Wang3c276252016-09-21 15:21:36 -07002989 Params:
2990 core: if True, only return the number of core flows added
Jon Hall30b82fa2015-03-04 17:15:43 -08002991 """
2992 try:
You Wang3c276252016-09-21 15:21:36 -07002993 if core:
2994 cmdStr = "flows any " + str( deviceId ) + " | " +\
2995 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
2996 else:
2997 cmdStr = "flows any " + str( deviceId ) + " | " +\
2998 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08002999 handle = self.lineCount( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003000 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003001 assert "Command not found:" not in handle, handle
Jon Hall30b82fa2015-03-04 17:15:43 -08003002 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003003 except AssertionError:
3004 main.log.exception( "" )
3005 return None
Jon Hall30b82fa2015-03-04 17:15:43 -08003006 except pexpect.EOF:
3007 main.log.error( self.name + ": EOF exception found" )
3008 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003009 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003010 except Exception:
Jon Hall30b82fa2015-03-04 17:15:43 -08003011 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003012 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -04003013
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003014 def groupAddedCount( self, deviceId, core=False ):
3015 """
3016 Determine the number of group rules for the given device id that are
3017 in the added state
3018 Params:
3019 core: if True, only return the number of core groups added
3020 """
3021 try:
3022 if core:
3023 cmdStr = "groups any " + str( deviceId ) + " | " +\
3024 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
3025 else:
3026 cmdStr = "groups any " + str( deviceId ) + " | " +\
3027 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003028 handle = self.lineCount( cmdStr )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003029 assert handle is not None, "Error in sendline"
3030 assert "Command not found:" not in handle, handle
3031 return handle
3032 except AssertionError:
3033 main.log.exception( "" )
3034 return None
3035 except pexpect.EOF:
3036 main.log.error( self.name + ": EOF exception found" )
3037 main.log.error( self.name + ": " + self.handle.before )
3038 main.cleanAndExit()
3039 except Exception:
3040 main.log.exception( self.name + ": Uncaught exception!" )
3041 main.cleanAndExit()
3042
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003043 def addStaticRoute( self, subnet, intf):
3044 """
3045 Adds a static route to onos.
3046 Params:
3047 subnet: The subnet reaching through this route
3048 intf: The interface this route is reachable through
3049 """
3050 try:
3051 cmdStr = "route-add " + subnet + " " + intf
3052 handle = self.sendline( cmdStr )
3053 assert handle is not None, "Error in sendline"
3054 assert "Command not found:" not in handle, handle
3055 return handle
3056 except AssertionError:
3057 main.log.exception( "" )
3058 return None
3059 except pexpect.EOF:
3060 main.log.error( self.name + ": EOF exception found" )
3061 main.log.error( self.name + ": " + self.handle.before )
3062 main.cleanAndExit()
3063 except Exception:
3064 main.log.exception( self.name + ": Uncaught exception!" )
3065 main.cleanAndExit()
3066
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003067 def checkGroupAddedCount( self, deviceId, expectedGroupCount=0, core=False, comparison=0):
3068 """
3069 Description:
3070 Check whether the number of groups for the given device id that
3071 are in ADDED state is bigger than minGroupCount.
3072 Required:
3073 * deviceId: device id to check the number of added group rules
3074 Optional:
3075 * minGroupCount: the number of groups to compare
3076 * core: if True, only check the number of core groups added
3077 * comparison: if 0, compare with greater than minFlowCount
3078 * if 1, compare with equal to minFlowCount
3079 Return:
3080 Returns the number of groups if it is bigger than minGroupCount,
3081 returns main.FALSE otherwise.
3082 """
3083 count = self.groupAddedCount( deviceId, core )
3084 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003085 main.log.debug( "found {} groups".format( count ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003086 return count if ((count > expectedGroupCount) if (comparison == 0) else (count == expectedGroupCount)) else main.FALSE
3087
You Wangc02f3be2018-05-18 12:14:23 -07003088 def getGroups( self, deviceId, groupType="any" ):
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003089 """
3090 Retrieve groups from a specific device.
You Wangc02f3be2018-05-18 12:14:23 -07003091 deviceId: Id of the device from which we retrieve groups
3092 groupType: Type of group
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003093 """
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003094 try:
You Wangc02f3be2018-05-18 12:14:23 -07003095 groupCmd = "groups -t {0} any {1}".format( groupType, deviceId )
3096 handle = self.sendline( groupCmd )
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003097 assert handle is not None, "Error in sendline"
3098 assert "Command not found:" not in handle, handle
3099 return handle
3100 except AssertionError:
3101 main.log.exception( "" )
3102 return None
3103 except TypeError:
3104 main.log.exception( self.name + ": Object not as expected" )
3105 return None
3106 except pexpect.EOF:
3107 main.log.error( self.name + ": EOF exception found" )
3108 main.log.error( self.name + ": " + self.handle.before )
3109 main.cleanAndExit()
3110 except Exception:
3111 main.log.exception( self.name + ": Uncaught exception!" )
3112 main.cleanAndExit()
3113
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003114 def checkFlowAddedCount( self, deviceId, expectedFlowCount=0, core=False, comparison=0):
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003115 """
3116 Description:
3117 Check whether the number of flow rules for the given device id that
3118 are in ADDED state is bigger than minFlowCount.
3119 Required:
3120 * deviceId: device id to check the number of added flow rules
3121 Optional:
3122 * minFlowCount: the number of flow rules to compare
3123 * core: if True, only check the number of core flows added
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003124 * comparison: if 0, compare with greater than minFlowCount
3125 * if 1, compare with equal to minFlowCount
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003126 Return:
3127 Returns the number of flow rules if it is bigger than minFlowCount,
3128 returns main.FALSE otherwise.
3129 """
3130 count = self.flowAddedCount( deviceId, core )
3131 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003132 main.log.debug( "found {} flows".format( count ) )
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003133 return count if ((count > expectedFlowCount) if (comparison == 0) else (count == expectedFlowCount)) else main.FALSE
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003134
kelvin-onlabd3b64892015-01-20 13:26:24 -08003135 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003136 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003137 Use 'devices' function to obtain list of all devices
3138 and parse the result to obtain a list of all device
3139 id's. Returns this list. Returns empty list if no
3140 devices exist
kelvin8ec71442015-01-15 16:57:00 -08003141 List is ordered sequentially
3142
andrewonlab3e15ead2014-10-15 14:21:34 -04003143 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08003144 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04003145 the ids. By obtaining the list of device ids on the fly,
3146 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08003147 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003148 try:
kelvin8ec71442015-01-15 16:57:00 -08003149 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08003150 devicesStr = self.devices( jsonFormat=False )
3151 idList = []
kelvin8ec71442015-01-15 16:57:00 -08003152
kelvin-onlabd3b64892015-01-20 13:26:24 -08003153 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08003154 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003155 return idList
kelvin8ec71442015-01-15 16:57:00 -08003156
3157 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08003158 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08003159 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08003160 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08003161 # Split list further into arguments before and after string
3162 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08003163 # append to idList
3164 for arg in tempList:
3165 idList.append( arg.split( "id=" )[ 1 ] )
3166 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04003167
Jon Halld4d4b372015-01-28 16:02:41 -08003168 except TypeError:
3169 main.log.exception( self.name + ": Object not as expected" )
3170 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04003171 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003172 main.log.error( self.name + ": EOF exception found" )
3173 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003174 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003175 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003176 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003177 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003178
kelvin-onlabd3b64892015-01-20 13:26:24 -08003179 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003180 """
andrewonlab7c211572014-10-15 16:45:20 -04003181 Uses 'nodes' function to obtain list of all nodes
3182 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08003183 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04003184 Returns:
3185 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08003186 """
andrewonlab7c211572014-10-15 16:45:20 -04003187 try:
Jon Hall5aa168b2015-03-23 14:23:09 -07003188 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003189 idList = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003190 # Sample nodesStr output
Jon Hallbd182782016-03-28 16:42:22 -07003191 # id=local, address=127.0.0.1:9876, state=READY *
kelvin-onlabd3b64892015-01-20 13:26:24 -08003192 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08003193 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003194 return idList
Jon Hall5aa168b2015-03-23 14:23:09 -07003195 nodesJson = json.loads( nodesStr )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003196 idList = [ node.get( 'id' ) for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08003197 return idList
Jon Hallc6793552016-01-19 14:18:37 -08003198 except ( TypeError, ValueError ):
3199 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, nodesStr ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003200 return None
andrewonlab7c211572014-10-15 16:45:20 -04003201 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003202 main.log.error( self.name + ": EOF exception found" )
3203 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003204 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003205 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003206 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003207 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003208
kelvin-onlabd3b64892015-01-20 13:26:24 -08003209 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08003210 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003211 Return the first device from the devices api whose 'id' contains 'dpid'
3212 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08003213 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003214 try:
kelvin8ec71442015-01-15 16:57:00 -08003215 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04003216 return None
3217 else:
kelvin8ec71442015-01-15 16:57:00 -08003218 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003219 rawDevices = self.devices()
3220 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08003221 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08003222 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08003223 # print "%s in %s?" % ( dpid, device[ 'id' ] )
3224 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04003225 return device
3226 return None
Jon Hallc6793552016-01-19 14:18:37 -08003227 except ( TypeError, ValueError ):
3228 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawDevices ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003229 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04003230 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003231 main.log.error( self.name + ": EOF exception found" )
3232 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003233 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003234 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003235 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003236 main.cleanAndExit()
Jon Halla91c4dc2014-10-22 12:57:04 -04003237
You Wang24139872016-05-03 11:48:47 -07003238 def getTopology( self, topologyOutput ):
3239 """
3240 Definition:
3241 Loads a json topology output
3242 Return:
3243 topology = current ONOS topology
3244 """
You Wang24139872016-05-03 11:48:47 -07003245 try:
3246 # either onos:topology or 'topology' will work in CLI
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003247 topology = json.loads( topologyOutput )
Jeremy Songsterbc2d8ac2016-05-04 11:25:42 -07003248 main.log.debug( topology )
You Wang24139872016-05-03 11:48:47 -07003249 return topology
You Wangd3cb2ce2016-05-16 14:01:24 -07003250 except ( TypeError, ValueError ):
3251 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, topologyOutput ) )
3252 return None
You Wang24139872016-05-03 11:48:47 -07003253 except pexpect.EOF:
3254 main.log.error( self.name + ": EOF exception found" )
3255 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003256 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003257 except Exception:
3258 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003259 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003260
Pier6a0c4de2018-03-18 16:01:30 -07003261 def checkStatus( self, numoswitch, numolink = -1, numoctrl = -1, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08003262 """
Jon Hallefbd9792015-03-05 16:11:36 -08003263 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08003264 supplied values. By default this will report to main.log, but the
You Wang24139872016-05-03 11:48:47 -07003265 log level can be specific.
kelvin8ec71442015-01-15 16:57:00 -08003266
Flavio Castro82ee2f62016-06-07 15:04:12 -07003267 Params: numoswitch = expected number of switches
Jon Hallefbd9792015-03-05 16:11:36 -08003268 numolink = expected number of links
Flavio Castro82ee2f62016-06-07 15:04:12 -07003269 numoctrl = expected number of controllers
You Wang24139872016-05-03 11:48:47 -07003270 logLevel = level to log to.
3271 Currently accepts 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04003272
Jon Hallefbd9792015-03-05 16:11:36 -08003273 Returns: main.TRUE if the number of switches and links are correct,
3274 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04003275 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08003276 """
Jon Hall42db6dc2014-10-24 19:03:48 -04003277 try:
You Wang13310252016-07-31 10:56:14 -07003278 summary = self.summary()
3279 summary = json.loads( summary )
Flavio Castrof5b3f872016-06-23 17:52:31 -07003280 except ( TypeError, ValueError ):
3281 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summary ) )
3282 return main.ERROR
3283 try:
3284 topology = self.getTopology( self.topology() )
Jon Halle0f0b342017-04-18 11:43:47 -07003285 if topology == {} or topology is None or summary == {} or summary is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04003286 return main.ERROR
3287 output = ""
kelvin8ec71442015-01-15 16:57:00 -08003288 # Is the number of switches is what we expected
3289 devices = topology.get( 'devices', False )
3290 links = topology.get( 'links', False )
Flavio Castro82ee2f62016-06-07 15:04:12 -07003291 nodes = summary.get( 'nodes', False )
3292 if devices is False or links is False or nodes is False:
Jon Hall42db6dc2014-10-24 19:03:48 -04003293 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08003294 switchCheck = ( int( devices ) == int( numoswitch ) )
kelvin8ec71442015-01-15 16:57:00 -08003295 # Is the number of links is what we expected
Pier6a0c4de2018-03-18 16:01:30 -07003296 linkCheck = ( int( links ) == int( numolink ) ) or int( numolink ) == -1
Flavio Castro82ee2f62016-06-07 15:04:12 -07003297 nodeCheck = ( int( nodes ) == int( numoctrl ) ) or int( numoctrl ) == -1
3298 if switchCheck and linkCheck and nodeCheck:
kelvin8ec71442015-01-15 16:57:00 -08003299 # We expected the correct numbers
You Wang24139872016-05-03 11:48:47 -07003300 output = output + "The number of links and switches match "\
3301 + "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003302 result = main.TRUE
3303 else:
You Wang24139872016-05-03 11:48:47 -07003304 output = output + \
3305 "The number of links and switches does not match " + \
3306 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003307 result = main.FALSE
You Wang24139872016-05-03 11:48:47 -07003308 output = output + "\n ONOS sees %i devices" % int( devices )
3309 output = output + " (%i expected) " % int( numoswitch )
Pier6a0c4de2018-03-18 16:01:30 -07003310 if int( numolink ) > 0:
3311 output = output + "and %i links " % int( links )
3312 output = output + "(%i expected)" % int( numolink )
YPZhangd7e4b6e2016-06-17 16:07:55 -07003313 if int( numoctrl ) > 0:
Flavio Castro82ee2f62016-06-07 15:04:12 -07003314 output = output + "and %i controllers " % int( nodes )
3315 output = output + "(%i expected)" % int( numoctrl )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003316 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08003317 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003318 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08003319 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04003320 else:
You Wang24139872016-05-03 11:48:47 -07003321 main.log.info( output )
kelvin8ec71442015-01-15 16:57:00 -08003322 return result
Jon Hall42db6dc2014-10-24 19:03:48 -04003323 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003324 main.log.error( self.name + ": EOF exception found" )
3325 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003326 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003327 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003328 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003329 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003330
kelvin-onlabd3b64892015-01-20 13:26:24 -08003331 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08003332 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003333 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08003334 deviceId must be the id of a device as seen in the onos devices command
3335 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04003336 role must be either master, standby, or none
3337
Jon Halle3f39ff2015-01-13 11:50:53 -08003338 Returns:
3339 main.TRUE or main.FALSE based on argument verification and
3340 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003341 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003342 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003343 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04003344 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08003345 cmdStr = "device-role " +\
3346 str( deviceId ) + " " +\
3347 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003348 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003349 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003350 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003351 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08003352 if re.search( "Error", handle ):
3353 # end color output to escape any colours
3354 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08003355 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003356 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08003357 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08003358 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04003359 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003360 main.log.error( "Invalid 'role' given to device_role(). " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003361 "Value was '" + str( role ) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04003362 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003363 except AssertionError:
3364 main.log.exception( "" )
3365 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003366 except TypeError:
3367 main.log.exception( self.name + ": Object not as expected" )
3368 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04003369 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003370 main.log.error( self.name + ": EOF exception found" )
3371 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003372 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003373 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003374 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003375 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003376
kelvin-onlabd3b64892015-01-20 13:26:24 -08003377 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08003378 """
Jon Hall0dd09952018-04-19 09:59:11 -07003379 Lists all topology clusters
Jon Hallffb386d2014-11-21 13:43:38 -08003380 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003381 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08003382 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08003383 try:
Jon Hall0dd09952018-04-19 09:59:11 -07003384 cmdStr = "topo-clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003385 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003386 cmdStr += " -j"
3387 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003388 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003389 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07003390 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003391 except AssertionError:
3392 main.log.exception( "" )
3393 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003394 except TypeError:
3395 main.log.exception( self.name + ": Object not as expected" )
3396 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08003397 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003398 main.log.error( self.name + ": EOF exception found" )
3399 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003400 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003401 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003402 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003403 main.cleanAndExit()
Jon Hall73cf9cc2014-11-20 22:28:38 -08003404
kelvin-onlabd3b64892015-01-20 13:26:24 -08003405 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003406 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003407 CLI command to get the current leader for the Election test application
3408 NOTE: Requires installation of the onos-app-election feature
3409 Returns: Node IP of the leader if one exists
3410 None if none exists
3411 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003412 """
Jon Hall94fd0472014-12-08 11:52:42 -08003413 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003414 cmdStr = "election-test-leader"
3415 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003416 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003417 assert "Command not found:" not in response, response
Jon Halle3f39ff2015-01-13 11:50:53 -08003418 # Leader
3419 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003420 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08003421 nodeSearch = re.search( leaderPattern, response )
3422 if nodeSearch:
3423 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08003424 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003425 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08003426 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08003427 # no leader
3428 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003429 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003430 nullSearch = re.search( nullPattern, response )
3431 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08003432 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003433 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08003434 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08003435 # error
Jon Hall0e240372018-05-02 11:21:57 -07003436 main.log.error( self.name + ": Error in electionTestLeader on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003437 ": " + "unexpected response" )
3438 main.log.error( repr( response ) )
3439 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003440 except AssertionError:
3441 main.log.exception( "" )
3442 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003443 except TypeError:
3444 main.log.exception( self.name + ": Object not as expected" )
3445 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003446 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003447 main.log.error( self.name + ": EOF exception found" )
3448 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003449 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003450 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003451 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003452 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003453
kelvin-onlabd3b64892015-01-20 13:26:24 -08003454 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003455 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003456 CLI command to run for leadership of the Election test application.
3457 NOTE: Requires installation of the onos-app-election feature
3458 Returns: Main.TRUE on success
3459 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003460 """
Jon Hall94fd0472014-12-08 11:52:42 -08003461 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003462 cmdStr = "election-test-run"
3463 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003464 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003465 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003466 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003467 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003468 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003469 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08003470 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08003471 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003472 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003473 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003474 # error
Jon Hall0e240372018-05-02 11:21:57 -07003475 main.log.error( self.name + ": Error in electionTestRun on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003476 ": " + "unexpected response" )
3477 main.log.error( repr( response ) )
3478 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003479 except AssertionError:
3480 main.log.exception( "" )
3481 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003482 except TypeError:
3483 main.log.exception( self.name + ": Object not as expected" )
3484 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003485 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003486 main.log.error( self.name + ": EOF exception found" )
3487 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003488 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003489 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003490 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003491 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003492
kelvin-onlabd3b64892015-01-20 13:26:24 -08003493 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08003494 """
Jon Hall94fd0472014-12-08 11:52:42 -08003495 * CLI command to withdraw the local node from leadership election for
3496 * the Election test application.
3497 #NOTE: Requires installation of the onos-app-election feature
3498 Returns: Main.TRUE on success
3499 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08003500 """
Jon Hall94fd0472014-12-08 11:52:42 -08003501 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003502 cmdStr = "election-test-withdraw"
3503 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003504 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003505 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003506 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003507 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003508 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003509 if re.search( successPattern, response ):
3510 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003511 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003512 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003513 # error
Jon Hall0e240372018-05-02 11:21:57 -07003514 main.log.error( self.name + ": Error in electionTestWithdraw on " +
Jon Hall97cf84a2016-06-20 13:35:58 -07003515 self.name + ": " + "unexpected response" )
3516 main.log.error( repr( response ) )
3517 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003518 except AssertionError:
3519 main.log.exception( "" )
3520 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003521 except TypeError:
3522 main.log.exception( self.name + ": Object not as expected" )
3523 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003524 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003525 main.log.error( self.name + ": EOF exception found" )
3526 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003527 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003528 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003529 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003530 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003531
kelvin8ec71442015-01-15 16:57:00 -08003532 def getDevicePortsEnabledCount( self, dpid ):
3533 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003534 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003535 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003536 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003537 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003538 cmdStr = "onos:ports -e " + dpid + " | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003539 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003540 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003541 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003542 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003543 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003544 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003545 return output
Jon Hallc6793552016-01-19 14:18:37 -08003546 except AssertionError:
3547 main.log.exception( "" )
3548 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003549 except TypeError:
3550 main.log.exception( self.name + ": Object not as expected" )
3551 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003552 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003553 main.log.error( self.name + ": EOF exception found" )
3554 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003555 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003556 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003557 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003558 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003559
kelvin8ec71442015-01-15 16:57:00 -08003560 def getDeviceLinksActiveCount( self, dpid ):
3561 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003562 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003563 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003564 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003565 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003566 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003567 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003568 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003569 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003570 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003571 main.log.error( self.name + ": Error in getting ports " )
kelvin-onlab898a6c62015-01-16 14:13:53 -08003572 return ( output, "Error " )
Jon Halla495f562016-05-16 18:03:26 -07003573 return output
Jon Hallc6793552016-01-19 14:18:37 -08003574 except AssertionError:
3575 main.log.exception( "" )
3576 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003577 except TypeError:
3578 main.log.exception( self.name + ": Object not as expected" )
3579 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003580 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003581 main.log.error( self.name + ": EOF exception found" )
3582 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003583 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003584 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003585 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003586 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003587
kelvin8ec71442015-01-15 16:57:00 -08003588 def getAllIntentIds( self ):
3589 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003590 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08003591 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003592 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003593 cmdStr = "onos:intents | grep id="
3594 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003595 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003596 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003597 if re.search( "Error", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003598 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003599 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003600 return output
Jon Hallc6793552016-01-19 14:18:37 -08003601 except AssertionError:
3602 main.log.exception( "" )
3603 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003604 except TypeError:
3605 main.log.exception( self.name + ": Object not as expected" )
3606 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003607 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003608 main.log.error( self.name + ": EOF exception found" )
3609 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003610 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003611 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003612 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003613 main.cleanAndExit()
Jon Halld4d4b372015-01-28 16:02:41 -08003614
Jon Hall73509952015-02-24 16:42:56 -08003615 def intentSummary( self ):
3616 """
Jon Hallefbd9792015-03-05 16:11:36 -08003617 Returns a dictionary containing the current intent states and the count
Jon Hall73509952015-02-24 16:42:56 -08003618 """
3619 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003620 intents = self.intents( )
Jon Hall08f61bc2015-04-13 16:00:30 -07003621 states = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003622 for intent in json.loads( intents ):
Jon Hall08f61bc2015-04-13 16:00:30 -07003623 states.append( intent.get( 'state', None ) )
3624 out = [ ( i, states.count( i ) ) for i in set( states ) ]
Jon Hall63604932015-02-26 17:09:50 -08003625 main.log.info( dict( out ) )
Jon Hall73509952015-02-24 16:42:56 -08003626 return dict( out )
Jon Hallc6793552016-01-19 14:18:37 -08003627 except ( TypeError, ValueError ):
3628 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intents ) )
Jon Hall73509952015-02-24 16:42:56 -08003629 return None
3630 except pexpect.EOF:
3631 main.log.error( self.name + ": EOF exception found" )
3632 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003633 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003634 except Exception:
Jon Hall73509952015-02-24 16:42:56 -08003635 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003636 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003637
Jon Hall61282e32015-03-19 11:34:11 -07003638 def leaders( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003639 """
3640 Returns the output of the leaders command.
Jon Hall61282e32015-03-19 11:34:11 -07003641 Optional argument:
3642 * jsonFormat - boolean indicating if you want output in json
Jon Hall63604932015-02-26 17:09:50 -08003643 """
Jon Hall63604932015-02-26 17:09:50 -08003644 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003645 cmdStr = "onos:leaders"
Jon Hall61282e32015-03-19 11:34:11 -07003646 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003647 cmdStr += " -j"
3648 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003649 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003650 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003651 return output
Jon Hallc6793552016-01-19 14:18:37 -08003652 except AssertionError:
3653 main.log.exception( "" )
3654 return None
Jon Hall63604932015-02-26 17:09:50 -08003655 except TypeError:
3656 main.log.exception( self.name + ": Object not as expected" )
3657 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003658 except pexpect.EOF:
3659 main.log.error( self.name + ": EOF exception found" )
3660 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003661 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003662 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003663 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003664 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003665
acsmarsa4a4d1e2015-07-10 16:01:24 -07003666 def leaderCandidates( self, jsonFormat=True ):
3667 """
3668 Returns the output of the leaders -c command.
3669 Optional argument:
3670 * jsonFormat - boolean indicating if you want output in json
3671 """
3672 try:
3673 cmdStr = "onos:leaders -c"
3674 if jsonFormat:
3675 cmdStr += " -j"
3676 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003677 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003678 assert "Command not found:" not in output, output
acsmarsa4a4d1e2015-07-10 16:01:24 -07003679 return output
Jon Hallc6793552016-01-19 14:18:37 -08003680 except AssertionError:
3681 main.log.exception( "" )
3682 return None
acsmarsa4a4d1e2015-07-10 16:01:24 -07003683 except TypeError:
3684 main.log.exception( self.name + ": Object not as expected" )
3685 return None
3686 except pexpect.EOF:
3687 main.log.error( self.name + ": EOF exception found" )
3688 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003689 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003690 except Exception:
3691 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003692 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003693
Jon Hallc6793552016-01-19 14:18:37 -08003694 def specificLeaderCandidate( self, topic ):
acsmarsa4a4d1e2015-07-10 16:01:24 -07003695 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003696 Returns a list in format [leader,candidate1,candidate2,...] for a given
acsmarsa4a4d1e2015-07-10 16:01:24 -07003697 topic parameter and an empty list if the topic doesn't exist
3698 If no leader is elected leader in the returned list will be "none"
3699 Returns None if there is a type error processing the json object
3700 """
3701 try:
Jon Hall6e709752016-02-01 13:38:46 -08003702 cmdStr = "onos:leaders -j"
Jon Hallc6793552016-01-19 14:18:37 -08003703 rawOutput = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003704 assert rawOutput is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003705 assert "Command not found:" not in rawOutput, rawOutput
3706 output = json.loads( rawOutput )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003707 results = []
3708 for dict in output:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003709 if dict[ "topic" ] == topic:
3710 leader = dict[ "leader" ]
3711 candidates = re.split( ", ", dict[ "candidates" ][ 1:-1 ] )
Jon Hallc6793552016-01-19 14:18:37 -08003712 results.append( leader )
3713 results.extend( candidates )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003714 return results
Jon Hallc6793552016-01-19 14:18:37 -08003715 except AssertionError:
3716 main.log.exception( "" )
3717 return None
3718 except ( TypeError, ValueError ):
3719 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawOutput ) )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003720 return None
3721 except pexpect.EOF:
3722 main.log.error( self.name + ": EOF exception found" )
3723 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003724 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003725 except Exception:
3726 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003727 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003728
Jon Hall61282e32015-03-19 11:34:11 -07003729 def pendingMap( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003730 """
3731 Returns the output of the intent Pending map.
3732 """
Jon Hall63604932015-02-26 17:09:50 -08003733 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003734 cmdStr = "onos:intents -p"
Jon Hall61282e32015-03-19 11:34:11 -07003735 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003736 cmdStr += " -j"
3737 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003738 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003739 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003740 return output
Jon Hallc6793552016-01-19 14:18:37 -08003741 except AssertionError:
3742 main.log.exception( "" )
3743 return None
Jon Hall63604932015-02-26 17:09:50 -08003744 except TypeError:
3745 main.log.exception( self.name + ": Object not as expected" )
3746 return None
3747 except pexpect.EOF:
3748 main.log.error( self.name + ": EOF exception found" )
3749 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003750 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003751 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003752 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003753 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003754
Jon Hall2c8959e2016-12-16 12:17:34 -08003755 def partitions( self, candidates=False, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003756 """
3757 Returns the output of the raft partitions command for ONOS.
3758 """
Jon Hall61282e32015-03-19 11:34:11 -07003759 # Sample JSON
3760 # {
3761 # "leader": "tcp://10.128.30.11:7238",
3762 # "members": [
3763 # "tcp://10.128.30.11:7238",
3764 # "tcp://10.128.30.17:7238",
3765 # "tcp://10.128.30.13:7238",
3766 # ],
3767 # "name": "p1",
3768 # "term": 3
3769 # },
Jon Hall63604932015-02-26 17:09:50 -08003770 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003771 cmdStr = "onos:partitions"
Jon Hall2c8959e2016-12-16 12:17:34 -08003772 if candidates:
3773 cmdStr += " -c"
Jon Hall61282e32015-03-19 11:34:11 -07003774 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003775 cmdStr += " -j"
3776 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003777 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003778 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003779 return output
Jon Hallc6793552016-01-19 14:18:37 -08003780 except AssertionError:
3781 main.log.exception( "" )
3782 return None
Jon Hall63604932015-02-26 17:09:50 -08003783 except TypeError:
3784 main.log.exception( self.name + ": Object not as expected" )
3785 return None
3786 except pexpect.EOF:
3787 main.log.error( self.name + ": EOF exception found" )
3788 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003789 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003790 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003791 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003792 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003793
Jon Halle9f909e2016-09-23 10:43:12 -07003794 def apps( self, summary=False, active=False, jsonFormat=True ):
Jon Hallbe379602015-03-24 13:39:32 -07003795 """
3796 Returns the output of the apps command for ONOS. This command lists
3797 information about installed ONOS applications
3798 """
3799 # Sample JSON object
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003800 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
Jon Hallbe379602015-03-24 13:39:32 -07003801 # "description":"ONOS OpenFlow protocol southbound providers",
3802 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003803 # "features":"[onos-openflow]","state":"ACTIVE"}]
Jon Hallbe379602015-03-24 13:39:32 -07003804 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003805 cmdStr = "onos:apps"
Jon Hallf03ae762019-01-22 13:25:27 -08003806 expectJson = False
Jon Halle9f909e2016-09-23 10:43:12 -07003807 if summary:
3808 cmdStr += " -s"
3809 if active:
3810 cmdStr += " -a"
Jon Hallbe379602015-03-24 13:39:32 -07003811 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003812 cmdStr += " -j"
Jon Hallf03ae762019-01-22 13:25:27 -08003813 expectJson = True
3814 output = self.sendline( cmdStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07003815 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003816 assert "Command not found:" not in output, output
3817 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003818 return output
Jon Hallbe379602015-03-24 13:39:32 -07003819 # FIXME: look at specific exceptions/Errors
3820 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07003821 main.log.exception( self.name + ": Error in processing onos:app command." )
Jon Hallbe379602015-03-24 13:39:32 -07003822 return None
3823 except TypeError:
3824 main.log.exception( self.name + ": Object not as expected" )
3825 return None
3826 except pexpect.EOF:
3827 main.log.error( self.name + ": EOF exception found" )
3828 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003829 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003830 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003831 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003832 main.cleanAndExit()
Jon Hallbe379602015-03-24 13:39:32 -07003833
You Wangcdc51fe2018-08-12 17:14:56 -07003834 def appStatus( self, appName ):
Jon Hall146f1522015-03-24 15:33:24 -07003835 """
3836 Uses the onos:apps cli command to return the status of an application.
3837 Returns:
3838 "ACTIVE" - If app is installed and activated
3839 "INSTALLED" - If app is installed and deactivated
3840 "UNINSTALLED" - If app is not installed
3841 None - on error
3842 """
Jon Hall146f1522015-03-24 15:33:24 -07003843 try:
3844 if not isinstance( appName, types.StringType ):
3845 main.log.error( self.name + ".appStatus(): appName must be" +
3846 " a string" )
3847 return None
3848 output = self.apps( jsonFormat=True )
3849 appsJson = json.loads( output )
3850 state = None
3851 for app in appsJson:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003852 if appName == app.get( 'name' ):
3853 state = app.get( 'state' )
Jon Hall146f1522015-03-24 15:33:24 -07003854 break
3855 if state == "ACTIVE" or state == "INSTALLED":
3856 return state
3857 elif state is None:
You Wang0d9f2c02018-08-10 14:56:32 -07003858 main.log.warn( "{} app not found".format( appName ) )
Jon Hall146f1522015-03-24 15:33:24 -07003859 return "UNINSTALLED"
3860 elif state:
3861 main.log.error( "Unexpected state from 'onos:apps': " +
3862 str( state ) )
3863 return state
Jon Hallc6793552016-01-19 14:18:37 -08003864 except ( TypeError, ValueError ):
3865 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003866 return None
3867 except pexpect.EOF:
3868 main.log.error( self.name + ": EOF exception found" )
3869 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003870 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003871 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003872 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003873 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003874
Jon Hallbe379602015-03-24 13:39:32 -07003875 def app( self, appName, option ):
3876 """
3877 Interacts with the app command for ONOS. This command manages
3878 application inventory.
3879 """
Jon Hallbe379602015-03-24 13:39:32 -07003880 try:
Jon Hallbd16b922015-03-26 17:53:15 -07003881 # Validate argument types
3882 valid = True
3883 if not isinstance( appName, types.StringType ):
3884 main.log.error( self.name + ".app(): appName must be a " +
3885 "string" )
3886 valid = False
3887 if not isinstance( option, types.StringType ):
3888 main.log.error( self.name + ".app(): option must be a string" )
3889 valid = False
3890 if not valid:
3891 return main.FALSE
3892 # Validate Option
3893 option = option.lower()
3894 # NOTE: Install may become a valid option
3895 if option == "activate":
3896 pass
3897 elif option == "deactivate":
3898 pass
3899 elif option == "uninstall":
3900 pass
3901 else:
3902 # Invalid option
3903 main.log.error( "The ONOS app command argument only takes " +
3904 "the values: (activate|deactivate|uninstall)" +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003905 "; was given '" + option + "'" )
Jon Hallbd16b922015-03-26 17:53:15 -07003906 return main.FALSE
Jon Hall146f1522015-03-24 15:33:24 -07003907 cmdStr = "onos:app " + option + " " + appName
Jon Hallbe379602015-03-24 13:39:32 -07003908 output = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003909 assert output is not None, "Error in sendline"
3910 assert "Command not found:" not in output, output
Jon Hallbe379602015-03-24 13:39:32 -07003911 if "Error executing command" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003912 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hallbe379602015-03-24 13:39:32 -07003913 str( output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003914 return main.FALSE
Jon Hallbe379602015-03-24 13:39:32 -07003915 elif "No such application" in output:
3916 main.log.error( "The application '" + appName +
3917 "' is not installed in ONOS" )
Jon Hall146f1522015-03-24 15:33:24 -07003918 return main.FALSE
3919 elif "Command not found:" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003920 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hall146f1522015-03-24 15:33:24 -07003921 str( output ) )
3922 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003923 elif "Unsupported command:" in output:
3924 main.log.error( "Incorrect command given to 'app': " +
3925 str( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003926 # NOTE: we may need to add more checks here
Jon Hallbd16b922015-03-26 17:53:15 -07003927 # else: Command was successful
Jon Hall08f61bc2015-04-13 16:00:30 -07003928 # main.log.debug( "app response: " + repr( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003929 return main.TRUE
You Wangb5a55f72017-03-03 12:51:05 -08003930 except AssertionError:
3931 main.log.exception( self.name + ": AssertionError exception found" )
3932 return main.ERROR
Jon Hallbe379602015-03-24 13:39:32 -07003933 except TypeError:
3934 main.log.exception( self.name + ": Object not as expected" )
3935 return main.ERROR
3936 except pexpect.EOF:
3937 main.log.error( self.name + ": EOF exception found" )
3938 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003939 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003940 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003941 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003942 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003943
Jon Hallbd16b922015-03-26 17:53:15 -07003944 def activateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003945 """
3946 Activate an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003947 appName is the hierarchical app name, not the feature name
3948 If check is True, method will check the status of the app after the
3949 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003950 Returns main.TRUE if the command was successfully sent
3951 main.FALSE if the cli responded with an error or given
3952 incorrect input
3953 """
3954 try:
3955 if not isinstance( appName, types.StringType ):
3956 main.log.error( self.name + ".activateApp(): appName must be" +
3957 " a string" )
3958 return main.FALSE
3959 status = self.appStatus( appName )
3960 if status == "INSTALLED":
3961 response = self.app( appName, "activate" )
Jon Hallbd16b922015-03-26 17:53:15 -07003962 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003963 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07003964 status = self.appStatus( appName )
3965 if status == "ACTIVE":
3966 return main.TRUE
3967 else:
Jon Hall050e1bd2015-03-30 13:33:02 -07003968 main.log.debug( "The state of application " +
3969 appName + " is " + status )
Jon Hallbd16b922015-03-26 17:53:15 -07003970 time.sleep( 1 )
3971 return main.FALSE
3972 else: # not 'check' or command didn't succeed
3973 return response
Jon Hall146f1522015-03-24 15:33:24 -07003974 elif status == "ACTIVE":
3975 return main.TRUE
3976 elif status == "UNINSTALLED":
3977 main.log.error( self.name + ": Tried to activate the " +
3978 "application '" + appName + "' which is not " +
3979 "installed." )
3980 else:
3981 main.log.error( "Unexpected return value from appStatus: " +
3982 str( status ) )
3983 return main.ERROR
3984 except TypeError:
3985 main.log.exception( self.name + ": Object not as expected" )
3986 return main.ERROR
3987 except pexpect.EOF:
3988 main.log.error( self.name + ": EOF exception found" )
3989 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003990 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003991 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003992 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003993 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003994
Jon Hallbd16b922015-03-26 17:53:15 -07003995 def deactivateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003996 """
3997 Deactivate an app that is already activated in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003998 appName is the hierarchical app name, not the feature name
3999 If check is True, method will check the status of the app after the
4000 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004001 Returns main.TRUE if the command was successfully sent
4002 main.FALSE if the cli responded with an error or given
4003 incorrect input
4004 """
4005 try:
4006 if not isinstance( appName, types.StringType ):
4007 main.log.error( self.name + ".deactivateApp(): appName must " +
4008 "be a string" )
4009 return main.FALSE
4010 status = self.appStatus( appName )
4011 if status == "INSTALLED":
4012 return main.TRUE
4013 elif status == "ACTIVE":
4014 response = self.app( appName, "deactivate" )
Jon Hallbd16b922015-03-26 17:53:15 -07004015 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004016 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004017 status = self.appStatus( appName )
4018 if status == "INSTALLED":
4019 return main.TRUE
4020 else:
4021 time.sleep( 1 )
4022 return main.FALSE
4023 else: # not check or command didn't succeed
4024 return response
Jon Hall146f1522015-03-24 15:33:24 -07004025 elif status == "UNINSTALLED":
4026 main.log.warn( self.name + ": Tried to deactivate the " +
4027 "application '" + appName + "' which is not " +
4028 "installed." )
4029 return main.TRUE
4030 else:
4031 main.log.error( "Unexpected return value from appStatus: " +
4032 str( status ) )
4033 return main.ERROR
4034 except TypeError:
4035 main.log.exception( self.name + ": Object not as expected" )
4036 return main.ERROR
4037 except pexpect.EOF:
4038 main.log.error( self.name + ": EOF exception found" )
4039 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004040 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004041 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004042 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004043 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004044
Jon Hallbd16b922015-03-26 17:53:15 -07004045 def uninstallApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004046 """
4047 Uninstall an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004048 appName is the hierarchical app name, not the feature name
4049 If check is True, method will check the status of the app after the
4050 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004051 Returns main.TRUE if the command was successfully sent
4052 main.FALSE if the cli responded with an error or given
4053 incorrect input
4054 """
4055 # TODO: check with Thomas about the state machine for apps
4056 try:
4057 if not isinstance( appName, types.StringType ):
4058 main.log.error( self.name + ".uninstallApp(): appName must " +
4059 "be a string" )
4060 return main.FALSE
4061 status = self.appStatus( appName )
4062 if status == "INSTALLED":
4063 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004064 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004065 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004066 status = self.appStatus( appName )
4067 if status == "UNINSTALLED":
4068 return main.TRUE
4069 else:
4070 time.sleep( 1 )
4071 return main.FALSE
4072 else: # not check or command didn't succeed
4073 return response
Jon Hall146f1522015-03-24 15:33:24 -07004074 elif status == "ACTIVE":
4075 main.log.warn( self.name + ": Tried to uninstall the " +
4076 "application '" + appName + "' which is " +
4077 "currently active." )
4078 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004079 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004080 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004081 status = self.appStatus( appName )
4082 if status == "UNINSTALLED":
4083 return main.TRUE
4084 else:
4085 time.sleep( 1 )
4086 return main.FALSE
4087 else: # not check or command didn't succeed
4088 return response
Jon Hall146f1522015-03-24 15:33:24 -07004089 elif status == "UNINSTALLED":
4090 return main.TRUE
4091 else:
4092 main.log.error( "Unexpected return value from appStatus: " +
4093 str( status ) )
4094 return main.ERROR
4095 except TypeError:
4096 main.log.exception( self.name + ": Object not as expected" )
4097 return main.ERROR
4098 except pexpect.EOF:
4099 main.log.error( self.name + ": EOF exception found" )
4100 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004101 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004102 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004103 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004104 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004105
4106 def appIDs( self, jsonFormat=True ):
4107 """
4108 Show the mappings between app id and app names given by the 'app-ids'
4109 cli command
4110 """
4111 try:
4112 cmdStr = "app-ids"
4113 if jsonFormat:
4114 cmdStr += " -j"
Jon Hallc6358dd2015-04-10 12:44:28 -07004115 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004116 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004117 assert "Command not found:" not in output, output
4118 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07004119 return output
Jon Hallbd16b922015-03-26 17:53:15 -07004120 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004121 main.log.exception( self.name + ": Error in processing onos:app-ids command." )
Jon Hallbd16b922015-03-26 17:53:15 -07004122 return None
4123 except TypeError:
4124 main.log.exception( self.name + ": Object not as expected" )
4125 return None
4126 except pexpect.EOF:
4127 main.log.error( self.name + ": EOF exception found" )
4128 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004129 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004130 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004131 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004132 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004133
4134 def appToIDCheck( self ):
4135 """
4136 This method will check that each application's ID listed in 'apps' is
4137 the same as the ID listed in 'app-ids'. The check will also check that
4138 there are no duplicate IDs issued. Note that an app ID should be
4139 a globaly unique numerical identifier for app/app-like features. Once
4140 an ID is registered, the ID is never freed up so that if an app is
4141 reinstalled it will have the same ID.
4142
4143 Returns: main.TRUE if the check passes and
4144 main.FALSE if the check fails or
4145 main.ERROR if there is some error in processing the test
4146 """
4147 try:
Jon Hall0e240372018-05-02 11:21:57 -07004148 # Grab IDs
Jon Hallc6793552016-01-19 14:18:37 -08004149 rawJson = self.appIDs( jsonFormat=True )
4150 if rawJson:
4151 ids = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004152 else:
Jon Hall0e240372018-05-02 11:21:57 -07004153 main.log.error( "app-ids returned nothing: " + repr( rawJson ) )
4154 return main.FALSE
4155
4156 # Grab Apps
Jon Hallc6793552016-01-19 14:18:37 -08004157 rawJson = self.apps( jsonFormat=True )
4158 if rawJson:
4159 apps = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004160 else:
Jon Hallc6793552016-01-19 14:18:37 -08004161 main.log.error( "apps returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07004162 return main.FALSE
Jon Hall0e240372018-05-02 11:21:57 -07004163
Jon Hallbd16b922015-03-26 17:53:15 -07004164 result = main.TRUE
4165 for app in apps:
4166 appID = app.get( 'id' )
4167 if appID is None:
4168 main.log.error( "Error parsing app: " + str( app ) )
4169 result = main.FALSE
4170 appName = app.get( 'name' )
4171 if appName is None:
4172 main.log.error( "Error parsing app: " + str( app ) )
4173 result = main.FALSE
4174 # get the entry in ids that has the same appID
Jon Hall390696c2015-05-05 17:13:41 -07004175 current = filter( lambda item: item[ 'id' ] == appID, ids )
Jon Hallbd16b922015-03-26 17:53:15 -07004176 if not current: # if ids doesn't have this id
4177 result = main.FALSE
4178 main.log.error( "'app-ids' does not have the ID for " +
4179 str( appName ) + " that apps does." )
Jon Hallb9d381e2018-02-05 12:02:10 -08004180 main.log.debug( "apps command returned: " + str( app ) +
4181 "; app-ids has: " + str( ids ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004182 elif len( current ) > 1:
4183 # there is more than one app with this ID
4184 result = main.FALSE
4185 # We will log this later in the method
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004186 elif not current[ 0 ][ 'name' ] == appName:
4187 currentName = current[ 0 ][ 'name' ]
Jon Hallbd16b922015-03-26 17:53:15 -07004188 result = main.FALSE
4189 main.log.error( "'app-ids' has " + str( currentName ) +
4190 " registered under id:" + str( appID ) +
4191 " but 'apps' has " + str( appName ) )
4192 else:
4193 pass # id and name match!
Jon Hall0e240372018-05-02 11:21:57 -07004194
Jon Hallbd16b922015-03-26 17:53:15 -07004195 # now make sure that app-ids has no duplicates
4196 idsList = []
4197 namesList = []
4198 for item in ids:
4199 idsList.append( item[ 'id' ] )
4200 namesList.append( item[ 'name' ] )
4201 if len( idsList ) != len( set( idsList ) ) or\
4202 len( namesList ) != len( set( namesList ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004203 main.log.error( "'app-ids' has some duplicate entries: \n"
4204 + json.dumps( ids,
4205 sort_keys=True,
4206 indent=4,
4207 separators=( ',', ': ' ) ) )
4208 result = main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07004209 return result
Jon Hallc6793552016-01-19 14:18:37 -08004210 except ( TypeError, ValueError ):
4211 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004212 return main.ERROR
4213 except pexpect.EOF:
4214 main.log.error( self.name + ": EOF exception found" )
4215 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004216 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004217 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004218 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004219 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004220
Jon Hallfb760a02015-04-13 15:35:03 -07004221 def getCfg( self, component=None, propName=None, short=False,
4222 jsonFormat=True ):
4223 """
4224 Get configuration settings from onos cli
4225 Optional arguments:
4226 component - Optionally only list configurations for a specific
4227 component. If None, all components with configurations
4228 are displayed. Case Sensitive string.
4229 propName - If component is specified, propName option will show
4230 only this specific configuration from that component.
4231 Case Sensitive string.
4232 jsonFormat - Returns output as json. Note that this will override
4233 the short option
4234 short - Short, less verbose, version of configurations.
4235 This is overridden by the json option
4236 returns:
4237 Output from cli as a string or None on error
4238 """
4239 try:
4240 baseStr = "cfg"
4241 cmdStr = " get"
4242 componentStr = ""
4243 if component:
4244 componentStr += " " + component
4245 if propName:
4246 componentStr += " " + propName
4247 if jsonFormat:
4248 baseStr += " -j"
Jon Hall22e94ce2019-01-15 14:52:17 -08004249 expectJson = True
Jon Hallfb760a02015-04-13 15:35:03 -07004250 elif short:
4251 baseStr += " -s"
Jon Hall22e94ce2019-01-15 14:52:17 -08004252 expectJson = False
4253 output = self.sendline( baseStr + cmdStr + componentStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07004254 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004255 assert "Command not found:" not in output, output
4256 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004257 return output
4258 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004259 main.log.exception( self.name + ": Error in processing 'cfg get' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004260 return None
4261 except TypeError:
4262 main.log.exception( self.name + ": Object not as expected" )
4263 return None
4264 except pexpect.EOF:
4265 main.log.error( self.name + ": EOF exception found" )
4266 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004267 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004268 except Exception:
4269 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004270 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004271
4272 def setCfg( self, component, propName, value=None, check=True ):
4273 """
4274 Set/Unset configuration settings from ONOS cli
Jon Hall390696c2015-05-05 17:13:41 -07004275 Required arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004276 component - The case sensitive name of the component whose
4277 property is to be set
4278 propName - The case sensitive name of the property to be set/unset
Jon Hall390696c2015-05-05 17:13:41 -07004279 Optional arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004280 value - The value to set the property to. If None, will unset the
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004281 property and revert it to it's default value(if applicable)
Jon Hallfb760a02015-04-13 15:35:03 -07004282 check - Boolean, Check whether the option was successfully set this
4283 only applies when a value is given.
4284 returns:
4285 main.TRUE on success or main.FALSE on failure. If check is False,
4286 will return main.TRUE unless there is an error
4287 """
4288 try:
4289 baseStr = "cfg"
4290 cmdStr = " set " + str( component ) + " " + str( propName )
4291 if value is not None:
4292 cmdStr += " " + str( value )
4293 output = self.sendline( baseStr + cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004294 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004295 assert "Command not found:" not in output, output
4296 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004297 if value and check:
4298 results = self.getCfg( component=str( component ),
4299 propName=str( propName ),
4300 jsonFormat=True )
4301 # Check if current value is what we just set
4302 try:
4303 jsonOutput = json.loads( results )
4304 current = jsonOutput[ 'value' ]
Jon Hallc6793552016-01-19 14:18:37 -08004305 except ( TypeError, ValueError ):
Jon Hallfb760a02015-04-13 15:35:03 -07004306 main.log.exception( "Error parsing cfg output" )
4307 main.log.error( "output:" + repr( results ) )
4308 return main.FALSE
4309 if current == str( value ):
4310 return main.TRUE
4311 return main.FALSE
4312 return main.TRUE
4313 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004314 main.log.exception( self.name + ": Error in processing 'cfg set' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004315 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08004316 except ( TypeError, ValueError ):
4317 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, results ) )
Jon Hallfb760a02015-04-13 15:35:03 -07004318 return main.FALSE
4319 except pexpect.EOF:
4320 main.log.error( self.name + ": EOF exception found" )
4321 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004322 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004323 except Exception:
4324 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004325 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004326
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004327 def distPrimitivesSend( self, cmd ):
4328 """
4329 Function to handle sending cli commands for the distributed primitives test app
4330
4331 This command will catch some exceptions and retry the command on some
4332 specific store exceptions.
4333
4334 Required arguments:
4335 cmd - The command to send to the cli
4336 returns:
4337 string containing the cli output
4338 None on Error
4339 """
4340 try:
4341 output = self.sendline( cmd )
4342 try:
4343 assert output is not None, "Error in sendline"
4344 # TODO: Maybe make this less hardcoded
4345 # ConsistentMap Exceptions
4346 assert "org.onosproject.store.service" not in output
4347 # Node not leader
4348 assert "java.lang.IllegalStateException" not in output
4349 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004350 main.log.error( self.name + ": Error in processing '" + cmd + "' " +
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004351 "command: " + str( output ) )
4352 retryTime = 30 # Conservative time, given by Madan
4353 main.log.info( "Waiting " + str( retryTime ) +
4354 "seconds before retrying." )
4355 time.sleep( retryTime ) # Due to change in mastership
4356 output = self.sendline( cmd )
4357 assert output is not None, "Error in sendline"
4358 assert "Command not found:" not in output, output
4359 assert "Error executing command" not in output, output
4360 main.log.info( self.name + ": " + output )
4361 return output
4362 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004363 main.log.exception( self.name + ": Error in processing '" + cmd + "' command." )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004364 return None
4365 except TypeError:
4366 main.log.exception( self.name + ": Object not as expected" )
4367 return None
4368 except pexpect.EOF:
4369 main.log.error( self.name + ": EOF exception found" )
4370 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004371 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004372 except Exception:
4373 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004374 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004375
Jon Hall390696c2015-05-05 17:13:41 -07004376 def setTestAdd( self, setName, values ):
4377 """
4378 CLI command to add elements to a distributed set.
4379 Arguments:
4380 setName - The name of the set to add to.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004381 values - The value(s) to add to the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004382 Example usages:
4383 setTestAdd( "set1", "a b c" )
4384 setTestAdd( "set2", "1" )
4385 returns:
4386 main.TRUE on success OR
4387 main.FALSE if elements were already in the set OR
4388 main.ERROR on error
4389 """
4390 try:
4391 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004392 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004393 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
4394 negativeMatch = "\[(.*)\] was already in set " + str( setName )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004395 if re.search( positiveMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004396 return main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004397 elif re.search( negativeMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004398 return main.FALSE
4399 else:
4400 main.log.error( self.name + ": setTestAdd did not" +
4401 " match expected output" )
Jon Hall390696c2015-05-05 17:13:41 -07004402 main.log.debug( self.name + " actual: " + repr( output ) )
4403 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004404 except TypeError:
4405 main.log.exception( self.name + ": Object not as expected" )
4406 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004407 except Exception:
4408 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004409 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004410
4411 def setTestRemove( self, setName, values, clear=False, retain=False ):
4412 """
4413 CLI command to remove elements from a distributed set.
4414 Required arguments:
4415 setName - The name of the set to remove from.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004416 values - The value(s) to remove from the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004417 Optional arguments:
4418 clear - Clear all elements from the set
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004419 retain - Retain only the given values. (intersection of the
4420 original set and the given set)
Jon Hall390696c2015-05-05 17:13:41 -07004421 returns:
4422 main.TRUE on success OR
4423 main.FALSE if the set was not changed OR
4424 main.ERROR on error
4425 """
4426 try:
4427 cmdStr = "set-test-remove "
4428 if clear:
4429 cmdStr += "-c " + str( setName )
4430 elif retain:
4431 cmdStr += "-r " + str( setName ) + " " + str( values )
4432 else:
4433 cmdStr += str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004434 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004435 if clear:
4436 pattern = "Set " + str( setName ) + " cleared"
4437 if re.search( pattern, output ):
4438 return main.TRUE
4439 elif retain:
4440 positivePattern = str( setName ) + " was pruned to contain " +\
4441 "only elements of set \[(.*)\]"
4442 negativePattern = str( setName ) + " was not changed by " +\
4443 "retaining only elements of the set " +\
4444 "\[(.*)\]"
4445 if re.search( positivePattern, output ):
4446 return main.TRUE
4447 elif re.search( negativePattern, output ):
4448 return main.FALSE
4449 else:
4450 positivePattern = "\[(.*)\] was removed from the set " +\
4451 str( setName )
4452 if ( len( values.split() ) == 1 ):
4453 negativePattern = "\[(.*)\] was not in set " +\
4454 str( setName )
4455 else:
4456 negativePattern = "No element of \[(.*)\] was in set " +\
4457 str( setName )
4458 if re.search( positivePattern, output ):
4459 return main.TRUE
4460 elif re.search( negativePattern, output ):
4461 return main.FALSE
4462 main.log.error( self.name + ": setTestRemove did not" +
4463 " match expected output" )
4464 main.log.debug( self.name + " expected: " + pattern )
4465 main.log.debug( self.name + " actual: " + repr( output ) )
4466 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004467 except TypeError:
4468 main.log.exception( self.name + ": Object not as expected" )
4469 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004470 except Exception:
4471 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004472 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004473
4474 def setTestGet( self, setName, values="" ):
4475 """
4476 CLI command to get the elements in a distributed set.
4477 Required arguments:
4478 setName - The name of the set to remove from.
4479 Optional arguments:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004480 values - The value(s) to check if in the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004481 returns:
4482 main.ERROR on error OR
4483 A list of elements in the set if no optional arguments are
4484 supplied OR
4485 A tuple containing the list then:
4486 main.FALSE if the given values are not in the set OR
4487 main.TRUE if the given values are in the set OR
4488 """
4489 try:
4490 values = str( values ).strip()
4491 setName = str( setName ).strip()
4492 length = len( values.split() )
4493 containsCheck = None
4494 # Patterns to match
4495 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004496 pattern = "Items in set " + setName + ":\r\n" + setPattern
Jon Hall390696c2015-05-05 17:13:41 -07004497 containsTrue = "Set " + setName + " contains the value " + values
4498 containsFalse = "Set " + setName + " did not contain the value " +\
4499 values
4500 containsAllTrue = "Set " + setName + " contains the the subset " +\
4501 setPattern
4502 containsAllFalse = "Set " + setName + " did not contain the the" +\
4503 " subset " + setPattern
4504
4505 cmdStr = "set-test-get "
4506 cmdStr += setName + " " + values
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004507 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004508 if length == 0:
4509 match = re.search( pattern, output )
4510 else: # if given values
4511 if length == 1: # Contains output
Jon Hall54b994f2016-12-05 10:48:59 -08004512 patternTrue = pattern + "\r\n" + containsTrue
4513 patternFalse = pattern + "\r\n" + containsFalse
Jon Hall390696c2015-05-05 17:13:41 -07004514 else: # ContainsAll output
Jon Hall54b994f2016-12-05 10:48:59 -08004515 patternTrue = pattern + "\r\n" + containsAllTrue
4516 patternFalse = pattern + "\r\n" + containsAllFalse
Jon Hall390696c2015-05-05 17:13:41 -07004517 matchTrue = re.search( patternTrue, output )
4518 matchFalse = re.search( patternFalse, output )
4519 if matchTrue:
4520 containsCheck = main.TRUE
4521 match = matchTrue
4522 elif matchFalse:
4523 containsCheck = main.FALSE
4524 match = matchFalse
4525 else:
Jon Halle0f0b342017-04-18 11:43:47 -07004526 main.log.error( self.name + " setTestGet did not match " +
Jon Hall390696c2015-05-05 17:13:41 -07004527 "expected output" )
4528 main.log.debug( self.name + " expected: " + pattern )
4529 main.log.debug( self.name + " actual: " + repr( output ) )
4530 match = None
4531 if match:
4532 setMatch = match.group( 1 )
4533 if setMatch == '':
4534 setList = []
4535 else:
4536 setList = setMatch.split( ", " )
4537 if length > 0:
4538 return ( setList, containsCheck )
4539 else:
4540 return setList
4541 else: # no match
4542 main.log.error( self.name + ": setTestGet did not" +
4543 " match expected output" )
4544 main.log.debug( self.name + " expected: " + pattern )
4545 main.log.debug( self.name + " actual: " + repr( output ) )
4546 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004547 except TypeError:
4548 main.log.exception( self.name + ": Object not as expected" )
4549 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004550 except Exception:
4551 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004552 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004553
4554 def setTestSize( self, setName ):
4555 """
4556 CLI command to get the elements in a distributed set.
4557 Required arguments:
4558 setName - The name of the set to remove from.
4559 returns:
Jon Hallfeff3082015-05-19 10:23:26 -07004560 The integer value of the size returned or
Jon Hall390696c2015-05-05 17:13:41 -07004561 None on error
4562 """
4563 try:
4564 # TODO: Should this check against the number of elements returned
4565 # and then return true/false based on that?
4566 setName = str( setName ).strip()
4567 # Patterns to match
4568 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004569 pattern = "There are (\d+) items in set " + setName + ":\r\n" +\
Jon Hall390696c2015-05-05 17:13:41 -07004570 setPattern
4571 cmdStr = "set-test-get -s "
4572 cmdStr += setName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004573 output = self.distPrimitivesSend( cmdStr )
Jon Hall0e240372018-05-02 11:21:57 -07004574 if output:
4575 match = re.search( pattern, output )
4576 if match:
4577 setSize = int( match.group( 1 ) )
4578 setMatch = match.group( 2 )
4579 if len( setMatch.split() ) == setSize:
4580 main.log.info( "The size returned by " + self.name +
4581 " matches the number of elements in " +
4582 "the returned set" )
4583 else:
4584 main.log.error( "The size returned by " + self.name +
4585 " does not match the number of " +
4586 "elements in the returned set." )
4587 return setSize
Jon Hall390696c2015-05-05 17:13:41 -07004588 else: # no match
4589 main.log.error( self.name + ": setTestGet did not" +
4590 " match expected output" )
4591 main.log.debug( self.name + " expected: " + pattern )
4592 main.log.debug( self.name + " actual: " + repr( output ) )
4593 return None
Jon Hall390696c2015-05-05 17:13:41 -07004594 except TypeError:
4595 main.log.exception( self.name + ": Object not as expected" )
4596 return None
Jon Hall390696c2015-05-05 17:13:41 -07004597 except Exception:
4598 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004599 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004600
Jon Hall80daded2015-05-27 16:07:00 -07004601 def counters( self, jsonFormat=True ):
Jon Hall390696c2015-05-05 17:13:41 -07004602 """
4603 Command to list the various counters in the system.
4604 returns:
Jon Hall80daded2015-05-27 16:07:00 -07004605 if jsonFormat, a string of the json object returned by the cli
4606 command
4607 if not jsonFormat, the normal string output of the cli command
Jon Hall390696c2015-05-05 17:13:41 -07004608 None on error
4609 """
Jon Hall390696c2015-05-05 17:13:41 -07004610 try:
Jon Hall390696c2015-05-05 17:13:41 -07004611 cmdStr = "counters"
Jon Hall80daded2015-05-27 16:07:00 -07004612 if jsonFormat:
4613 cmdStr += " -j"
Jon Hall390696c2015-05-05 17:13:41 -07004614 output = self.sendline( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004615 main.log.debug( self.name + ": Counters unparsed: " + output )
4616 output = output.split( "\r\n" )[ -1 ]
4617 main.log.debug( self.name + ": Counters parsed: " + output )
Jon Halla495f562016-05-16 18:03:26 -07004618 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004619 assert "Command not found:" not in output, output
4620 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004621 main.log.info( self.name + ": " + output )
Jon Hall80daded2015-05-27 16:07:00 -07004622 return output
Jon Hall390696c2015-05-05 17:13:41 -07004623 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004624 main.log.exception( self.name + ": Error in processing 'counters' command." )
Jon Hall80daded2015-05-27 16:07:00 -07004625 return None
Jon Hall390696c2015-05-05 17:13:41 -07004626 except TypeError:
4627 main.log.exception( self.name + ": Object not as expected" )
Jon Hall80daded2015-05-27 16:07:00 -07004628 return None
Jon Hall390696c2015-05-05 17:13:41 -07004629 except pexpect.EOF:
4630 main.log.error( self.name + ": EOF exception found" )
4631 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004632 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004633 except Exception:
4634 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004635 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004636
Jon Hall935db192016-04-19 00:22:04 -07004637 def counterTestAddAndGet( self, counter, delta=1 ):
Jon Hall390696c2015-05-05 17:13:41 -07004638 """
Jon Halle1a3b752015-07-22 13:02:46 -07004639 CLI command to add a delta to then get a distributed counter.
Jon Hall390696c2015-05-05 17:13:41 -07004640 Required arguments:
4641 counter - The name of the counter to increment.
4642 Optional arguments:
Jon Halle1a3b752015-07-22 13:02:46 -07004643 delta - The long to add to the counter
Jon Hall390696c2015-05-05 17:13:41 -07004644 returns:
4645 integer value of the counter or
4646 None on Error
4647 """
4648 try:
4649 counter = str( counter )
Jon Halle1a3b752015-07-22 13:02:46 -07004650 delta = int( delta )
Jon Hall390696c2015-05-05 17:13:41 -07004651 cmdStr = "counter-test-increment "
Jon Hall390696c2015-05-05 17:13:41 -07004652 cmdStr += counter
Jon Halle1a3b752015-07-22 13:02:46 -07004653 if delta != 1:
4654 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004655 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004656 pattern = counter + " was updated to (-?\d+)"
Jon Hall390696c2015-05-05 17:13:41 -07004657 match = re.search( pattern, output )
4658 if match:
4659 return int( match.group( 1 ) )
4660 else:
Jon Halle1a3b752015-07-22 13:02:46 -07004661 main.log.error( self.name + ": counterTestAddAndGet did not" +
Jon Hall390696c2015-05-05 17:13:41 -07004662 " match expected output." )
4663 main.log.debug( self.name + " expected: " + pattern )
4664 main.log.debug( self.name + " actual: " + repr( output ) )
4665 return None
Jon Hall390696c2015-05-05 17:13:41 -07004666 except TypeError:
4667 main.log.exception( self.name + ": Object not as expected" )
4668 return None
Jon Hall390696c2015-05-05 17:13:41 -07004669 except Exception:
4670 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004671 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004672
Jon Hall935db192016-04-19 00:22:04 -07004673 def counterTestGetAndAdd( self, counter, delta=1 ):
Jon Halle1a3b752015-07-22 13:02:46 -07004674 """
4675 CLI command to get a distributed counter then add a delta to it.
4676 Required arguments:
4677 counter - The name of the counter to increment.
4678 Optional arguments:
4679 delta - The long to add to the counter
Jon Halle1a3b752015-07-22 13:02:46 -07004680 returns:
4681 integer value of the counter or
4682 None on Error
4683 """
4684 try:
4685 counter = str( counter )
4686 delta = int( delta )
4687 cmdStr = "counter-test-increment -g "
Jon Halle1a3b752015-07-22 13:02:46 -07004688 cmdStr += counter
4689 if delta != 1:
4690 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004691 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004692 pattern = counter + " was updated to (-?\d+)"
4693 match = re.search( pattern, output )
4694 if match:
4695 return int( match.group( 1 ) )
4696 else:
4697 main.log.error( self.name + ": counterTestGetAndAdd did not" +
4698 " match expected output." )
4699 main.log.debug( self.name + " expected: " + pattern )
4700 main.log.debug( self.name + " actual: " + repr( output ) )
4701 return None
Jon Halle1a3b752015-07-22 13:02:46 -07004702 except TypeError:
4703 main.log.exception( self.name + ": Object not as expected" )
4704 return None
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004705 except Exception:
4706 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004707 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004708
4709 def valueTestGet( self, valueName ):
4710 """
4711 CLI command to get the value of an atomic value.
4712 Required arguments:
4713 valueName - The name of the value to get.
4714 returns:
4715 string value of the value or
4716 None on Error
4717 """
4718 try:
4719 valueName = str( valueName )
4720 cmdStr = "value-test "
4721 operation = "get"
4722 cmdStr = "value-test {} {}".format( valueName,
4723 operation )
4724 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004725 main.log.debug( self.name + ": value test unparsed: " + output )
4726 output = output.split( "\r\n" )[ -1 ]
4727 main.log.debug( self.name + ": value test parsed: " + output )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004728 pattern = "(\w+)"
4729 match = re.search( pattern, output )
4730 if match:
4731 return match.group( 1 )
4732 else:
4733 main.log.error( self.name + ": valueTestGet did not" +
4734 " match expected output." )
4735 main.log.debug( self.name + " expected: " + pattern )
4736 main.log.debug( self.name + " actual: " + repr( output ) )
4737 return None
4738 except TypeError:
4739 main.log.exception( self.name + ": Object not as expected" )
4740 return None
4741 except Exception:
4742 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004743 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004744
4745 def valueTestSet( self, valueName, newValue ):
4746 """
4747 CLI command to set the value of an atomic value.
4748 Required arguments:
4749 valueName - The name of the value to set.
4750 newValue - The value to assign to the given value.
4751 returns:
4752 main.TRUE on success or
4753 main.ERROR on Error
4754 """
4755 try:
4756 valueName = str( valueName )
4757 newValue = str( newValue )
4758 operation = "set"
4759 cmdStr = "value-test {} {} {}".format( valueName,
4760 operation,
4761 newValue )
4762 output = self.distPrimitivesSend( cmdStr )
4763 if output is not None:
4764 return main.TRUE
4765 else:
4766 return main.ERROR
4767 except TypeError:
4768 main.log.exception( self.name + ": Object not as expected" )
4769 return main.ERROR
4770 except Exception:
4771 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004772 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004773
4774 def valueTestCompareAndSet( self, valueName, oldValue, newValue ):
4775 """
4776 CLI command to compareAndSet the value of an atomic value.
4777 Required arguments:
4778 valueName - The name of the value.
4779 oldValue - Compare the current value of the atomic value to this
4780 newValue - If the value equals oldValue, set the value to newValue
4781 returns:
4782 main.TRUE on success or
4783 main.FALSE on failure or
4784 main.ERROR on Error
4785 """
4786 try:
4787 valueName = str( valueName )
4788 oldValue = str( oldValue )
4789 newValue = str( newValue )
4790 operation = "compareAndSet"
4791 cmdStr = "value-test {} {} {} {}".format( valueName,
4792 operation,
4793 oldValue,
4794 newValue )
4795 output = self.distPrimitivesSend( cmdStr )
4796 pattern = "(\w+)"
4797 match = re.search( pattern, output )
4798 if match:
4799 result = match.group( 1 )
4800 if result == "true":
4801 return main.TRUE
4802 elif result == "false":
4803 return main.FALSE
4804 else:
4805 main.log.error( self.name + ": valueTestCompareAndSet did not" +
4806 " match expected output." )
4807 main.log.debug( self.name + " expected: " + pattern )
4808 main.log.debug( self.name + " actual: " + repr( output ) )
4809 return main.ERROR
4810 except TypeError:
4811 main.log.exception( self.name + ": Object not as expected" )
4812 return main.ERROR
4813 except Exception:
4814 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004815 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004816
4817 def valueTestGetAndSet( self, valueName, newValue ):
4818 """
4819 CLI command to getAndSet the value of an atomic value.
4820 Required arguments:
4821 valueName - The name of the value to get.
4822 newValue - The value to assign to the given value
4823 returns:
4824 string value of the value or
4825 None on Error
4826 """
4827 try:
4828 valueName = str( valueName )
4829 cmdStr = "value-test "
4830 operation = "getAndSet"
4831 cmdStr += valueName + " " + operation
4832 cmdStr = "value-test {} {} {}".format( valueName,
4833 operation,
4834 newValue )
4835 output = self.distPrimitivesSend( cmdStr )
4836 pattern = "(\w+)"
4837 match = re.search( pattern, output )
4838 if match:
4839 return match.group( 1 )
4840 else:
4841 main.log.error( self.name + ": valueTestGetAndSet did not" +
4842 " match expected output." )
4843 main.log.debug( self.name + " expected: " + pattern )
4844 main.log.debug( self.name + " actual: " + repr( output ) )
4845 return None
4846 except TypeError:
4847 main.log.exception( self.name + ": Object not as expected" )
4848 return None
4849 except Exception:
4850 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004851 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004852
4853 def valueTestDestroy( self, valueName ):
4854 """
4855 CLI command to destroy an atomic value.
4856 Required arguments:
4857 valueName - The name of the value to destroy.
4858 returns:
4859 main.TRUE on success or
4860 main.ERROR on Error
4861 """
4862 try:
4863 valueName = str( valueName )
4864 cmdStr = "value-test "
4865 operation = "destroy"
4866 cmdStr += valueName + " " + operation
4867 output = self.distPrimitivesSend( cmdStr )
4868 if output is not None:
4869 return main.TRUE
4870 else:
4871 return main.ERROR
4872 except TypeError:
4873 main.log.exception( self.name + ": Object not as expected" )
4874 return main.ERROR
Jon Halle1a3b752015-07-22 13:02:46 -07004875 except Exception:
4876 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004877 main.cleanAndExit()
Jon Halle1a3b752015-07-22 13:02:46 -07004878
YPZhangfebf7302016-05-24 16:45:56 -07004879 def summary( self, jsonFormat=True, timeout=30 ):
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004880 """
4881 Description: Execute summary command in onos
4882 Returns: json object ( summary -j ), returns main.FALSE if there is
4883 no output
4884
4885 """
4886 try:
4887 cmdStr = "summary"
4888 if jsonFormat:
4889 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07004890 handle = self.sendline( cmdStr, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07004891 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004892 assert "Command not found:" not in handle, handle
Jon Hall6e709752016-02-01 13:38:46 -08004893 assert "Error:" not in handle, handle
Devin Lima7cfdbd2017-09-29 15:02:22 -07004894 assert "Error executing" not in handle, handle
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004895 if not handle:
4896 main.log.error( self.name + ": There is no output in " +
4897 "summary command" )
4898 return main.FALSE
4899 return handle
Jon Hallc6793552016-01-19 14:18:37 -08004900 except AssertionError:
Jon Hall6e709752016-02-01 13:38:46 -08004901 main.log.exception( "{} Error in summary output:".format( self.name ) )
Jon Hallc6793552016-01-19 14:18:37 -08004902 return None
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004903 except TypeError:
4904 main.log.exception( self.name + ": Object not as expected" )
4905 return None
4906 except pexpect.EOF:
4907 main.log.error( self.name + ": EOF exception found" )
4908 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004909 main.cleanAndExit()
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004910 except Exception:
4911 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004912 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004913
Jon Hall935db192016-04-19 00:22:04 -07004914 def transactionalMapGet( self, keyName ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004915 """
4916 CLI command to get the value of a key in a consistent map using
4917 transactions. This a test function and can only get keys from the
4918 test map hard coded into the cli command
4919 Required arguments:
4920 keyName - The name of the key to get
Jon Hall2a5002c2015-08-21 16:49:11 -07004921 returns:
4922 The string value of the key or
4923 None on Error
4924 """
4925 try:
4926 keyName = str( keyName )
4927 cmdStr = "transactional-map-test-get "
Jon Hall2a5002c2015-08-21 16:49:11 -07004928 cmdStr += keyName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004929 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07004930 pattern = "Key-value pair \(" + keyName + ", (?P<value>.+)\) found."
4931 if "Key " + keyName + " not found." in output:
Jon Hall9bfadd22016-05-11 14:48:07 -07004932 main.log.warn( output )
Jon Hall2a5002c2015-08-21 16:49:11 -07004933 return None
4934 else:
4935 match = re.search( pattern, output )
4936 if match:
4937 return match.groupdict()[ 'value' ]
4938 else:
4939 main.log.error( self.name + ": transactionlMapGet did not" +
4940 " match expected output." )
4941 main.log.debug( self.name + " expected: " + pattern )
4942 main.log.debug( self.name + " actual: " + repr( output ) )
4943 return None
4944 except TypeError:
4945 main.log.exception( self.name + ": Object not as expected" )
4946 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004947 except Exception:
4948 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004949 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004950
Jon Hall935db192016-04-19 00:22:04 -07004951 def transactionalMapPut( self, numKeys, value ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004952 """
4953 CLI command to put a value into 'numKeys' number of keys in a
4954 consistent map using transactions. This a test function and can only
4955 put into keys named 'Key#' of the test map hard coded into the cli command
4956 Required arguments:
4957 numKeys - Number of keys to add the value to
4958 value - The string value to put into the keys
Jon Hall2a5002c2015-08-21 16:49:11 -07004959 returns:
4960 A dictionary whose keys are the name of the keys put into the map
4961 and the values of the keys are dictionaries whose key-values are
4962 'value': value put into map and optionaly
4963 'oldValue': Previous value in the key or
4964 None on Error
4965
4966 Example output
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004967 { 'Key1': {'oldValue': 'oldTestValue', 'value': 'Testing'},
4968 'Key2': {'value': 'Testing'} }
Jon Hall2a5002c2015-08-21 16:49:11 -07004969 """
4970 try:
4971 numKeys = str( numKeys )
4972 value = str( value )
4973 cmdStr = "transactional-map-test-put "
Jon Hall2a5002c2015-08-21 16:49:11 -07004974 cmdStr += numKeys + " " + value
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004975 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07004976 newPattern = 'Created Key (?P<key>(\w)+) with value (?P<value>(.)+)\.'
4977 updatedPattern = "Put (?P<value>(.)+) into key (?P<key>(\w)+)\. The old value was (?P<oldValue>(.)+)\."
4978 results = {}
4979 for line in output.splitlines():
4980 new = re.search( newPattern, line )
4981 updated = re.search( updatedPattern, line )
4982 if new:
4983 results[ new.groupdict()[ 'key' ] ] = { 'value': new.groupdict()[ 'value' ] }
4984 elif updated:
4985 results[ updated.groupdict()[ 'key' ] ] = { 'value': updated.groupdict()[ 'value' ],
Jon Hallc6793552016-01-19 14:18:37 -08004986 'oldValue': updated.groupdict()[ 'oldValue' ] }
Jon Hall2a5002c2015-08-21 16:49:11 -07004987 else:
4988 main.log.error( self.name + ": transactionlMapGet did not" +
4989 " match expected output." )
Jon Hallc6793552016-01-19 14:18:37 -08004990 main.log.debug( "{} expected: {!r} or {!r}".format( self.name,
4991 newPattern,
4992 updatedPattern ) )
Jon Hall2a5002c2015-08-21 16:49:11 -07004993 main.log.debug( self.name + " actual: " + repr( output ) )
4994 return results
Jon Hall0e240372018-05-02 11:21:57 -07004995 except ( TypeError, AttributeError ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004996 main.log.exception( self.name + ": Object not as expected" )
4997 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004998 except Exception:
4999 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005000 main.cleanAndExit()
Jon Hallc6793552016-01-19 14:18:37 -08005001
acsmarsdaea66c2015-09-03 11:44:06 -07005002 def maps( self, jsonFormat=True ):
5003 """
5004 Description: Returns result of onos:maps
5005 Optional:
5006 * jsonFormat: enable json formatting of output
5007 """
5008 try:
5009 cmdStr = "maps"
5010 if jsonFormat:
5011 cmdStr += " -j"
5012 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07005013 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005014 assert "Command not found:" not in handle, handle
acsmarsdaea66c2015-09-03 11:44:06 -07005015 return handle
Jon Hallc6793552016-01-19 14:18:37 -08005016 except AssertionError:
5017 main.log.exception( "" )
5018 return None
acsmarsdaea66c2015-09-03 11:44:06 -07005019 except TypeError:
5020 main.log.exception( self.name + ": Object not as expected" )
5021 return None
5022 except pexpect.EOF:
5023 main.log.error( self.name + ": EOF exception found" )
5024 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005025 main.cleanAndExit()
acsmarsdaea66c2015-09-03 11:44:06 -07005026 except Exception:
5027 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005028 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005029
5030 def getSwController( self, uri, jsonFormat=True ):
5031 """
5032 Descrition: Gets the controller information from the device
5033 """
5034 try:
5035 cmd = "device-controllers "
5036 if jsonFormat:
5037 cmd += "-j "
5038 response = self.sendline( cmd + uri )
Jon Halla495f562016-05-16 18:03:26 -07005039 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005040 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005041 return response
Jon Hallc6793552016-01-19 14:18:37 -08005042 except AssertionError:
5043 main.log.exception( "" )
5044 return None
GlennRC050596c2015-11-18 17:06:41 -08005045 except TypeError:
5046 main.log.exception( self.name + ": Object not as expected" )
5047 return None
5048 except pexpect.EOF:
5049 main.log.error( self.name + ": EOF exception found" )
5050 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005051 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005052 except Exception:
5053 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005054 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005055
5056 def setSwController( self, uri, ip, proto="tcp", port="6653", jsonFormat=True ):
5057 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005058 Descrition: sets the controller(s) for the specified device
GlennRC050596c2015-11-18 17:06:41 -08005059
5060 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005061 Required: uri - String: The uri of the device(switch).
GlennRC050596c2015-11-18 17:06:41 -08005062 ip - String or List: The ip address of the controller.
5063 This parameter can be formed in a couple of different ways.
5064 VALID:
5065 10.0.0.1 - just the ip address
5066 tcp:10.0.0.1 - the protocol and the ip address
5067 tcp:10.0.0.1:6653 - the protocol and port can be specified,
5068 so that you can add controllers with different
5069 protocols and ports
5070 INVALID:
5071 10.0.0.1:6653 - this is not supported by ONOS
5072
5073 Optional: proto - The type of connection e.g. tcp, ssl. If a list of ips are given
5074 port - The port number.
5075 jsonFormat - If set ONOS will output in json NOTE: This is currently not supported
5076
5077 Returns: main.TRUE if ONOS returns without any errors, otherwise returns main.FALSE
5078 """
5079 try:
5080 cmd = "device-setcontrollers"
5081
5082 if jsonFormat:
5083 cmd += " -j"
5084 cmd += " " + uri
5085 if isinstance( ip, str ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005086 ip = [ ip ]
GlennRC050596c2015-11-18 17:06:41 -08005087 for item in ip:
5088 if ":" in item:
5089 sitem = item.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005090 if len( sitem ) == 3:
GlennRC050596c2015-11-18 17:06:41 -08005091 cmd += " " + item
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005092 elif "." in sitem[ 1 ]:
5093 cmd += " {}:{}".format( item, port )
GlennRC050596c2015-11-18 17:06:41 -08005094 else:
5095 main.log.error( "Malformed entry: " + item )
5096 raise TypeError
5097 else:
5098 cmd += " {}:{}:{}".format( proto, item, port )
GlennRC050596c2015-11-18 17:06:41 -08005099 response = self.sendline( cmd )
Jon Halla495f562016-05-16 18:03:26 -07005100 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005101 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005102 if "Error" in response:
5103 main.log.error( response )
5104 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005105 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005106 except AssertionError:
5107 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005108 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005109 except TypeError:
5110 main.log.exception( self.name + ": Object not as expected" )
5111 return main.FALSE
5112 except pexpect.EOF:
5113 main.log.error( self.name + ": EOF exception found" )
5114 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005115 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005116 except Exception:
5117 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005118 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005119
5120 def removeDevice( self, device ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005121 '''
GlennRC20fc6522015-12-23 23:26:57 -08005122 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005123 Remove a device from ONOS by passing the uri of the device(s).
GlennRC20fc6522015-12-23 23:26:57 -08005124 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005125 device - (str or list) the id or uri of the device ex. "of:0000000000000001"
GlennRC20fc6522015-12-23 23:26:57 -08005126 Returns:
5127 Returns main.FALSE if an exception is thrown or an error is present
5128 in the response. Otherwise, returns main.TRUE.
5129 NOTE:
5130 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005131 '''
GlennRC20fc6522015-12-23 23:26:57 -08005132 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005133 if isinstance( device, str ):
You Wang823f5022016-08-18 15:24:41 -07005134 deviceStr = device
5135 device = []
5136 device.append( deviceStr )
GlennRC20fc6522015-12-23 23:26:57 -08005137
5138 for d in device:
5139 time.sleep( 1 )
5140 response = self.sendline( "device-remove {}".format( d ) )
Jon Halla495f562016-05-16 18:03:26 -07005141 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005142 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005143 if "Error" in response:
5144 main.log.warn( "Error for device: {}\nResponse: {}".format( d, response ) )
5145 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005146 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005147 except AssertionError:
5148 main.log.exception( "" )
5149 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005150 except TypeError:
5151 main.log.exception( self.name + ": Object not as expected" )
5152 return main.FALSE
5153 except pexpect.EOF:
5154 main.log.error( self.name + ": EOF exception found" )
5155 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005156 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005157 except Exception:
5158 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005159 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005160
5161 def removeHost( self, host ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005162 '''
GlennRC20fc6522015-12-23 23:26:57 -08005163 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005164 Remove a host from ONOS by passing the id of the host(s)
GlennRC20fc6522015-12-23 23:26:57 -08005165 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005166 hostId - (str or list) the id or mac of the host ex. "00:00:00:00:00:01"
GlennRC20fc6522015-12-23 23:26:57 -08005167 Returns:
5168 Returns main.FALSE if an exception is thrown or an error is present
5169 in the response. Otherwise, returns main.TRUE.
5170 NOTE:
5171 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005172 '''
GlennRC20fc6522015-12-23 23:26:57 -08005173 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005174 if isinstance( host, str ):
GlennRC20fc6522015-12-23 23:26:57 -08005175 host = list( host )
5176
5177 for h in host:
5178 time.sleep( 1 )
5179 response = self.sendline( "host-remove {}".format( h ) )
Jon Halla495f562016-05-16 18:03:26 -07005180 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005181 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005182 if "Error" in response:
5183 main.log.warn( "Error for host: {}\nResponse: {}".format( h, response ) )
5184 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005185 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005186 except AssertionError:
5187 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005188 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005189 except TypeError:
5190 main.log.exception( self.name + ": Object not as expected" )
5191 return main.FALSE
5192 except pexpect.EOF:
5193 main.log.error( self.name + ": EOF exception found" )
5194 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005195 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005196 except Exception:
5197 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005198 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005199
YPZhangfebf7302016-05-24 16:45:56 -07005200 def link( self, begin, end, state, timeout=30, showResponse=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005201 '''
GlennRCed771242016-01-13 17:02:47 -08005202 Description:
5203 Bring link down or up in the null-provider.
5204 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005205 begin - (string) One end of a device or switch.
5206 end - (string) the other end of the device or switch
GlennRCed771242016-01-13 17:02:47 -08005207 returns:
5208 main.TRUE if no exceptions were thrown and no Errors are
5209 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005210 '''
GlennRCed771242016-01-13 17:02:47 -08005211 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005212 cmd = "null-link null:{} null:{} {}".format( begin, end, state )
YPZhangfebf7302016-05-24 16:45:56 -07005213 response = self.sendline( cmd, showResponse=showResponse, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07005214 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005215 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08005216 if "Error" in response or "Failure" in response:
5217 main.log.error( response )
5218 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005219 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005220 except AssertionError:
5221 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005222 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005223 except TypeError:
5224 main.log.exception( self.name + ": Object not as expected" )
5225 return main.FALSE
5226 except pexpect.EOF:
5227 main.log.error( self.name + ": EOF exception found" )
5228 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005229 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005230 except Exception:
5231 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005232 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005233
Jon Hall2c8959e2016-12-16 12:17:34 -08005234 def portstate( self, dpid, port, state ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005235 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005236 Description:
5237 Changes the state of port in an OF switch by means of the
5238 PORTSTATUS OF messages.
5239 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005240 dpid - (string) Datapath ID of the device. Ex: 'of:0000000000000102'
5241 port - (string) target port in the device. Ex: '2'
5242 state - (string) target state (enable or disable)
Flavio Castro82ee2f62016-06-07 15:04:12 -07005243 returns:
5244 main.TRUE if no exceptions were thrown and no Errors are
5245 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005246 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005247 try:
Jon Hall2c8959e2016-12-16 12:17:34 -08005248 state = state.lower()
5249 assert state == 'enable' or state == 'disable', "Unknown state"
Jon Halle0f0b342017-04-18 11:43:47 -07005250 cmd = "portstate {} {} {}".format( dpid, port, state )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005251 response = self.sendline( cmd, showResponse=True )
5252 assert response is not None, "Error in sendline"
5253 assert "Command not found:" not in response, response
5254 if "Error" in response or "Failure" in response:
5255 main.log.error( response )
5256 return main.FALSE
5257 return main.TRUE
5258 except AssertionError:
5259 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005260 return main.FALSE
Flavio Castro82ee2f62016-06-07 15:04:12 -07005261 except TypeError:
5262 main.log.exception( self.name + ": Object not as expected" )
5263 return main.FALSE
5264 except pexpect.EOF:
5265 main.log.error( self.name + ": EOF exception found" )
5266 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005267 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005268 except Exception:
5269 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005270 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005271
5272 def logSet( self, level="INFO", app="org.onosproject" ):
5273 """
5274 Set the logging level to lvl for a specific app
5275 returns main.TRUE on success
5276 returns main.FALSE if Error occurred
5277 if noExit is True, TestON will not exit, but clean up
5278 Available level: DEBUG, TRACE, INFO, WARN, ERROR
5279 Level defaults to INFO
5280 """
5281 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005282 self.handle.sendline( "log:set %s %s" % ( level, app ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -08005283 self.handle.expect( self.karafPrompt )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005284
5285 response = self.handle.before
5286 if re.search( "Error", response ):
5287 return main.FALSE
5288 return main.TRUE
5289 except pexpect.TIMEOUT:
5290 main.log.exception( self.name + ": TIMEOUT exception found" )
Devin Lim44075962017-08-11 10:56:37 -07005291 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005292 except pexpect.EOF:
5293 main.log.error( self.name + ": EOF exception found" )
5294 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005295 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005296 except Exception:
5297 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005298 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07005299
5300 def getGraphDict( self, timeout=60, includeHost=False ):
5301 """
5302 Return a dictionary which describes the latest network topology data as a
5303 graph.
5304 An example of the dictionary:
5305 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
5306 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
5307 Each vertex should at least have an 'edges' attribute which describes the
5308 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005309 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07005310 list of attributes.
5311 An example of the edges dictionary:
5312 'edges': { vertex2: { 'port': ..., 'weight': ... },
5313 vertex3: { 'port': ..., 'weight': ... } }
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005314 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07005315 in topology data.
5316 """
5317 graphDict = {}
5318 try:
5319 links = self.links()
5320 links = json.loads( links )
5321 devices = self.devices()
5322 devices = json.loads( devices )
5323 idToDevice = {}
5324 for device in devices:
5325 idToDevice[ device[ 'id' ] ] = device
5326 if includeHost:
5327 hosts = self.hosts()
5328 # FIXME: support 'includeHost' argument
5329 for link in links:
5330 nodeA = link[ 'src' ][ 'device' ]
5331 nodeB = link[ 'dst' ][ 'device' ]
5332 assert idToDevice[ nodeA ][ 'available' ] and idToDevice[ nodeB ][ 'available' ]
Jon Halle0f0b342017-04-18 11:43:47 -07005333 if nodeA not in graphDict.keys():
5334 graphDict[ nodeA ] = { 'edges': {},
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005335 'dpid': idToDevice[ nodeA ][ 'id' ][ 3: ],
Jon Halle0f0b342017-04-18 11:43:47 -07005336 'type': idToDevice[ nodeA ][ 'type' ],
5337 'available': idToDevice[ nodeA ][ 'available' ],
5338 'role': idToDevice[ nodeA ][ 'role' ],
5339 'mfr': idToDevice[ nodeA ][ 'mfr' ],
5340 'hw': idToDevice[ nodeA ][ 'hw' ],
5341 'sw': idToDevice[ nodeA ][ 'sw' ],
5342 'serial': idToDevice[ nodeA ][ 'serial' ],
5343 'chassisId': idToDevice[ nodeA ][ 'chassisId' ],
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005344 'annotations': idToDevice[ nodeA ][ 'annotations' ]}
You Wangdb8cd0a2016-05-26 15:19:45 -07005345 else:
5346 # Assert nodeB is not connected to any current links of nodeA
You Wang7d14d642019-01-23 15:10:08 -08005347 # assert nodeB not in graphDict[ nodeA ][ 'edges' ].keys()
5348 pass
Jon Halle0f0b342017-04-18 11:43:47 -07005349 graphDict[ nodeA ][ 'edges' ][ nodeB ] = { 'port': link[ 'src' ][ 'port' ],
5350 'type': link[ 'type' ],
5351 'state': link[ 'state' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07005352 return graphDict
5353 except ( TypeError, ValueError ):
5354 main.log.exception( self.name + ": Object not as expected" )
5355 return None
5356 except KeyError:
5357 main.log.exception( self.name + ": KeyError exception found" )
5358 return None
5359 except AssertionError:
5360 main.log.exception( self.name + ": AssertionError exception found" )
5361 return None
5362 except pexpect.EOF:
5363 main.log.error( self.name + ": EOF exception found" )
5364 main.log.error( self.name + ": " + self.handle.before )
5365 return None
5366 except Exception:
5367 main.log.exception( self.name + ": Uncaught exception!" )
5368 return None
YPZhangcbc2a062016-07-11 10:55:44 -07005369
5370 def getIntentPerfSummary( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005371 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005372 Send command to check intent-perf summary
5373 Returns: dictionary for intent-perf summary
5374 if something wrong, function will return None
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005375 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005376 cmd = "intent-perf -s"
5377 respDic = {}
5378 resp = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08005379 assert resp is not None, "Error in sendline"
5380 assert "Command not found:" not in resp, resp
YPZhangcbc2a062016-07-11 10:55:44 -07005381 try:
5382 # Generate the dictionary to return
5383 for l in resp.split( "\n" ):
5384 # Delete any white space in line
5385 temp = re.sub( r'\s+', '', l )
5386 temp = temp.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005387 respDic[ temp[ 0 ] ] = temp[ 1 ]
YPZhangcbc2a062016-07-11 10:55:44 -07005388
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005389 except ( TypeError, ValueError ):
YPZhangcbc2a062016-07-11 10:55:44 -07005390 main.log.exception( self.name + ": Object not as expected" )
5391 return None
5392 except KeyError:
5393 main.log.exception( self.name + ": KeyError exception found" )
5394 return None
5395 except AssertionError:
5396 main.log.exception( self.name + ": AssertionError exception found" )
5397 return None
5398 except pexpect.EOF:
5399 main.log.error( self.name + ": EOF exception found" )
5400 main.log.error( self.name + ": " + self.handle.before )
5401 return None
5402 except Exception:
5403 main.log.exception( self.name + ": Uncaught exception!" )
5404 return None
5405 return respDic
5406
Chiyu Chengec63bde2016-11-17 18:11:36 -08005407 def logSearch( self, mode='all', searchTerm='', startLine='', logNum=1 ):
chengchiyu08303a02016-09-08 17:40:26 -07005408 """
5409 Searches the latest ONOS log file for the given search term and
5410 return a list that contains all the lines that have the search term.
YPZhangcbc2a062016-07-11 10:55:44 -07005411
chengchiyu08303a02016-09-08 17:40:26 -07005412 Arguments:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005413 searchTerm:
5414 The string to grep from the ONOS log.
5415 startLine:
5416 The term that decides which line is the start to search the searchTerm in
5417 the karaf log. For now, startTerm only works in 'first' mode.
5418 logNum:
5419 In some extreme cases, one karaf log is not big enough to contain all the
5420 information.Because of this, search mutiply logs is necessary to capture
5421 the right result. logNum is the number of karaf logs that we need to search
5422 the searchTerm.
chengchiyu08303a02016-09-08 17:40:26 -07005423 mode:
5424 all: return all the strings that contain the search term
5425 last: return the last string that contains the search term
5426 first: return the first string that contains the search term
Chiyu Chengec63bde2016-11-17 18:11:36 -08005427 num: return the number of times that the searchTerm appears in the log
5428 total: return how many lines in karaf log
chengchiyu08303a02016-09-08 17:40:26 -07005429 """
5430 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005431 assert isinstance( searchTerm, str )
Jon Halle0f0b342017-04-18 11:43:47 -07005432 # Build the log paths string
Chiyu Chengec63bde2016-11-17 18:11:36 -08005433 logPath = '/opt/onos/log/karaf.log.'
5434 logPaths = '/opt/onos/log/karaf.log'
5435 for i in range( 1, logNum ):
5436 logPaths = logPath + str( i ) + " " + logPaths
5437 cmd = "cat " + logPaths
You Wang6d301d42017-04-21 10:49:33 -07005438 if startLine:
Jon Halla478b852017-12-04 15:00:15 -08005439 # 100000000 is just a extreme large number to make sure this function can
5440 # grep all the lines after startLine
You Wang6d301d42017-04-21 10:49:33 -07005441 cmd = cmd + " | grep -A 100000000 \'" + startLine + "\'"
Chiyu Chengec63bde2016-11-17 18:11:36 -08005442 if mode == 'all':
5443 cmd = cmd + " | grep \'" + searchTerm + "\'"
You Wang6d301d42017-04-21 10:49:33 -07005444 elif mode == 'last':
Chiyu Chengec63bde2016-11-17 18:11:36 -08005445 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | tail -n 1"
You Wang6d301d42017-04-21 10:49:33 -07005446 elif mode == 'first':
5447 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | head -n 1"
5448 elif mode == 'num':
You Wangd91a70f2019-01-03 15:28:10 -08005449 cmd = cmd + " | grep \'" + searchTerm + "\' | wc -l"
5450 num = self.lineCount( cmd )
Chiyu Chengb8c2c842016-10-05 12:40:49 -07005451 return num
You Wang6d301d42017-04-21 10:49:33 -07005452 elif mode == 'total':
Jon Halld5a94fb2018-11-13 14:32:23 -08005453 totalLines = self.lineCount( "cat /opt/onos/log/karaf.log | wc -l" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005454 return int( totalLines )
You Wang6d301d42017-04-21 10:49:33 -07005455 else:
5456 main.log.error( self.name + " unsupported mode" )
5457 return main.ERROR
chengchiyu08303a02016-09-08 17:40:26 -07005458 before = self.sendline( cmd )
5459 before = before.splitlines()
5460 # make sure the returned list only contains the search term
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005461 returnLines = [ line for line in before if searchTerm in line ]
chengchiyu08303a02016-09-08 17:40:26 -07005462 return returnLines
5463 except AssertionError:
5464 main.log.error( self.name + " searchTerm is not string type" )
5465 return None
5466 except pexpect.EOF:
5467 main.log.error( self.name + ": EOF exception found" )
5468 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005469 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005470 except pexpect.TIMEOUT:
5471 main.log.error( self.name + ": TIMEOUT exception found" )
5472 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005473 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005474 except Exception:
5475 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005476 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005477
5478 def vplsShow( self, jsonFormat=True ):
5479 """
5480 Description: Returns result of onos:vpls show, which should list the
5481 configured VPLS networks and the assigned interfaces.
5482 Optional:
5483 * jsonFormat: enable json formatting of output
5484 Returns:
5485 The output of the command or None on error.
5486 """
5487 try:
5488 cmdStr = "vpls show"
5489 if jsonFormat:
5490 raise NotImplementedError
5491 cmdStr += " -j"
5492 handle = self.sendline( cmdStr )
5493 assert handle is not None, "Error in sendline"
5494 assert "Command not found:" not in handle, handle
5495 return handle
5496 except AssertionError:
5497 main.log.exception( "" )
5498 return None
5499 except TypeError:
5500 main.log.exception( self.name + ": Object not as expected" )
5501 return None
5502 except pexpect.EOF:
5503 main.log.error( self.name + ": EOF exception found" )
5504 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005505 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005506 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005507 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005508 return None
5509 except Exception:
5510 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005511 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005512
5513 def parseVplsShow( self ):
5514 """
5515 Parse the cli output of 'vpls show' into json output. This is required
5516 as there is currently no json output available.
5517 """
5518 try:
5519 output = []
5520 raw = self.vplsShow( jsonFormat=False )
5521 namePat = "VPLS name: (?P<name>\w+)"
5522 interfacesPat = "Associated interfaces: \[(?P<interfaces>.*)\]"
5523 encapPat = "Encapsulation: (?P<encap>\w+)"
5524 pattern = "\s+".join( [ namePat, interfacesPat, encapPat ] )
5525 mIter = re.finditer( pattern, raw )
5526 for match in mIter:
5527 item = {}
5528 item[ 'name' ] = match.group( 'name' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005529 ifaces = match.group( 'interfaces' ).split( ', ' )
Jon Hall2c8959e2016-12-16 12:17:34 -08005530 if ifaces == [ "" ]:
5531 ifaces = []
5532 item[ 'interfaces' ] = ifaces
5533 encap = match.group( 'encap' )
5534 if encap != 'NONE':
5535 item[ 'encapsulation' ] = encap.lower()
5536 output.append( item )
5537 return output
5538 except Exception:
5539 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005540 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005541
5542 def vplsList( self, jsonFormat=True ):
5543 """
5544 Description: Returns result of onos:vpls list, which should list the
5545 configured VPLS networks.
5546 Optional:
5547 * jsonFormat: enable json formatting of output
5548 """
5549 try:
5550 cmdStr = "vpls list"
5551 if jsonFormat:
5552 raise NotImplementedError
5553 cmdStr += " -j"
5554 handle = self.sendline( cmdStr )
5555 assert handle is not None, "Error in sendline"
5556 assert "Command not found:" not in handle, handle
5557 return handle
5558 except AssertionError:
5559 main.log.exception( "" )
5560 return None
5561 except TypeError:
5562 main.log.exception( self.name + ": Object not as expected" )
5563 return None
5564 except pexpect.EOF:
5565 main.log.error( self.name + ": EOF exception found" )
5566 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005567 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005568 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005569 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005570 return None
5571 except Exception:
5572 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005573 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005574
5575 def vplsCreate( self, network ):
5576 """
5577 CLI command to create a new VPLS network.
5578 Required arguments:
5579 network - String name of the network to create.
5580 returns:
5581 main.TRUE on success and main.FALSE on failure
5582 """
5583 try:
5584 network = str( network )
5585 cmdStr = "vpls create "
5586 cmdStr += network
5587 output = self.sendline( cmdStr )
5588 assert output is not None, "Error in sendline"
5589 assert "Command not found:" not in output, output
5590 assert "Error executing command" not in output, output
5591 assert "VPLS already exists:" not in output, output
5592 return main.TRUE
5593 except AssertionError:
5594 main.log.exception( "" )
5595 return main.FALSE
5596 except TypeError:
5597 main.log.exception( self.name + ": Object not as expected" )
5598 return main.FALSE
5599 except pexpect.EOF:
5600 main.log.error( self.name + ": EOF exception found" )
5601 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005602 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005603 except Exception:
5604 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005605 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005606
5607 def vplsDelete( self, network ):
5608 """
5609 CLI command to delete a VPLS network.
5610 Required arguments:
5611 network - Name of the network to delete.
5612 returns:
5613 main.TRUE on success and main.FALSE on failure
5614 """
5615 try:
5616 network = str( network )
5617 cmdStr = "vpls delete "
5618 cmdStr += network
5619 output = self.sendline( cmdStr )
5620 assert output is not None, "Error in sendline"
5621 assert "Command not found:" not in output, output
5622 assert "Error executing command" not in output, output
5623 assert " not found" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005624 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005625 return main.TRUE
5626 except AssertionError:
5627 main.log.exception( "" )
5628 return main.FALSE
5629 except TypeError:
5630 main.log.exception( self.name + ": Object not as expected" )
5631 return main.FALSE
5632 except pexpect.EOF:
5633 main.log.error( self.name + ": EOF exception found" )
5634 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005635 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005636 except Exception:
5637 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005638 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005639
5640 def vplsAddIface( self, network, iface ):
5641 """
5642 CLI command to add an interface to a VPLS network.
5643 Required arguments:
5644 network - Name of the network to add the interface to.
5645 iface - The ONOS name for an interface.
5646 returns:
5647 main.TRUE on success and main.FALSE on failure
5648 """
5649 try:
5650 network = str( network )
5651 iface = str( iface )
5652 cmdStr = "vpls add-if "
5653 cmdStr += network + " " + iface
5654 output = self.sendline( cmdStr )
5655 assert output is not None, "Error in sendline"
5656 assert "Command not found:" not in output, output
5657 assert "Error executing command" not in output, output
5658 assert "already associated to network" not in output, output
5659 assert "Interface cannot be added." not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005660 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005661 return main.TRUE
5662 except AssertionError:
5663 main.log.exception( "" )
5664 return main.FALSE
5665 except TypeError:
5666 main.log.exception( self.name + ": Object not as expected" )
5667 return main.FALSE
5668 except pexpect.EOF:
5669 main.log.error( self.name + ": EOF exception found" )
5670 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005671 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005672 except Exception:
5673 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005674 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005675
5676 def vplsRemIface( self, network, iface ):
5677 """
5678 CLI command to remove an interface from a VPLS network.
5679 Required arguments:
5680 network - Name of the network to remove the interface from.
5681 iface - Name of the interface to remove.
5682 returns:
5683 main.TRUE on success and main.FALSE on failure
5684 """
5685 try:
5686 iface = str( iface )
5687 cmdStr = "vpls rem-if "
5688 cmdStr += network + " " + iface
5689 output = self.sendline( cmdStr )
5690 assert output is not None, "Error in sendline"
5691 assert "Command not found:" not in output, output
5692 assert "Error executing command" not in output, output
5693 assert "is not configured" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005694 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005695 return main.TRUE
5696 except AssertionError:
5697 main.log.exception( "" )
5698 return main.FALSE
5699 except TypeError:
5700 main.log.exception( self.name + ": Object not as expected" )
5701 return main.FALSE
5702 except pexpect.EOF:
5703 main.log.error( self.name + ": EOF exception found" )
5704 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005705 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005706 except Exception:
5707 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005708 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005709
5710 def vplsClean( self ):
5711 """
5712 Description: Clears the VPLS app configuration.
5713 Returns: main.TRUE on success and main.FALSE on failure
5714 """
5715 try:
5716 cmdStr = "vpls clean"
5717 handle = self.sendline( cmdStr )
5718 assert handle is not None, "Error in sendline"
5719 assert "Command not found:" not in handle, handle
Jon Hallcf97cf12017-06-06 09:37:51 -07005720 assert "still updating" not in handle, handle
Jon Hall2c8959e2016-12-16 12:17:34 -08005721 return handle
5722 except AssertionError:
5723 main.log.exception( "" )
5724 return main.FALSE
5725 except TypeError:
5726 main.log.exception( self.name + ": Object not as expected" )
5727 return main.FALSE
5728 except pexpect.EOF:
5729 main.log.error( self.name + ": EOF exception found" )
5730 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005731 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005732 except Exception:
5733 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005734 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005735
5736 def vplsSetEncap( self, network, encapType ):
5737 """
5738 CLI command to add an interface to a VPLS network.
5739 Required arguments:
5740 network - Name of the network to create.
5741 encapType - Type of encapsulation.
5742 returns:
5743 main.TRUE on success and main.FALSE on failure
5744 """
5745 try:
5746 network = str( network )
5747 encapType = str( encapType ).upper()
5748 assert encapType in [ "MPLS", "VLAN", "NONE" ], "Incorrect type"
5749 cmdStr = "vpls set-encap "
5750 cmdStr += network + " " + encapType
5751 output = self.sendline( cmdStr )
5752 assert output is not None, "Error in sendline"
5753 assert "Command not found:" not in output, output
5754 assert "Error executing command" not in output, output
5755 assert "already associated to network" not in output, output
5756 assert "Encapsulation type " not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005757 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005758 return main.TRUE
5759 except AssertionError:
5760 main.log.exception( "" )
5761 return main.FALSE
5762 except TypeError:
5763 main.log.exception( self.name + ": Object not as expected" )
5764 return main.FALSE
5765 except pexpect.EOF:
5766 main.log.error( self.name + ": EOF exception found" )
5767 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005768 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005769 except Exception:
5770 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005771 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005772
5773 def interfaces( self, jsonFormat=True ):
5774 """
5775 Description: Returns result of interfaces command.
5776 Optional:
5777 * jsonFormat: enable json formatting of output
5778 Returns:
5779 The output of the command or None on error.
5780 """
5781 try:
5782 cmdStr = "interfaces"
5783 if jsonFormat:
Jon Halle0f0b342017-04-18 11:43:47 -07005784 raise NotImplementedError
Jon Hall2c8959e2016-12-16 12:17:34 -08005785 cmdStr += " -j"
5786 handle = self.sendline( cmdStr )
5787 assert handle is not None, "Error in sendline"
5788 assert "Command not found:" not in handle, handle
5789 return handle
5790 except AssertionError:
5791 main.log.exception( "" )
5792 return None
5793 except TypeError:
5794 main.log.exception( self.name + ": Object not as expected" )
5795 return None
5796 except pexpect.EOF:
5797 main.log.error( self.name + ": EOF exception found" )
5798 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005799 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005800 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005801 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005802 return None
5803 except Exception:
5804 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005805 main.cleanAndExit()
Chiyu Chengec63bde2016-11-17 18:11:36 -08005806
5807 def getTimeStampFromLog( self, mode, searchTerm, splitTerm_before, splitTerm_after, startLine='', logNum=1 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005808 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005809 Get the timestamp of searchTerm from karaf log.
5810
5811 Arguments:
5812 splitTerm_before and splitTerm_after:
5813
5814 The terms that split the string that contains the timeStamp of
5815 searchTerm. For example, if that string is "xxxxxxxcreationTime =
5816 1419510501xxxxxx", then the splitTerm_before is "CreationTime = "
5817 and the splitTerm_after is "x"
5818
5819 others:
Jon Halle0f0b342017-04-18 11:43:47 -07005820 Please look at the "logsearch" Function in onosclidriver.py
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005821 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005822 if logNum < 0:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005823 main.log.error( "Get wrong log number ")
Chiyu Chengec63bde2016-11-17 18:11:36 -08005824 return main.ERROR
5825 lines = self.logSearch( mode=mode, searchTerm=searchTerm, startLine=startLine, logNum=logNum )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005826 if len( lines ) == 0:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005827 main.log.warn( "Captured timestamp string is empty" )
5828 return main.ERROR
5829 lines = lines[ 0 ]
5830 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005831 assert isinstance( lines, str )
Chiyu Chengec63bde2016-11-17 18:11:36 -08005832 # get the target value
5833 line = lines.split( splitTerm_before )
5834 key = line[ 1 ].split( splitTerm_after )
5835 return int( key[ 0 ] )
5836 except IndexError:
5837 main.log.warn( "Index Error!" )
5838 return main.ERROR
5839 except AssertionError:
5840 main.log.warn( "Search Term Not Found " )
5841 return main.ERROR
Jon Halle0f0b342017-04-18 11:43:47 -07005842
5843 def workQueueAdd( self, queueName, value ):
5844 """
5845 CLI command to add a string to the specified Work Queue.
5846 This function uses the distributed primitives test app, which
5847 gives some cli access to distributed primitives for testing
5848 purposes only.
5849
5850 Required arguments:
5851 queueName - The name of the queue to add to
5852 value - The value to add to the queue
5853 returns:
5854 main.TRUE on success, main.FALSE on failure and
5855 main.ERROR on error.
5856 """
5857 try:
5858 queueName = str( queueName )
5859 value = str( value )
5860 prefix = "work-queue-test"
5861 operation = "add"
5862 cmdStr = " ".join( [ prefix, queueName, operation, value ] )
5863 output = self.distPrimitivesSend( cmdStr )
5864 if "Invalid operation name" in output:
5865 main.log.warn( output )
5866 return main.ERROR
5867 elif "Done" in output:
5868 return main.TRUE
5869 except TypeError:
5870 main.log.exception( self.name + ": Object not as expected" )
5871 return main.ERROR
5872 except Exception:
5873 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005874 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005875
5876 def workQueueAddMultiple( self, queueName, value1, value2 ):
5877 """
5878 CLI command to add two strings to the specified Work Queue.
5879 This function uses the distributed primitives test app, which
5880 gives some cli access to distributed primitives for testing
5881 purposes only.
5882
5883 Required arguments:
5884 queueName - The name of the queue to add to
5885 value1 - The first value to add to the queue
5886 value2 - The second value to add to the queue
5887 returns:
5888 main.TRUE on success, main.FALSE on failure and
5889 main.ERROR on error.
5890 """
5891 try:
5892 queueName = str( queueName )
5893 value1 = str( value1 )
5894 value2 = str( value2 )
5895 prefix = "work-queue-test"
5896 operation = "addMultiple"
5897 cmdStr = " ".join( [ prefix, queueName, operation, value1, value2 ] )
5898 output = self.distPrimitivesSend( cmdStr )
5899 if "Invalid operation name" in output:
5900 main.log.warn( output )
5901 return main.ERROR
5902 elif "Done" in output:
5903 return main.TRUE
5904 except TypeError:
5905 main.log.exception( self.name + ": Object not as expected" )
5906 return main.ERROR
5907 except Exception:
5908 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005909 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005910
5911 def workQueueTakeAndComplete( self, queueName, number=1 ):
5912 """
5913 CLI command to take a value from the specified Work Queue and compelte it.
5914 This function uses the distributed primitives test app, which
5915 gives some cli access to distributed primitives for testing
5916 purposes only.
5917
5918 Required arguments:
5919 queueName - The name of the queue to add to
5920 number - The number of items to take and complete
5921 returns:
5922 main.TRUE on success, main.FALSE on failure and
5923 main.ERROR on error.
5924 """
5925 try:
5926 queueName = str( queueName )
5927 number = str( int( number ) )
5928 prefix = "work-queue-test"
5929 operation = "takeAndComplete"
5930 cmdStr = " ".join( [ prefix, queueName, operation, number ] )
5931 output = self.distPrimitivesSend( cmdStr )
5932 if "Invalid operation name" in output:
5933 main.log.warn( output )
5934 return main.ERROR
5935 elif "Done" in output:
5936 return main.TRUE
5937 except TypeError:
5938 main.log.exception( self.name + ": Object not as expected" )
5939 return main.ERROR
5940 except Exception:
5941 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005942 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005943
5944 def workQueueDestroy( self, queueName ):
5945 """
5946 CLI command to destroy the specified Work Queue.
5947 This function uses the distributed primitives test app, which
5948 gives some cli access to distributed primitives for testing
5949 purposes only.
5950
5951 Required arguments:
5952 queueName - The name of the queue to add to
5953 returns:
5954 main.TRUE on success, main.FALSE on failure and
5955 main.ERROR on error.
5956 """
5957 try:
5958 queueName = str( queueName )
5959 prefix = "work-queue-test"
5960 operation = "destroy"
5961 cmdStr = " ".join( [ prefix, queueName, operation ] )
5962 output = self.distPrimitivesSend( cmdStr )
5963 if "Invalid operation name" in output:
5964 main.log.warn( output )
5965 return main.ERROR
5966 return main.TRUE
5967 except TypeError:
5968 main.log.exception( self.name + ": Object not as expected" )
5969 return main.ERROR
5970 except Exception:
5971 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005972 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005973
5974 def workQueueTotalPending( self, queueName ):
5975 """
5976 CLI command to get the Total Pending items of the specified Work Queue.
5977 This function uses the distributed primitives test app, which
5978 gives some cli access to distributed primitives for testing
5979 purposes only.
5980
5981 Required arguments:
5982 queueName - The name of the queue to add to
5983 returns:
5984 The number of Pending items in the specified work queue or
5985 None on error
5986 """
5987 try:
5988 queueName = str( queueName )
5989 prefix = "work-queue-test"
5990 operation = "totalPending"
5991 cmdStr = " ".join( [ prefix, queueName, operation ] )
5992 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08005993 main.log.debug( self.name + ": work queue unparsed: " + output )
5994 output = output.split( "\r\n" )[ -1 ]
5995 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07005996 pattern = r'\d+'
5997 if "Invalid operation name" in output:
5998 main.log.warn( output )
5999 return None
6000 else:
6001 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006002 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006003 except ( AttributeError, TypeError ):
6004 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6005 return None
6006 except Exception:
6007 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006008 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006009
6010 def workQueueTotalCompleted( self, queueName ):
6011 """
6012 CLI command to get the Total Completed items of the specified Work Queue.
6013 This function uses the distributed primitives test app, which
6014 gives some cli access to distributed primitives for testing
6015 purposes only.
6016
6017 Required arguments:
6018 queueName - The name of the queue to add to
6019 returns:
6020 The number of complete items in the specified work queue or
6021 None on error
6022 """
6023 try:
6024 queueName = str( queueName )
6025 prefix = "work-queue-test"
6026 operation = "totalCompleted"
6027 cmdStr = " ".join( [ prefix, queueName, operation ] )
6028 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006029 main.log.debug( self.name + ": work queue unparsed: " + output )
6030 output = output.split( "\r\n" )[ -1 ]
6031 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006032 pattern = r'\d+'
6033 if "Invalid operation name" in output:
6034 main.log.warn( output )
6035 return None
6036 else:
6037 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006038 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006039 except ( AttributeError, TypeError ):
6040 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6041 return None
6042 except Exception:
6043 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006044 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006045
6046 def workQueueTotalInProgress( self, queueName ):
6047 """
6048 CLI command to get the Total In Progress items of the specified Work Queue.
6049 This function uses the distributed primitives test app, which
6050 gives some cli access to distributed primitives for testing
6051 purposes only.
6052
6053 Required arguments:
6054 queueName - The name of the queue to add to
6055 returns:
6056 The number of In Progress items in the specified work queue or
6057 None on error
6058 """
6059 try:
6060 queueName = str( queueName )
6061 prefix = "work-queue-test"
6062 operation = "totalInProgress"
6063 cmdStr = " ".join( [ prefix, queueName, operation ] )
6064 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006065 main.log.debug( self.name + ": work queue unparsed: " + output )
6066 output = output.split( "\r\n" )[ -1 ]
6067 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006068 pattern = r'\d+'
6069 if "Invalid operation name" in output:
6070 main.log.warn( output )
6071 return None
6072 else:
6073 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006074 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006075 except ( AttributeError, TypeError ):
6076 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6077 return None
6078 except Exception:
6079 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006080 main.cleanAndExit()
Jeremy Ronquillo818bc7c2017-08-09 17:14:53 +00006081
6082 def events( self, args='-a' ):
6083 """
6084 Description: Returns events -a command output
6085 Optional:
6086 add other arguments
6087 """
6088 try:
6089 cmdStr = "events"
6090 if args:
6091 cmdStr += " " + args
6092 handle = self.sendline( cmdStr )
6093 assert handle is not None, "Error in sendline"
6094 assert "Command not found:" not in handle, handle
6095 return handle
6096 except AssertionError:
6097 main.log.exception( "" )
6098 return None
6099 except TypeError:
6100 main.log.exception( self.name + ": Object not as expected" )
6101 return None
6102 except pexpect.EOF:
6103 main.log.error( self.name + ": EOF exception found" )
6104 main.log.error( self.name + ": " + self.handle.before )
6105 main.cleanAndExit()
6106 except Exception:
6107 main.log.exception( self.name + ": Uncaught exception!" )
6108 main.cleanAndExit()
6109
6110 def getMaster( self, deviceID ):
6111 """
6112 Description: Obtains current master using "roles" command for a specific deviceID
6113 """
6114 try:
6115 return str( self.getRole( deviceID )[ 'master' ] )
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!" )
Devin Lime6fe3c42017-10-18 16:28:40 -07006128 main.cleanAndExit()
Jon Halla478b852017-12-04 15:00:15 -08006129
6130 def issu( self ):
6131 """
6132 Short summary of In-Service Software Upgrade status
6133
6134 Returns the output of the cli command or None on Error
6135 """
6136 try:
6137 cmdStr = "issu"
6138 handle = self.sendline( cmdStr )
6139 assert handle is not None, "Error in sendline"
6140 assert "Command not found:" not in handle, handle
6141 assert "Unsupported command:" not in handle, handle
6142 return handle
6143 except AssertionError:
6144 main.log.exception( "" )
6145 return None
6146 except TypeError:
6147 main.log.exception( self.name + ": Object not as expected" )
6148 return None
6149 except pexpect.EOF:
6150 main.log.error( self.name + ": EOF exception found" )
6151 main.log.error( self.name + ": " + self.handle.before )
6152 main.cleanAndExit()
6153 except Exception:
6154 main.log.exception( self.name + ": Uncaught exception!" )
6155 main.cleanAndExit()
6156
6157 def issuInit( self ):
6158 """
6159 Initiates an In-Service Software Upgrade
6160
6161 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6162 """
6163 try:
6164 cmdStr = "issu init"
6165 handle = self.sendline( cmdStr )
6166 assert handle is not None, "Error in sendline"
6167 assert "Command not found:" not in handle, handle
6168 assert "Unsupported command:" not in handle, handle
6169 if "Initialized" in handle:
6170 return main.TRUE
6171 else:
6172 return main.FALSE
6173 except AssertionError:
6174 main.log.exception( "" )
6175 return main.ERROR
6176 except TypeError:
6177 main.log.exception( self.name + ": Object not as expected" )
6178 return main.ERROR
6179 except pexpect.EOF:
6180 main.log.error( self.name + ": EOF exception found" )
6181 main.log.error( self.name + ": " + self.handle.before )
6182 main.cleanAndExit()
6183 except Exception:
6184 main.log.exception( self.name + ": Uncaught exception!" )
6185 main.cleanAndExit()
6186
6187 def issuUpgrade( self ):
6188 """
6189 Transitions stores to upgraded nodes
6190
6191 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6192 """
6193 try:
6194 cmdStr = "issu upgrade"
6195 handle = self.sendline( cmdStr )
6196 assert handle is not None, "Error in sendline"
6197 assert "Command not found:" not in handle, handle
6198 assert "Unsupported command:" not in handle, handle
6199 if "Upgraded" in handle:
6200 return main.TRUE
6201 else:
6202 return main.FALSE
6203 except AssertionError:
6204 main.log.exception( "" )
6205 return main.ERROR
6206 except TypeError:
6207 main.log.exception( self.name + ": Object not as expected" )
6208 return main.ERROR
6209 except pexpect.EOF:
6210 main.log.error( self.name + ": EOF exception found" )
6211 main.log.error( self.name + ": " + self.handle.before )
6212 main.cleanAndExit()
6213 except Exception:
6214 main.log.exception( self.name + ": Uncaught exception!" )
6215 main.cleanAndExit()
6216
6217 def issuCommit( self ):
6218 """
6219 Finalizes an In-Service Software Upgrade
6220
6221 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6222 """
6223 try:
6224 cmdStr = "issu commit"
6225 handle = self.sendline( cmdStr )
6226 assert handle is not None, "Error in sendline"
6227 assert "Command not found:" not in handle, handle
6228 assert "Unsupported command:" not in handle, handle
6229 # TODO: Check the version returned by this command
6230 if "Committed version" in handle:
6231 return main.TRUE
6232 else:
6233 return main.FALSE
6234 except AssertionError:
6235 main.log.exception( "" )
6236 return main.ERROR
6237 except TypeError:
6238 main.log.exception( self.name + ": Object not as expected" )
6239 return main.ERROR
6240 except pexpect.EOF:
6241 main.log.error( self.name + ": EOF exception found" )
6242 main.log.error( self.name + ": " + self.handle.before )
6243 main.cleanAndExit()
6244 except Exception:
6245 main.log.exception( self.name + ": Uncaught exception!" )
6246 main.cleanAndExit()
6247
6248 def issuRollback( self ):
6249 """
6250 Rolls back an In-Service Software Upgrade
6251
6252 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6253 """
6254 try:
6255 cmdStr = "issu rollback"
6256 handle = self.sendline( cmdStr )
6257 assert handle is not None, "Error in sendline"
6258 assert "Command not found:" not in handle, handle
6259 assert "Unsupported command:" not in handle, handle
6260 # TODO: Check the version returned by this command
6261 if "Rolled back to version" in handle:
6262 return main.TRUE
6263 else:
6264 return main.FALSE
6265 except AssertionError:
6266 main.log.exception( "" )
6267 return main.ERROR
6268 except TypeError:
6269 main.log.exception( self.name + ": Object not as expected" )
6270 return main.ERROR
6271 except pexpect.EOF:
6272 main.log.error( self.name + ": EOF exception found" )
6273 main.log.error( self.name + ": " + self.handle.before )
6274 main.cleanAndExit()
6275 except Exception:
6276 main.log.exception( self.name + ": Uncaught exception!" )
6277 main.cleanAndExit()
6278
6279 def issuReset( self ):
6280 """
6281 Resets the In-Service Software Upgrade status after a rollback
6282
6283 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6284 """
6285 try:
6286 cmdStr = "issu reset"
6287 handle = self.sendline( cmdStr )
6288 assert handle is not None, "Error in sendline"
6289 assert "Command not found:" not in handle, handle
6290 assert "Unsupported command:" not in handle, handle
6291 # TODO: Check the version returned by this command
6292 if "Reset version" in handle:
6293 return main.TRUE
6294 else:
6295 return main.FALSE
6296 except AssertionError:
6297 main.log.exception( "" )
6298 return main.ERROR
6299 except TypeError:
6300 main.log.exception( self.name + ": Object not as expected" )
6301 return main.ERROR
6302 except pexpect.EOF:
6303 main.log.error( self.name + ": EOF exception found" )
6304 main.log.error( self.name + ": " + self.handle.before )
6305 main.cleanAndExit()
6306 except Exception:
6307 main.log.exception( self.name + ": Uncaught exception!" )
6308 main.cleanAndExit()
6309
6310 def issuStatus( self ):
6311 """
6312 Status of an In-Service Software Upgrade
6313
6314 Returns the output of the cli command or None on Error
6315 """
6316 try:
6317 cmdStr = "issu status"
6318 handle = self.sendline( cmdStr )
6319 assert handle is not None, "Error in sendline"
6320 assert "Command not found:" not in handle, handle
6321 assert "Unsupported command:" not in handle, handle
6322 return handle
6323 except AssertionError:
6324 main.log.exception( "" )
6325 return None
6326 except TypeError:
6327 main.log.exception( self.name + ": Object not as expected" )
6328 return None
6329 except pexpect.EOF:
6330 main.log.error( self.name + ": EOF exception found" )
6331 main.log.error( self.name + ": " + self.handle.before )
6332 main.cleanAndExit()
6333 except Exception:
6334 main.log.exception( self.name + ": Uncaught exception!" )
6335 main.cleanAndExit()
6336
6337 def issuVersion( self ):
6338 """
6339 Get the version of an In-Service Software Upgrade
6340
6341 Returns the output of the cli command or None on Error
6342 """
6343 try:
6344 cmdStr = "issu version"
6345 handle = self.sendline( cmdStr )
6346 assert handle is not None, "Error in sendline"
6347 assert "Command not found:" not in handle, handle
6348 assert "Unsupported command:" not in handle, handle
6349 return handle
6350 except AssertionError:
6351 main.log.exception( "" )
6352 return None
6353 except TypeError:
6354 main.log.exception( self.name + ": Object not as expected" )
6355 return None
6356 except pexpect.EOF:
6357 main.log.error( self.name + ": EOF exception found" )
6358 main.log.error( self.name + ": " + self.handle.before )
6359 main.cleanAndExit()
6360 except Exception:
6361 main.log.exception( self.name + ": Uncaught exception!" )
6362 main.cleanAndExit()
You Wange24d6272018-03-27 21:18:50 -07006363
6364 def mcastJoin( self, sIP, groupIP, sPort, dPorts ):
6365 """
6366 Create a multicast route by calling 'mcast-join' command
6367 sIP: source IP of the multicast route
6368 groupIP: group IP of the multicast route
6369 sPort: source port (e.g. of:0000000000000001/3 ) of the multicast route
6370 dPorts: a list of destination ports of the multicast route
6371 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6372 """
6373 try:
6374 cmdStr = "mcast-join"
6375 cmdStr += " " + str( sIP )
6376 cmdStr += " " + str( groupIP )
6377 cmdStr += " " + str( sPort )
6378 assert isinstance( dPorts, list )
6379 for dPort in dPorts:
6380 cmdStr += " " + str( dPort )
6381 handle = self.sendline( cmdStr )
6382 assert handle is not None, "Error in sendline"
6383 assert "Command not found:" not in handle, handle
6384 assert "Unsupported command:" not in handle, handle
6385 assert "Error executing command" not in handle, handle
6386 if "Added the mcast route" in handle:
6387 return main.TRUE
6388 else:
6389 return main.FALSE
6390 except AssertionError:
6391 main.log.exception( "" )
6392 return None
6393 except TypeError:
6394 main.log.exception( self.name + ": Object not as expected" )
6395 return None
6396 except pexpect.EOF:
6397 main.log.error( self.name + ": EOF exception found" )
6398 main.log.error( self.name + ": " + self.handle.before )
6399 main.cleanAndExit()
6400 except Exception:
6401 main.log.exception( self.name + ": Uncaught exception!" )
6402 main.cleanAndExit()
6403
6404 def mcastDelete( self, sIP, groupIP, dPorts ):
6405 """
6406 Delete a multicast route by calling 'mcast-delete' command
6407 sIP: source IP of the multicast route
6408 groupIP: group IP of the multicast route
6409 dPorts: a list of destination ports of the multicast route
6410 Returns main.TRUE if mcast route is deleted; Otherwise main.FALSE
6411 """
6412 try:
6413 cmdStr = "mcast-delete"
6414 cmdStr += " " + str( sIP )
6415 cmdStr += " " + str( groupIP )
6416 assert isinstance( dPorts, list )
6417 for dPort in dPorts:
6418 cmdStr += " " + str( dPort )
6419 handle = self.sendline( cmdStr )
6420 assert handle is not None, "Error in sendline"
6421 assert "Command not found:" not in handle, handle
6422 assert "Unsupported command:" not in handle, handle
6423 assert "Error executing command" not in handle, handle
6424 if "Updated the mcast route" in handle:
6425 return main.TRUE
6426 else:
6427 return main.FALSE
6428 except AssertionError:
6429 main.log.exception( "" )
6430 return None
6431 except TypeError:
6432 main.log.exception( self.name + ": Object not as expected" )
6433 return None
6434 except pexpect.EOF:
6435 main.log.error( self.name + ": EOF exception found" )
6436 main.log.error( self.name + ": " + self.handle.before )
6437 main.cleanAndExit()
6438 except Exception:
6439 main.log.exception( self.name + ": Uncaught exception!" )
6440 main.cleanAndExit()
6441
6442 def mcastHostJoin( self, sAddr, gAddr, srcs, sinks ):
6443 """
6444 Create a multicast route by calling 'mcast-host-join' command
6445 sAddr: we can provide * for ASM or a specific address for SSM
6446 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006447 srcs: a list of HostId of the sources e.g. ["00:AA:00:00:00:01/None"]
You Wange24d6272018-03-27 21:18:50 -07006448 sinks: a list of HostId of the sinks e.g. ["00:AA:00:00:01:05/40"]
6449 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6450 """
6451 try:
6452 cmdStr = "mcast-host-join"
6453 cmdStr += " -sAddr " + str( sAddr )
6454 cmdStr += " -gAddr " + str( gAddr )
6455 assert isinstance( srcs, list )
6456 for src in srcs:
6457 cmdStr += " -srcs " + str( src )
6458 assert isinstance( sinks, list )
6459 for sink in sinks:
6460 cmdStr += " -sinks " + str( sink )
6461 handle = self.sendline( cmdStr )
6462 assert handle is not None, "Error in sendline"
6463 assert "Command not found:" not in handle, handle
6464 assert "Unsupported command:" not in handle, handle
6465 assert "Error executing command" not in handle, handle
6466 if "Added the mcast route" in handle:
6467 return main.TRUE
6468 else:
6469 return main.FALSE
6470 except AssertionError:
6471 main.log.exception( "" )
6472 return None
6473 except TypeError:
6474 main.log.exception( self.name + ": Object not as expected" )
6475 return None
6476 except pexpect.EOF:
6477 main.log.error( self.name + ": EOF exception found" )
6478 main.log.error( self.name + ": " + self.handle.before )
6479 main.cleanAndExit()
6480 except Exception:
6481 main.log.exception( self.name + ": Uncaught exception!" )
6482 main.cleanAndExit()
6483
6484 def mcastHostDelete( self, sAddr, gAddr, host=None ):
6485 """
6486 Delete multicast sink(s) by calling 'mcast-host-delete' command
6487 sAddr: we can provide * for ASM or a specific address for SSM
6488 gAddr: specifies multicast group address
You Wangc02d8352018-04-17 16:42:10 -07006489 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
You Wange24d6272018-03-27 21:18:50 -07006490 will delete the route if not specified
6491 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6492 """
6493 try:
6494 cmdStr = "mcast-host-delete"
6495 cmdStr += " -sAddr " + str( sAddr )
6496 cmdStr += " -gAddr " + str( gAddr )
6497 if host:
6498 cmdStr += " -h " + str( host )
6499 handle = self.sendline( cmdStr )
6500 assert handle is not None, "Error in sendline"
6501 assert "Command not found:" not in handle, handle
6502 assert "Unsupported command:" not in handle, handle
6503 assert "Error executing command" not in handle, handle
6504 if "Updated the mcast route" in handle:
6505 return main.TRUE
6506 elif "Deleted the mcast route" in handle:
6507 return main.TRUE
6508 else:
6509 return main.FALSE
6510 except AssertionError:
6511 main.log.exception( "" )
6512 return None
6513 except TypeError:
6514 main.log.exception( self.name + ": Object not as expected" )
6515 return None
6516 except pexpect.EOF:
6517 main.log.error( self.name + ": EOF exception found" )
6518 main.log.error( self.name + ": " + self.handle.before )
6519 main.cleanAndExit()
6520 except Exception:
6521 main.log.exception( self.name + ": Uncaught exception!" )
6522 main.cleanAndExit()
6523
You Wang547893e2018-05-08 13:34:59 -07006524 def mcastSinkDelete( self, sAddr, gAddr, sink=None ):
6525 """
6526 Delete multicast sink(s) by calling 'mcast-sink-delete' command
6527 sAddr: we can provide * for ASM or a specific address for SSM
6528 gAddr: specifies multicast group address
6529 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
6530 will delete the route if not specified
6531 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6532 """
6533 try:
6534 cmdStr = "mcast-sink-delete"
6535 cmdStr += " -sAddr " + str( sAddr )
6536 cmdStr += " -gAddr " + str( gAddr )
6537 if sink:
6538 cmdStr += " -s " + str( sink )
6539 handle = self.sendline( cmdStr )
6540 assert handle is not None, "Error in sendline"
6541 assert "Command not found:" not in handle, handle
6542 assert "Unsupported command:" not in handle, handle
6543 assert "Error executing command" not in handle, handle
6544 if "Updated the mcast route" in handle:
6545 return main.TRUE
6546 elif "Deleted the mcast route" in handle:
6547 return main.TRUE
6548 else:
6549 return main.FALSE
6550 except AssertionError:
6551 main.log.exception( "" )
6552 return None
6553 except TypeError:
6554 main.log.exception( self.name + ": Object not as expected" )
6555 return None
6556 except pexpect.EOF:
6557 main.log.error( self.name + ": EOF exception found" )
6558 main.log.error( self.name + ": " + self.handle.before )
6559 main.cleanAndExit()
6560 except Exception:
6561 main.log.exception( self.name + ": Uncaught exception!" )
6562 main.cleanAndExit()
6563
You Wange24d6272018-03-27 21:18:50 -07006564 def mcastSourceDelete( self, sAddr, gAddr, srcs=None ):
6565 """
6566 Delete multicast src(s) by calling 'mcast-source-delete' command
6567 sAddr: we can provide * for ASM or a specific address for SSM
6568 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006569 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 -07006570 will delete the route if not specified
6571 Returns main.TRUE if mcast sink is deleted; Otherwise main.FALSE
6572 """
6573 try:
6574 cmdStr = "mcast-source-delete"
6575 cmdStr += " -sAddr " + str( sAddr )
6576 cmdStr += " -gAddr " + str( gAddr )
6577 if srcs:
6578 assert isinstance( srcs, list )
6579 for src in srcs:
6580 cmdStr += " -src " + str( src )
6581 handle = self.sendline( cmdStr )
6582 assert handle is not None, "Error in sendline"
6583 assert "Command not found:" not in handle, handle
6584 assert "Unsupported command:" not in handle, handle
6585 assert "Error executing command" not in handle, handle
6586 if "Updated the mcast route" in handle:
6587 return main.TRUE
6588 elif "Deleted the mcast route" in handle:
6589 return main.TRUE
6590 else:
6591 return main.FALSE
6592 except AssertionError:
6593 main.log.exception( "" )
6594 return None
6595 except TypeError:
6596 main.log.exception( self.name + ": Object not as expected" )
6597 return None
6598 except pexpect.EOF:
6599 main.log.error( self.name + ": EOF exception found" )
6600 main.log.error( self.name + ": " + self.handle.before )
6601 main.cleanAndExit()
6602 except Exception:
6603 main.log.exception( self.name + ": Uncaught exception!" )
6604 main.cleanAndExit()
You Wang5da39c82018-04-26 22:55:08 -07006605
6606 def netcfg( self, jsonFormat=True, args="" ):
6607 """
6608 Run netcfg cli command with given args
6609 """
6610 try:
6611 cmdStr = "netcfg"
6612 if jsonFormat:
6613 cmdStr = cmdStr + " -j"
6614 if args:
6615 cmdStr = cmdStr + " " + str( args )
6616 handle = self.sendline( cmdStr )
6617 assert handle is not None, "Error in sendline"
6618 assert "Command not found:" not in handle, handle
6619 assert "Unsupported command:" not in handle, handle
6620 assert "Error executing command" not in handle, handle
6621 return handle
6622 except AssertionError:
6623 main.log.exception( "" )
6624 return None
6625 except TypeError:
6626 main.log.exception( self.name + ": Object not as expected" )
6627 return None
6628 except pexpect.EOF:
6629 main.log.error( self.name + ": EOF exception found" )
6630 main.log.error( self.name + ": " + self.handle.before )
6631 main.cleanAndExit()
6632 except Exception:
6633 main.log.exception( self.name + ": Uncaught exception!" )
6634 main.cleanAndExit()
6635
You Wang0fa76e72018-05-18 11:33:25 -07006636 def composeT3Command( self, sAddr, dAddr, ipv6=False, verbose=True, simple=False ):
You Wang5da39c82018-04-26 22:55:08 -07006637 """
You Wang54b1d672018-06-11 16:44:13 -07006638 Compose and return a list of t3-troubleshoot cli commands for given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006639 Options:
6640 sAddr: IP address of the source host
6641 dAddr: IP address of the destination host
You Wang0fa76e72018-05-18 11:33:25 -07006642 ipv6: True if hosts are IPv6
6643 verbose: return verbose t3 output if True
6644 simple: compose command for t3-troubleshoot-simple if True
You Wang5da39c82018-04-26 22:55:08 -07006645 """
6646 try:
6647 # Collect information of both hosts from onos
6648 hosts = self.hosts()
6649 hosts = json.loads( hosts )
6650 sHost = None
6651 dHost = None
6652 for host in hosts:
6653 if sAddr in host[ "ipAddresses" ]:
6654 sHost = host
6655 elif dAddr in host[ "ipAddresses" ]:
6656 dHost = host
6657 if sHost and dHost:
6658 break
6659 assert sHost, "Not able to find host with IP {}".format( sAddr )
You Wang54b1d672018-06-11 16:44:13 -07006660 cmdList = []
You Wang5d9527b2018-05-29 17:08:54 -07006661 if simple:
6662 assert dHost, "Not able to find host with IP {}".format( dAddr )
You Wang54b1d672018-06-11 16:44:13 -07006663 cmdStr = "t3-troubleshoot-simple"
6664 if verbose:
6665 cmdStr += " -vv"
6666 if ipv6:
6667 cmdStr += " -et ipv6"
You Wang0fa76e72018-05-18 11:33:25 -07006668 cmdStr += " {}/{} {}/{}".format( sHost[ "mac" ], sHost[ "vlan" ], dHost[ "mac" ], dHost[ "vlan" ] )
You Wang54b1d672018-06-11 16:44:13 -07006669 cmdList.append( cmdStr )
You Wang0fa76e72018-05-18 11:33:25 -07006670 else:
You Wang54b1d672018-06-11 16:44:13 -07006671 for location in sHost[ "locations" ]:
6672 cmdStr = "t3-troubleshoot"
6673 if verbose:
6674 cmdStr += " -vv"
6675 if ipv6:
6676 cmdStr += " -et ipv6"
6677 cmdStr += " -s " + str( sAddr )
6678 cmdStr += " -sp " + str( location[ "elementId" ] ) + "/" + str( location[ "port" ] )
6679 cmdStr += " -sm " + str( sHost[ "mac" ] )
6680 if sHost[ "vlan" ] != "None":
6681 cmdStr += " -vid " + sHost[ "vlan" ]
6682 cmdStr += " -d " + str( dAddr )
6683 netcfg = self.netcfg( args="devices {}".format( location[ "elementId" ] ) )
6684 netcfg = json.loads( netcfg )
6685 assert netcfg, "Failed to get netcfg"
6686 cmdStr += " -dm " + str( netcfg[ "segmentrouting" ][ "routerMac" ] )
6687 cmdList.append( cmdStr )
6688 return cmdList
You Wang5da39c82018-04-26 22:55:08 -07006689 except AssertionError:
6690 main.log.exception( "" )
6691 return None
6692 except ( KeyError, TypeError ):
6693 main.log.exception( self.name + ": Object not as expected" )
6694 return None
6695 except Exception:
6696 main.log.exception( self.name + ": Uncaught exception!" )
6697 main.cleanAndExit()
6698
6699 def t3( self, sAddr, dAddr, ipv6=False ):
6700 """
You Wang54b1d672018-06-11 16:44:13 -07006701 Run t3-troubleshoot cli commands for all posible routes given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006702 Options:
6703 sAddr: IP address of the source host
6704 dAddr: IP address of the destination host
6705 """
6706 try:
You Wang54b1d672018-06-11 16:44:13 -07006707 cmdList = self.composeT3Command( sAddr, dAddr, ipv6 )
6708 assert cmdList is not None, "composeT3Command returned None"
6709 t3Output = ""
6710 for cmdStr in cmdList:
6711 handle = self.sendline( cmdStr )
6712 assert handle is not None, "Error in sendline"
6713 assert "Command not found:" not in handle, handle
6714 assert "Unsupported command:" not in handle, handle
6715 assert "Error executing command" not in handle, handle
6716 assert "Tracing packet" in handle
6717 t3Output += handle
6718 return t3Output
You Wang5da39c82018-04-26 22:55:08 -07006719 except AssertionError:
6720 main.log.exception( "" )
6721 return None
6722 except pexpect.EOF:
6723 main.log.error( self.name + ": EOF exception found" )
6724 main.log.error( self.name + ": " + self.handle.before )
6725 main.cleanAndExit()
6726 except Exception:
6727 main.log.exception( self.name + ": Uncaught exception!" )
6728 main.cleanAndExit()
Jon Hall3c0114c2020-08-11 15:07:42 -07006729
6730 def prepareForCLI( self, debug=True, maxRetries=120 ):
6731 """
6732 Prepare docker container to connect to onos cli
6733 """
6734 try:
6735 # Wait for log files to be created
6736 ready = 0
6737 retries = 0
6738 while not ready and retries < maxRetries:
6739 retries += 1
6740 self.handle.sendline( "ls -al /root/onos/apache-karaf-*/data/log" )
6741 ready = self.handle.expect( [ "No such file or directory", self.dockerPrompt ] )
6742 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6743 if not ready:
6744 self.handle.expect( self.dockerPrompt )
6745 time.sleep( 1 )
Jon Hall3c0114c2020-08-11 15:07:42 -07006746
6747 cmdList = []
6748 cmdList.append( "apt-get update" )
6749 cmdList.append( "apt-get install -y openssh-server" )
6750 # Some built in scripts are hardcoded
6751 cmdList.append( "ln -s /root/onos /opt/onos" )
6752 cmdList.append( "ln -s /root/onos/apache-karaf-*/data/log /opt/onos/log" )
6753 cmdList.append( "ls -al /opt/onos" )
6754 output = ""
6755 for cmdStr in cmdList:
6756 self.handle.sendline( cmdStr )
6757 self.handle.expect( self.dockerPrompt )
6758 self.handle.sendline( "" )
6759 self.handle.expect( self.dockerPrompt )
6760 handle = self.handle.before
6761 assert "command not found" not in handle, handle
6762 assert "No such file or directory" not in handle, handle
6763 output += handle
6764 if debug:
6765 main.log.debug( "%s: %s" % ( self.name, output ) )
6766 return output
6767 except AssertionError:
6768 main.log.exception( "" )
6769 return None
6770 except pexpect.EOF:
6771 main.log.error( self.name + ": EOF exception found" )
6772 main.log.error( self.name + ": " + self.handle.before )
6773 main.cleanAndExit()
6774 except Exception:
6775 main.log.exception( self.name + ": Uncaught exception!" )
6776 main.cleanAndExit()
6777
6778 def onosSecureSSH( self, userName="onos", userPWD="rocks" ):
6779 """
6780 Enables secure access to ONOS console
6781 by removing default users & keys.
6782
6783 bin/onos-user-password onos rocks
6784
6785 Returns: main.TRUE on success and main.FALSE on failure
6786 """
6787
6788 try:
6789 self.handle.sendline( "" )
6790 self.handle.expect( self.dockerPrompt )
6791
6792 self.handle.sendline( "[ ! -f ~/.ssh/id_rsa.pub ] && ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' -q" )
6793 self.handle.expect( self.dockerPrompt )
6794 main.log.debug( "%s: %s%s" % ( self.name, self.handle.before, self.handle.after ) )
6795
6796 self.handle.sendline( "bin/onos-user-key $(id -un) $(cut -d\\\\ -f2 ~/.ssh/id_rsa.pub)" )
6797 self.handle.expect( pexpect.TIMEOUT, timeout=10 )
6798 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6799
6800 self.handle.sendline( "bin/onos-user-password %s %s" % ( userName, userPWD ) )
6801 i = self.handle.expect( [ "usage",
6802 self.dockerPrompt,
6803 pexpect.TIMEOUT ] )
6804 if i == 0:
6805 # malformed command
6806 main.log.warn( self.name + ": Could not parse onos-user-password command" )
6807 self.handle.expect( self.dockerPrompt )
6808 return main.FALSE
6809 elif i == 1:
6810 # Process started
6811 main.log.info( self.name + ": SSH password added for user " + userName )
6812 return main.TRUE
6813 elif i == 2:
6814 # timeout
6815 main.log.error( self.name + ": Failed to secure onos ssh " )
6816 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6817 except pexpect.EOF:
6818 main.log.error( self.name + ": EOF exception found" )
6819 main.log.error( self.name + ": " + self.handle.before )
6820 main.cleanAndExit()
6821 except Exception:
6822 main.log.exception( self.name + ": Uncaught exception!" )
6823 main.cleanAndExit()