blob: 7a0641eaa7d5580c999a470eeab067e745a66054 [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 Hall3c0114c2020-08-11 15:07:42 -070061 self.dockerPrompt = None
You Wangdb8cd0a2016-05-26 15:19:45 -070062 self.graph = Graph()
Devin Limdc78e202017-06-09 18:30:07 -070063 super( OnosCliDriver, self ).__init__()
kelvin8ec71442015-01-15 16:57:00 -080064
Jeremy Ronquillo82705492017-10-18 14:19:55 -070065 def checkOptions( self, var, defaultVar ):
Devin Limdc78e202017-06-09 18:30:07 -070066 if var is None or var == "":
67 return defaultVar
68 return var
Jeremy Ronquillo82705492017-10-18 14:19:55 -070069
kelvin8ec71442015-01-15 16:57:00 -080070 def connect( self, **connectargs ):
71 """
andrewonlab95ce8322014-10-13 14:12:04 -040072 Creates ssh handle for ONOS cli.
kelvin8ec71442015-01-15 16:57:00 -080073 """
andrewonlab95ce8322014-10-13 14:12:04 -040074 try:
75 for key in connectargs:
kelvin8ec71442015-01-15 16:57:00 -080076 vars( self )[ key ] = connectargs[ key ]
Author Namee1c79982019-06-04 23:38:42 +010077 self.karafPrompt = self.user_name + "@root >"
andrew@onlab.us658ec012015-03-11 15:13:09 -070078 self.home = "~/onos"
andrewonlab95ce8322014-10-13 14:12:04 -040079 for key in self.options:
80 if key == "home":
Devin Limdc78e202017-06-09 18:30:07 -070081 self.home = self.options[ key ]
82 elif key == "karaf_username":
83 self.karafUser = self.options[ key ]
84 elif key == "karaf_password":
85 self.karafPass = self.options[ key ]
Jon Hall3c0114c2020-08-11 15:07:42 -070086 elif key == "docker_prompt":
87 self.dockerPrompt = self.options[ key ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -070088 self.home = self.checkOptions( self.home, "~/onos" )
89 self.karafUser = self.checkOptions( self.karafUser, self.user_name )
90 self.karafPass = self.checkOptions( self.karafPass, self.pwd )
Jon Hall3c0114c2020-08-11 15:07:42 -070091 self.dockerPrompt = self.checkOptions( self.dockerPrompt, "~/onos#" )
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
304 while tries < 5:
305 i = self.handle.expect( [
306 self.karafPrompt,
307 "Password:",
308 pexpect.TIMEOUT ], onosStartTimeout )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400309
andrewonlab3a7c3c72014-10-24 17:21:03 -0400310 if i == 0:
Jon Hall3c0114c2020-08-11 15:07:42 -0700311 main.log.info( str( ONOSIp ) + " CLI Started successfully" )
Hari Krishnae36ef212015-01-04 14:09:13 -0800312 if karafTimeout:
kelvin8ec71442015-01-15 16:57:00 -0800313 self.handle.sendline(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800314 "config:property-set -p org.apache.karaf.shell\
Jon Hall3c0114c2020-08-11 15:07:42 -0700315 sshIdleTimeout " +
kelvin8ec71442015-01-15 16:57:00 -0800316 karafTimeout )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800317 self.handle.expect( self.karafPrompt )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400318 return main.TRUE
Jon Hall3c0114c2020-08-11 15:07:42 -0700319 elif i == 1:
320 main.log.info( str( ONOSIp ) + " CLI asking for password" )
321 main.log.debug( "Sending %s" % self.karafPass )
322 self.handle.sendline( self.karafPass )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400323 else:
Jon Hall3c0114c2020-08-11 15:07:42 -0700324 # If failed, send ctrl+c to process and try again
325 main.log.info( "Starting CLI failed. Retrying..." )
326 self.handle.send( "\x03" )
327 self.handle.sendline( startCliCommand )
328 tries += 1
329 main.log.error( "Connection to CLI " + str( ONOSIp ) + " timeout" )
330 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -0800331 except TypeError:
332 main.log.exception( self.name + ": Object not as expected" )
333 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400334 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800335 main.log.error( self.name + ": EOF exception found" )
336 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700337 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800338 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800339 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700340 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400341
suibin zhang116647a2016-05-06 16:30:09 -0700342 def startCellCli( self, karafTimeout="",
343 commandlineTimeout=10, onosStartTimeout=60 ):
344 """
Jon Hall3c0114c2020-08-11 15:07:42 -0700345 Start CLI on onos cell handle.
suibin zhang116647a2016-05-06 16:30:09 -0700346
347 karafTimeout is an optional argument. karafTimeout value passed
348 by user would be used to set the current karaf shell idle timeout.
349 Note that when ever this property is modified the shell will exit and
350 the subsequent login would reflect new idle timeout.
351 Below is an example to start a session with 60 seconds idle timeout
352 ( input value is in milliseconds ):
353
354 tValue = "60000"
355
356 Note: karafTimeout is left as str so that this could be read
357 and passed to startOnosCli from PARAMS file as str.
358 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000359
suibin zhang116647a2016-05-06 16:30:09 -0700360 try:
361 self.handle.sendline( "" )
362 x = self.handle.expect( [
Jon Hall3c0114c2020-08-11 15:07:42 -0700363 self.Prompt(), self.karafPrompt ], commandlineTimeout )
suibin zhang116647a2016-05-06 16:30:09 -0700364
365 if x == 1:
366 main.log.info( "ONOS cli is already running" )
367 return main.TRUE
368
Jeremy Ronquilloec916a42018-02-02 13:05:57 -0800369 # Wait for onos start ( onos-wait-for-start ) and enter onos cli
suibin zhang116647a2016-05-06 16:30:09 -0700370 self.handle.sendline( "/opt/onos/bin/onos" )
371 i = self.handle.expect( [
Jon Hall6c9e2da2018-11-06 12:01:23 -0800372 self.karafPrompt,
suibin zhang116647a2016-05-06 16:30:09 -0700373 pexpect.TIMEOUT ], onosStartTimeout )
374
375 if i == 0:
376 main.log.info( self.name + " CLI Started successfully" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800377 if karafTimeout: # FIXME: This doesn't look right
suibin zhang116647a2016-05-06 16:30:09 -0700378 self.handle.sendline(
379 "config:property-set -p org.apache.karaf.shell\
380 sshIdleTimeout " +
381 karafTimeout )
Jon Hall3c0114c2020-08-11 15:07:42 -0700382 self.handle.expect( self.Prompt() )
suibin zhang116647a2016-05-06 16:30:09 -0700383 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800384 self.handle.expect( self.karafPrompt )
suibin zhang116647a2016-05-06 16:30:09 -0700385 return main.TRUE
386 else:
387 # If failed, send ctrl+c to process and try again
388 main.log.info( "Starting CLI failed. Retrying..." )
389 self.handle.send( "\x03" )
390 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800391 i = self.handle.expect( [ self.karafPrompt, pexpect.TIMEOUT ],
suibin zhang116647a2016-05-06 16:30:09 -0700392 timeout=30 )
393 if i == 0:
394 main.log.info( self.name + " CLI Started " +
395 "successfully after retry attempt" )
396 if karafTimeout:
397 self.handle.sendline(
398 "config:property-set -p org.apache.karaf.shell\
399 sshIdleTimeout " +
400 karafTimeout )
Jon Hall3c0114c2020-08-11 15:07:42 -0700401 self.handle.expect( self.Prompt() )
suibin zhang116647a2016-05-06 16:30:09 -0700402 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800403 self.handle.expect( self.karafPrompt )
suibin zhang116647a2016-05-06 16:30:09 -0700404 return main.TRUE
405 else:
406 main.log.error( "Connection to CLI " +
407 self.name + " timeout" )
408 return main.FALSE
409
410 except TypeError:
411 main.log.exception( self.name + ": Object not as expected" )
412 return None
413 except pexpect.EOF:
414 main.log.error( self.name + ": EOF exception found" )
415 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700416 main.cleanAndExit()
suibin zhang116647a2016-05-06 16:30:09 -0700417 except Exception:
418 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700419 main.cleanAndExit()
suibin zhang116647a2016-05-06 16:30:09 -0700420
Pratik Parab3b2ab5a2017-02-14 13:15:14 -0800421 def log( self, cmdStr, level="", noExit=False ):
kelvin-onlab9f541032015-02-04 16:19:53 -0800422 """
423 log the commands in the onos CLI.
kelvin-onlab338f5512015-02-06 10:53:16 -0800424 returns main.TRUE on success
Jon Hallefbd9792015-03-05 16:11:36 -0800425 returns main.FALSE if Error occurred
YPZhangebf9eb52016-05-12 15:20:24 -0700426 if noExit is True, TestON will not exit, but clean up
kelvin-onlab338f5512015-02-06 10:53:16 -0800427 Available level: DEBUG, TRACE, INFO, WARN, ERROR
428 Level defaults to INFO
Pratik Parab3b2ab5a2017-02-14 13:15:14 -0800429 if cmdStr has spaces then put quotes in the passed string
kelvin-onlab9f541032015-02-04 16:19:53 -0800430 """
431 try:
kelvin-onlab338f5512015-02-06 10:53:16 -0800432 lvlStr = ""
433 if level:
434 lvlStr = "--level=" + level
435
kelvin-onlab338f5512015-02-06 10:53:16 -0800436 self.handle.sendline( "log:log " + lvlStr + " " + cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -0700437 self.handle.expect( "log:log" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800438 self.handle.expect( self.karafPrompt )
kelvin-onlabfb521662015-02-27 09:52:40 -0800439
kelvin-onlab9f541032015-02-04 16:19:53 -0800440 response = self.handle.before
441 if re.search( "Error", response ):
Jon Halldac3eae2020-06-05 12:04:06 -0700442 main.log.debug( response )
kelvin-onlab9f541032015-02-04 16:19:53 -0800443 return main.FALSE
444 return main.TRUE
Jon Hall80daded2015-05-27 16:07:00 -0700445 except pexpect.TIMEOUT:
446 main.log.exception( self.name + ": TIMEOUT exception found" )
Jon Hall43060f62020-06-23 13:13:33 -0700447 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700448 if noExit:
449 main.cleanup()
450 return None
451 else:
Devin Lim44075962017-08-11 10:56:37 -0700452 main.cleanAndExit()
kelvin-onlab9f541032015-02-04 16:19:53 -0800453 except pexpect.EOF:
454 main.log.error( self.name + ": EOF exception found" )
455 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700456 if noExit:
457 main.cleanup()
458 return None
459 else:
Devin Lim44075962017-08-11 10:56:37 -0700460 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800461 except Exception:
kelvin-onlabfb521662015-02-27 09:52:40 -0800462 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700463 if noExit:
464 main.cleanup()
465 return None
466 else:
Devin Lim44075962017-08-11 10:56:37 -0700467 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400468
Jon Hall0e240372018-05-02 11:21:57 -0700469 def clearBuffer( self, debug=False, timeout=10, noExit=False ):
kelvin8ec71442015-01-15 16:57:00 -0800470 """
Jon Hall0e240372018-05-02 11:21:57 -0700471 Test cli connection and clear any left over output in the buffer
472 Optional Arguments:
473 debug - Defaults to False. If True, will enable debug logging.
474 timeout - Defaults to 10. Amount of time in seconds for a command to return
475 before a timeout.
476 noExit - Defaults to False. If True, will not exit TestON in the event of a
kelvin8ec71442015-01-15 16:57:00 -0800477 """
andrewonlaba18f6bf2014-10-13 19:31:54 -0400478 try:
Jon Halla495f562016-05-16 18:03:26 -0700479 # Try to reconnect if disconnected from cli
480 self.handle.sendline( "" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700481 i = self.handle.expect( [ self.karafPrompt,
482 self.Prompt(),
483 pexpect.TIMEOUT ] )
Jon Hall0e240372018-05-02 11:21:57 -0700484 response = self.handle.before
Jon Halla495f562016-05-16 18:03:26 -0700485 if i == 1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700486 main.log.error( self.name + ": onos cli session closed. " )
Jon Halla495f562016-05-16 18:03:26 -0700487 if self.onosIp:
488 main.log.warn( "Trying to reconnect " + self.onosIp )
489 reconnectResult = self.startOnosCli( self.onosIp )
490 if reconnectResult:
491 main.log.info( self.name + ": onos cli session reconnected." )
492 else:
493 main.log.error( self.name + ": reconnection failed." )
YPZhang14a4aa92016-07-15 13:37:15 -0700494 if noExit:
495 return None
496 else:
Devin Lim44075962017-08-11 10:56:37 -0700497 main.cleanAndExit()
Jon Halla495f562016-05-16 18:03:26 -0700498 else:
Devin Lim44075962017-08-11 10:56:37 -0700499 main.cleanAndExit()
Jon Halla495f562016-05-16 18:03:26 -0700500 if i == 2:
Jon Hall7a6ebfd2017-03-13 10:58:58 -0700501 main.log.warn( "Timeout when testing cli responsiveness" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700502 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
Jon Hall7a6ebfd2017-03-13 10:58:58 -0700503 self.handle.send( "\x03" ) # Send ctrl-c to clear previous output
Jon Hall6c9e2da2018-11-06 12:01:23 -0800504 self.handle.expect( self.karafPrompt )
Jon Halla495f562016-05-16 18:03:26 -0700505
Jon Hall0e240372018-05-02 11:21:57 -0700506 response += self.handle.before
Jon Hall14a03b52016-05-11 12:07:30 -0700507 if debug:
Jon Hall0e240372018-05-02 11:21:57 -0700508 main.log.debug( self.name + ": Raw output from sending ''" )
509 main.log.debug( self.name + ": " + repr( response ) )
510 except pexpect.TIMEOUT:
511 main.log.error( self.name + ": ONOS timeout" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700512 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
You Wang141b43b2018-06-26 16:50:18 -0700513 self.handle.send( "\x03" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800514 self.handle.expect( self.karafPrompt )
Jon Hall0e240372018-05-02 11:21:57 -0700515 return None
516 except pexpect.EOF:
517 main.log.error( self.name + ": EOF exception found" )
518 main.log.error( self.name + ": " + self.handle.before )
519 if noExit:
520 return None
521 else:
522 main.cleanAndExit()
523 except Exception:
524 main.log.exception( self.name + ": Uncaught exception!" )
525 if noExit:
526 return None
527 else:
528 main.cleanAndExit()
529
Jon Hall22e94ce2019-01-15 14:52:17 -0800530 def sendline( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False, relaxedRegex=True, expectJson=False ):
Jon Hall0e240372018-05-02 11:21:57 -0700531 """
532 A wrapper around pexpect's sendline/expect. Will return all the output from a given command
533
534 Required Arguments:
535 cmdStr - String to send to the pexpect session
536
537 Optional Arguments:
538 showResponse - Defaults to False. If True will log the response.
539 debug - Defaults to False. If True, will enable debug logging.
540 timeout - Defaults to 10. Amount of time in seconds for a command to return
541 before a timeout.
542 noExit - Defaults to False. If True, will not exit TestON in the event of a
543 closed channel, but instead return None
Jon Hall6c9e2da2018-11-06 12:01:23 -0800544 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 -0700545
546 Warning: There are no sanity checking to commands sent using this method.
547
548 """
549 try:
550 # Try to reconnect if disconnected from cli
551 self.clearBuffer( debug=debug, timeout=timeout, noExit=noExit )
552 if debug:
553 # NOTE: This adds an average of .4 seconds per call
Jon Hall14a03b52016-05-11 12:07:30 -0700554 logStr = "\"Sending CLI command: '" + cmdStr + "'\""
Jon Halle0f0b342017-04-18 11:43:47 -0700555 self.log( logStr, noExit=noExit )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800556 self.handle.sendline( cmdStr )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800557 self.handle.expect( self.karafPrompt, timeout )
Jon Hall63604932015-02-26 17:09:50 -0800558 response = self.handle.before
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000559 main.log.info( "Command '" + str( cmdStr ) + "' sent to "
Jon Hallc6793552016-01-19 14:18:37 -0800560 + self.name + "." )
Jon Hallc6358dd2015-04-10 12:44:28 -0700561 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700562 main.log.debug( self.name + ": Raw output" )
563 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700564
Jon Hall3c0114c2020-08-11 15:07:42 -0700565 response = self.cleanOutput( response, debug=debug )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800566 # Remove control codes from karaf 4.2.1
Jon Hall3c0114c2020-08-11 15:07:42 -0700567 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 -0800568 response = karafEscape.sub( '', response )
569 if debug:
570 main.log.debug( self.name + ": karafEscape output" )
571 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700572 # Remove ANSI color control strings from output
Jon Hall43060f62020-06-23 13:13:33 -0700573 response = self.cleanOutput( response, debug )
Jon Hallc6358dd2015-04-10 12:44:28 -0700574
Jon Hall6c9e2da2018-11-06 12:01:23 -0800575 # Remove ANSI color control strings from output
Jon Hallcf31d0f2018-12-13 11:18:48 -0800576 # NOTE: karaf is sometimes adding a single character then two
577 # backspaces and sometimes adding 2 characters with 2 backspaces??
Jon Hall3c0114c2020-08-11 15:07:42 -0700578 backspaceEscape = re.compile( r'((.|\s)\x08)' )
579 unchanged = False
580 while not unchanged:
581 old = response
582 response = backspaceEscape.sub( '', response, count=1 )
583 if debug:
584 main.log.debug( self.name + ": backspaceEscape output" )
585 main.log.debug( self.name + ": " + repr( response ) )
586 unchanged = old == response
Jon Hall6c9e2da2018-11-06 12:01:23 -0800587
kelvin-onlabfb521662015-02-27 09:52:40 -0800588 # Remove extra return chars that get added
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000589 response = re.sub( r"\s\r", "", response )
Jon Hallc6358dd2015-04-10 12:44:28 -0700590 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700591 main.log.debug( self.name + ": Removed extra returns " +
592 "from output" )
593 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700594
595 # Strip excess whitespace
Jon Hall63604932015-02-26 17:09:50 -0800596 response = response.strip()
Jon Hallc6358dd2015-04-10 12:44:28 -0700597 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700598 main.log.debug( self.name + ": parsed and stripped output" )
599 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700600
Jon Hall63604932015-02-26 17:09:50 -0800601 # parse for just the output, remove the cmd from response
Jon Hallce0d70b2018-12-11 11:01:32 -0800602 cmdPattern = cmdStr.strip()
603 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
604 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800605 if relaxedRegex:
Jon Hallce0d70b2018-12-11 11:01:32 -0800606 cmdPattern = cmdPattern.split( '|' )[ -1 ].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 # This was added because karaf 4.2 is stripping some characters from the command echo
Jon Hallce0d70b2018-12-11 11:01:32 -0800610 output = response.split( cmdPattern, 1 )
Jon Hall22e94ce2019-01-15 14:52:17 -0800611 if expectJson:
612 main.log.warn( "Relaxed Regex: Searching for a json string amongst the output" )
613 jsonPattern = r'\{.*\}'
614 match = re.search( jsonPattern, output[ 0 ] )
615 if match:
616 output = [ '' , match.group( 0 ) ] # We expect a list with the second element to be the output
Jon Hall39e3ffe2018-12-05 11:40:29 -0800617 if len( output ) < 2:
618 main.log.warn( "Relaxing regex match to last 5 characters of the sent command" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800619 cmdPattern = cmdPattern[ -5: ]
620 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
621 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
622 output = response.split( cmdPattern, 1 )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800623 else:
Jon Hallce0d70b2018-12-11 11:01:32 -0800624 output = response.split( cmdPattern, 1 )
625 if len( output ) < 2: # TODO: Should we do this without the relaxedRegex flag?
Jon Hall8c9dd1c2018-11-14 15:40:39 -0800626 main.log.warn( "Relaxing regex match to last 5 characters of the sent command" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800627 output = response.split( cmdPattern[ -5: ], 1 )
Jon Hall0e240372018-05-02 11:21:57 -0700628 if output:
629 if debug:
630 main.log.debug( self.name + ": split output" )
631 for r in output:
632 main.log.debug( self.name + ": " + repr( r ) )
Jon Hallce0d70b2018-12-11 11:01:32 -0800633 if len( output ) == 1:
634 main.log.error( "Could not remove sent command echo from output" )
635 return output
Jon Hall0e240372018-05-02 11:21:57 -0700636 output = output[ 1 ].strip()
GlennRC85870432015-11-23 11:45:51 -0800637 if showResponse:
GlennRCed771242016-01-13 17:02:47 -0800638 main.log.info( "Response from ONOS: {}".format( output ) )
Jon Hall0e240372018-05-02 11:21:57 -0700639 self.clearBuffer( debug=debug, timeout=timeout, noExit=noExit )
GlennRC85870432015-11-23 11:45:51 -0800640 return output
GlennRCed771242016-01-13 17:02:47 -0800641 except pexpect.TIMEOUT:
Jon Hall0e240372018-05-02 11:21:57 -0700642 main.log.error( self.name + ": ONOS timeout" )
GlennRCed771242016-01-13 17:02:47 -0800643 if debug:
Jon Hall3c0114c2020-08-11 15:07:42 -0700644 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
You Wang6b5e5ba2019-01-31 15:32:40 -0800645 self.exitFromCmd( self.karafPrompt, 100 )
GlennRCed771242016-01-13 17:02:47 -0800646 return None
Jon Hallc6358dd2015-04-10 12:44:28 -0700647 except IndexError:
648 main.log.exception( self.name + ": Object not as expected" )
Jon Halla495f562016-05-16 18:03:26 -0700649 main.log.debug( "response: {}".format( repr( response ) ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700650 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800651 except TypeError:
652 main.log.exception( self.name + ": Object not as expected" )
653 return None
andrewonlaba18f6bf2014-10-13 19:31:54 -0400654 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800655 main.log.error( self.name + ": EOF exception found" )
656 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700657 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700658 return None
659 else:
Devin Lim44075962017-08-11 10:56:37 -0700660 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800661 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800662 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700663 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700664 return None
665 else:
Devin Lim44075962017-08-11 10:56:37 -0700666 main.cleanAndExit()
andrewonlaba18f6bf2014-10-13 19:31:54 -0400667
Jon Halld5a94fb2018-11-13 14:32:23 -0800668 def lineCount( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False, relaxedRegex=True ):
669 """
670 A wrapper around sendline(). Will return the number of lines returned or None on error
671
672 Required Arguments:
673 cmdStr - String to send to the pexpect session
674
675 Optional Arguments:
676 showResponse - Defaults to False. If True will log the response.
677 debug - Defaults to False. If True, will enable debug logging.
678 timeout - Defaults to 10. Amount of time in seconds for a command to return
679 before a timeout.
680 noExit - Defaults to False. If True, will not exit TestON in the event of a
681 closed channel, but instead return None
682 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.
683
684 Warning: There are no sanity checking to commands sent using this method.
685
686 """
687 try:
688 numLines = self.sendline( cmdStr, showResponse, debug, timeout, noExit, relaxedRegex )
You Wang0ce8e0c2019-02-22 12:22:26 -0800689 parsed = re.search( "(\d+)", numLines )
Jon Hall8c9dd1c2018-11-14 15:40:39 -0800690 if not parsed:
691 main.log.error( "Warning, output of karaf's wc may have changed" )
692 return None
693 return parsed.group( 1 )
Jon Halld5a94fb2018-11-13 14:32:23 -0800694 except IndexError:
695 main.log.exception( self.name + ": Object not as expected" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800696 main.log.debug( "response: {}".format( repr( numLines ) ) )
Jon Halld5a94fb2018-11-13 14:32:23 -0800697 return None
698 except TypeError:
699 main.log.exception( self.name + ": Object not as expected" )
700 return None
701 except Exception:
702 main.log.exception( self.name + ": Uncaught exception!" )
703 if noExit:
704 return None
705 else:
706 main.cleanAndExit()
707
kelvin8ec71442015-01-15 16:57:00 -0800708 # IMPORTANT NOTE:
709 # For all cli commands, naming convention should match
kelvin-onlabd3b64892015-01-20 13:26:24 -0800710 # the cli command changing 'a:b' with 'aB'.
711 # Ex ) onos:topology > onosTopology
712 # onos:links > onosLinks
713 # feature:list > featureList
Jon Halle3f39ff2015-01-13 11:50:53 -0800714
kelvin-onlabd3b64892015-01-20 13:26:24 -0800715 def addNode( self, nodeId, ONOSIp, tcpPort="" ):
kelvin8ec71442015-01-15 16:57:00 -0800716 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400717 Adds a new cluster node by ID and address information.
718 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800719 * nodeId
720 * ONOSIp
andrewonlabc2d05aa2014-10-13 16:51:10 -0400721 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800722 * tcpPort
kelvin8ec71442015-01-15 16:57:00 -0800723 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400724 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800725 cmdStr = "add-node " + str( nodeId ) + " " +\
726 str( ONOSIp ) + " " + str( tcpPort )
727 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700728 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800729 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -0800730 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700731 main.log.error( self.name + ": Error in adding node" )
kelvin8ec71442015-01-15 16:57:00 -0800732 main.log.error( handle )
Jon Halle3f39ff2015-01-13 11:50:53 -0800733 return main.FALSE
andrewonlabc2d05aa2014-10-13 16:51:10 -0400734 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800735 main.log.info( "Node " + str( ONOSIp ) + " added" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400736 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800737 except AssertionError:
738 main.log.exception( "" )
739 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800740 except TypeError:
741 main.log.exception( self.name + ": Object not as expected" )
742 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400743 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800744 main.log.error( self.name + ": EOF exception found" )
745 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700746 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800747 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800748 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700749 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400750
kelvin-onlabd3b64892015-01-20 13:26:24 -0800751 def removeNode( self, nodeId ):
kelvin8ec71442015-01-15 16:57:00 -0800752 """
andrewonlab86dc3082014-10-13 18:18:38 -0400753 Removes a cluster by ID
754 Issues command: 'remove-node [<node-id>]'
755 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800756 * nodeId
kelvin8ec71442015-01-15 16:57:00 -0800757 """
andrewonlab86dc3082014-10-13 18:18:38 -0400758 try:
andrewonlab86dc3082014-10-13 18:18:38 -0400759
kelvin-onlabd3b64892015-01-20 13:26:24 -0800760 cmdStr = "remove-node " + str( nodeId )
Jon Hall08f61bc2015-04-13 16:00:30 -0700761 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700762 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800763 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700764 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700765 main.log.error( self.name + ": Error in removing node" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700766 main.log.error( handle )
767 return main.FALSE
768 else:
769 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800770 except AssertionError:
771 main.log.exception( "" )
772 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800773 except TypeError:
774 main.log.exception( self.name + ": Object not as expected" )
775 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400776 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800777 main.log.error( self.name + ": EOF exception found" )
778 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700779 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800780 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800781 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700782 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400783
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700784 def nodes( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800785 """
andrewonlab7c211572014-10-15 16:45:20 -0400786 List the nodes currently visible
787 Issues command: 'nodes'
Jon Hall61282e32015-03-19 11:34:11 -0700788 Optional argument:
789 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800790 """
andrewonlab7c211572014-10-15 16:45:20 -0400791 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700792 cmdStr = "nodes"
Jon Hall61282e32015-03-19 11:34:11 -0700793 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700794 cmdStr += " -j"
795 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700796 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800797 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -0700798 return output
Jon Hallc6793552016-01-19 14:18:37 -0800799 except AssertionError:
800 main.log.exception( "" )
801 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800802 except TypeError:
803 main.log.exception( self.name + ": Object not as expected" )
804 return None
andrewonlab7c211572014-10-15 16:45:20 -0400805 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800806 main.log.error( self.name + ": EOF exception found" )
807 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700808 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800809 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800810 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700811 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400812
kelvin8ec71442015-01-15 16:57:00 -0800813 def topology( self ):
814 """
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700815 Definition:
Jon Hall390696c2015-05-05 17:13:41 -0700816 Returns the output of topology command.
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700817 Return:
818 topology = current ONOS topology
kelvin8ec71442015-01-15 16:57:00 -0800819 """
andrewonlab95ce8322014-10-13 14:12:04 -0400820 try:
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700821 cmdStr = "topology -j"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800822 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800823 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800824 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700825 main.log.info( cmdStr + " returned: " + str( handle ) )
andrewonlab95ce8322014-10-13 14:12:04 -0400826 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800827 except AssertionError:
828 main.log.exception( "" )
Jon Halld4d4b372015-01-28 16:02:41 -0800829 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800830 except TypeError:
831 main.log.exception( self.name + ": Object not as expected" )
832 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400833 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800834 main.log.error( self.name + ": EOF exception found" )
835 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700836 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800837 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800838 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700839 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -0800840
jenkins7ead5a82015-03-13 10:28:21 -0700841 def deviceRemove( self, deviceId ):
842 """
843 Removes particular device from storage
844
845 TODO: refactor this function
846 """
847 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700848 cmdStr = "device-remove " + str( deviceId )
849 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800850 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800851 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700852 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700853 main.log.error( self.name + ": Error in removing device" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700854 main.log.error( handle )
855 return main.FALSE
856 else:
857 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800858 except AssertionError:
859 main.log.exception( "" )
860 return None
jenkins7ead5a82015-03-13 10:28:21 -0700861 except TypeError:
862 main.log.exception( self.name + ": Object not as expected" )
863 return None
864 except pexpect.EOF:
865 main.log.error( self.name + ": EOF exception found" )
866 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700867 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700868 except Exception:
869 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700870 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700871
You Wang3b9689a2018-08-30 12:24:00 -0700872 def devices( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -0800873 """
Jon Hall7b02d952014-10-17 20:14:54 -0400874 Lists all infrastructure devices or switches
andrewonlab86dc3082014-10-13 18:18:38 -0400875 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800876 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800877 """
andrewonlab86dc3082014-10-13 18:18:38 -0400878 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700879 cmdStr = "devices"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800880 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700881 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -0700882 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -0800883 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800884 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700885 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800886 except AssertionError:
887 main.log.exception( "" )
888 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800889 except TypeError:
890 main.log.exception( self.name + ": Object not as expected" )
891 return None
andrewonlab7c211572014-10-15 16:45:20 -0400892 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800893 main.log.error( self.name + ": EOF exception found" )
894 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700895 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800896 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800897 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700898 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400899
kelvin-onlabd3b64892015-01-20 13:26:24 -0800900 def balanceMasters( self ):
kelvin8ec71442015-01-15 16:57:00 -0800901 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800902 This balances the devices across all controllers
903 by issuing command: 'onos> onos:balance-masters'
904 If required this could be extended to return devices balanced output.
kelvin8ec71442015-01-15 16:57:00 -0800905 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800906 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800907 cmdStr = "onos:balance-masters"
Jon Hallc6358dd2015-04-10 12:44:28 -0700908 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800909 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800910 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700911 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700912 main.log.error( self.name + ": Error in balancing masters" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700913 main.log.error( handle )
914 return main.FALSE
915 else:
916 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800917 except AssertionError:
918 main.log.exception( "" )
919 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800920 except TypeError:
921 main.log.exception( self.name + ": Object not as expected" )
922 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800923 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800924 main.log.error( self.name + ": EOF exception found" )
925 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700926 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800927 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800928 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700929 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800930
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000931 def checkMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700932 """
933 Returns the output of the masters command.
934 Optional argument:
935 * jsonFormat - boolean indicating if you want output in json
936 """
937 try:
938 cmdStr = "onos:masters"
939 if jsonFormat:
940 cmdStr += " -j"
941 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700942 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800943 assert "Command not found:" not in output, output
acsmars24950022015-07-30 18:00:43 -0700944 return output
Jon Hallc6793552016-01-19 14:18:37 -0800945 except AssertionError:
946 main.log.exception( "" )
947 return None
acsmars24950022015-07-30 18:00:43 -0700948 except TypeError:
949 main.log.exception( self.name + ": Object not as expected" )
950 return None
951 except pexpect.EOF:
952 main.log.error( self.name + ": EOF exception found" )
953 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700954 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700955 except Exception:
956 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700957 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700958
Jon Hallc6793552016-01-19 14:18:37 -0800959 def checkBalanceMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700960 """
961 Uses the master command to check that the devices' leadership
962 is evenly divided
963
964 Dependencies: checkMasters() and summary()
965
Jon Hall6509dbf2016-06-21 17:01:17 -0700966 Returns main.TRUE if the devices are balanced
967 Returns main.FALSE if the devices are unbalanced
acsmars24950022015-07-30 18:00:43 -0700968 Exits on Exception
969 Returns None on TypeError
970 """
971 try:
Jon Hallc6793552016-01-19 14:18:37 -0800972 summaryOutput = self.summary()
973 totalDevices = json.loads( summaryOutput )[ "devices" ]
974 except ( TypeError, ValueError ):
975 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summaryOutput ) )
976 return None
977 try:
acsmars24950022015-07-30 18:00:43 -0700978 totalOwnedDevices = 0
Jon Hallc6793552016-01-19 14:18:37 -0800979 mastersOutput = self.checkMasters()
980 masters = json.loads( mastersOutput )
acsmars24950022015-07-30 18:00:43 -0700981 first = masters[ 0 ][ "size" ]
982 for master in masters:
983 totalOwnedDevices += master[ "size" ]
984 if master[ "size" ] > first + 1 or master[ "size" ] < first - 1:
985 main.log.error( "Mastership not balanced" )
986 main.log.info( "\n" + self.checkMasters( False ) )
987 return main.FALSE
Jon Halle0f0b342017-04-18 11:43:47 -0700988 main.log.info( "Mastership balanced between " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700989 str( len( masters ) ) + " masters" )
acsmars24950022015-07-30 18:00:43 -0700990 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800991 except ( TypeError, ValueError ):
992 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, mastersOutput ) )
acsmars24950022015-07-30 18:00:43 -0700993 return None
994 except pexpect.EOF:
995 main.log.error( self.name + ": EOF exception found" )
996 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700997 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700998 except Exception:
999 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001000 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -07001001
YPZhangfebf7302016-05-24 16:45:56 -07001002 def links( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -08001003 """
Jon Halle8217482014-10-17 13:49:14 -04001004 Lists all core links
1005 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001006 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001007 """
Jon Halle8217482014-10-17 13:49:14 -04001008 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001009 cmdStr = "links"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001010 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001011 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07001012 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001013 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001014 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001015 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001016 except AssertionError:
1017 main.log.exception( "" )
1018 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001019 except TypeError:
1020 main.log.exception( self.name + ": Object not as expected" )
1021 return None
Jon Halle8217482014-10-17 13:49:14 -04001022 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001023 main.log.error( self.name + ": EOF exception found" )
1024 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001025 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001026 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001027 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001028 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001029
You Wang3b9689a2018-08-30 12:24:00 -07001030 def ports( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -08001031 """
Jon Halle8217482014-10-17 13:49:14 -04001032 Lists all ports
1033 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001034 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001035 """
Jon Halle8217482014-10-17 13:49:14 -04001036 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001037 cmdStr = "ports"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001038 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001039 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -07001040 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001041 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001042 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001043 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001044 except AssertionError:
1045 main.log.exception( "" )
1046 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001047 except TypeError:
1048 main.log.exception( self.name + ": Object not as expected" )
1049 return None
Jon Halle8217482014-10-17 13:49:14 -04001050 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001051 main.log.error( self.name + ": EOF exception found" )
1052 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001053 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001054 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001055 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001056 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001057
kelvin-onlabd3b64892015-01-20 13:26:24 -08001058 def roles( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001059 """
Jon Hall983a1702014-10-28 18:44:22 -04001060 Lists all devices and the controllers with roles assigned to them
1061 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001062 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001063 """
andrewonlab7c211572014-10-15 16:45:20 -04001064 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001065 cmdStr = "roles"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001066 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001067 cmdStr += " -j"
1068 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001069 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001070 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001071 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001072 except AssertionError:
1073 main.log.exception( "" )
1074 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001075 except TypeError:
1076 main.log.exception( self.name + ": Object not as expected" )
1077 return None
Jon Hall983a1702014-10-28 18:44:22 -04001078 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001079 main.log.error( self.name + ": EOF exception found" )
1080 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001081 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001082 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001083 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001084 main.cleanAndExit()
Jon Hall983a1702014-10-28 18:44:22 -04001085
kelvin-onlabd3b64892015-01-20 13:26:24 -08001086 def getRole( self, deviceId ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001087 """
Jon Halle3f39ff2015-01-13 11:50:53 -08001088 Given the a string containing the json representation of the "roles"
1089 cli command and a partial or whole device id, returns a json object
1090 containing the roles output for the first device whose id contains
1091 "device_id"
Jon Hall983a1702014-10-28 18:44:22 -04001092
1093 Returns:
Jon Halle3f39ff2015-01-13 11:50:53 -08001094 A dict of the role assignments for the given device or
1095 None if no match
kelvin8ec71442015-01-15 16:57:00 -08001096 """
Jon Hall983a1702014-10-28 18:44:22 -04001097 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001098 if deviceId is None:
Jon Hall983a1702014-10-28 18:44:22 -04001099 return None
1100 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001101 rawRoles = self.roles()
1102 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001103 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001104 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001105 # print device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001106 if str( deviceId ) in device[ 'id' ]:
Jon Hall983a1702014-10-28 18:44:22 -04001107 return device
1108 return None
Jon Hallc6793552016-01-19 14:18:37 -08001109 except ( TypeError, ValueError ):
1110 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001111 return None
andrewonlab86dc3082014-10-13 18:18:38 -04001112 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001113 main.log.error( self.name + ": EOF exception found" )
1114 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001115 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001116 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001117 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001118 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001119
kelvin-onlabd3b64892015-01-20 13:26:24 -08001120 def rolesNotNull( self ):
kelvin8ec71442015-01-15 16:57:00 -08001121 """
Jon Hall94fd0472014-12-08 11:52:42 -08001122 Iterates through each device and checks if there is a master assigned
1123 Returns: main.TRUE if each device has a master
1124 main.FALSE any device has no master
kelvin8ec71442015-01-15 16:57:00 -08001125 """
Jon Hall94fd0472014-12-08 11:52:42 -08001126 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001127 rawRoles = self.roles()
1128 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001129 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001130 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001131 # print device
1132 if device[ 'master' ] == "none":
1133 main.log.warn( "Device has no master: " + str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08001134 return main.FALSE
1135 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08001136 except ( TypeError, ValueError ):
1137 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001138 return None
Jon Hall94fd0472014-12-08 11:52:42 -08001139 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001140 main.log.error( self.name + ": EOF exception found" )
1141 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001142 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001143 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001144 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001145 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001146
kelvin-onlabd3b64892015-01-20 13:26:24 -08001147 def paths( self, srcId, dstId ):
kelvin8ec71442015-01-15 16:57:00 -08001148 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001149 Returns string of paths, and the cost.
1150 Issues command: onos:paths <src> <dst>
kelvin8ec71442015-01-15 16:57:00 -08001151 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001152 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001153 cmdStr = "onos:paths " + str( srcId ) + " " + str( dstId )
1154 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001155 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001156 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08001157 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001158 main.log.error( self.name + ": Error in getting paths" )
kelvin8ec71442015-01-15 16:57:00 -08001159 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001160 else:
kelvin8ec71442015-01-15 16:57:00 -08001161 path = handle.split( ";" )[ 0 ]
1162 cost = handle.split( ";" )[ 1 ]
1163 return ( path, cost )
Jon Hallc6793552016-01-19 14:18:37 -08001164 except AssertionError:
1165 main.log.exception( "" )
1166 return ( handle, "Error" )
Jon Halld4d4b372015-01-28 16:02:41 -08001167 except TypeError:
1168 main.log.exception( self.name + ": Object not as expected" )
1169 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001170 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001171 main.log.error( self.name + ": EOF exception found" )
1172 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001173 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001174 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001175 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001176 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -08001177
kelvin-onlabd3b64892015-01-20 13:26:24 -08001178 def hosts( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001179 """
Jon Hallffb386d2014-11-21 13:43:38 -08001180 Lists all discovered hosts
Jon Hall42db6dc2014-10-24 19:03:48 -04001181 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001182 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001183 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001184 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001185 cmdStr = "hosts"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001186 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001187 cmdStr += " -j"
1188 handle = self.sendline( cmdStr )
Jeremyd9e4eb12016-04-13 12:09:06 -07001189 if handle:
1190 assert "Command not found:" not in handle, handle
Jon Hallbaf53162015-12-17 17:04:34 -08001191 # TODO: Maybe make this less hardcoded
1192 # ConsistentMap Exceptions
1193 assert "org.onosproject.store.service" not in handle
1194 # Node not leader
1195 assert "java.lang.IllegalStateException" not in handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001196 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001197 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07001198 main.log.exception( self.name + ": Error in processing '" + cmdStr + "' " +
Jeremy Songster6949cea2016-04-19 18:13:18 -07001199 "command: " + str( handle ) )
Jon Hallc6793552016-01-19 14:18:37 -08001200 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001201 except TypeError:
1202 main.log.exception( self.name + ": Object not as expected" )
1203 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001204 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001205 main.log.error( self.name + ": EOF exception found" )
1206 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001207 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001208 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001209 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001210 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001211
kelvin-onlabd3b64892015-01-20 13:26:24 -08001212 def getHost( self, mac ):
kelvin8ec71442015-01-15 16:57:00 -08001213 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001214 Return the first host from the hosts api whose 'id' contains 'mac'
Jon Halle3f39ff2015-01-13 11:50:53 -08001215
Jon Hallefbd9792015-03-05 16:11:36 -08001216 Note: mac must be a colon separated mac address, but could be a
Jon Halle3f39ff2015-01-13 11:50:53 -08001217 partial mac address
1218
Jon Hall42db6dc2014-10-24 19:03:48 -04001219 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08001220 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001221 try:
kelvin8ec71442015-01-15 16:57:00 -08001222 if mac is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04001223 return None
1224 else:
1225 mac = mac
kelvin-onlabd3b64892015-01-20 13:26:24 -08001226 rawHosts = self.hosts()
1227 hostsJson = json.loads( rawHosts )
kelvin8ec71442015-01-15 16:57:00 -08001228 # search json for the host with mac then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001229 for host in hostsJson:
kelvin8ec71442015-01-15 16:57:00 -08001230 # print "%s in %s?" % ( mac, host[ 'id' ] )
Jon Halld4d4b372015-01-28 16:02:41 -08001231 if not host:
1232 pass
1233 elif mac in host[ 'id' ]:
Jon Hall42db6dc2014-10-24 19:03:48 -04001234 return host
1235 return None
Jon Hallc6793552016-01-19 14:18:37 -08001236 except ( TypeError, ValueError ):
1237 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawHosts ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001238 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001239 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001240 main.log.error( self.name + ": EOF exception found" )
1241 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001242 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001243 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001244 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001245 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001246
kelvin-onlabd3b64892015-01-20 13:26:24 -08001247 def getHostsId( self, hostList ):
kelvin8ec71442015-01-15 16:57:00 -08001248 """
1249 Obtain list of hosts
andrewonlab3f0a4af2014-10-17 12:25:14 -04001250 Issues command: 'onos> hosts'
kelvin8ec71442015-01-15 16:57:00 -08001251
andrewonlab3f0a4af2014-10-17 12:25:14 -04001252 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001253 * hostList: List of hosts obtained by Mininet
andrewonlab3f0a4af2014-10-17 12:25:14 -04001254 IMPORTANT:
1255 This function assumes that you started your
kelvin8ec71442015-01-15 16:57:00 -08001256 topology with the option '--mac'.
andrewonlab3f0a4af2014-10-17 12:25:14 -04001257 Furthermore, it assumes that value of VLAN is '-1'
1258 Description:
kelvin8ec71442015-01-15 16:57:00 -08001259 Converts mininet hosts ( h1, h2, h3... ) into
1260 ONOS format ( 00:00:00:00:00:01/-1 , ... )
1261 """
andrewonlab3f0a4af2014-10-17 12:25:14 -04001262 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001263 onosHostList = []
andrewonlab3f0a4af2014-10-17 12:25:14 -04001264
kelvin-onlabd3b64892015-01-20 13:26:24 -08001265 for host in hostList:
kelvin8ec71442015-01-15 16:57:00 -08001266 host = host.replace( "h", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001267 hostHex = hex( int( host ) ).zfill( 12 )
1268 hostHex = str( hostHex ).replace( 'x', '0' )
1269 i = iter( str( hostHex ) )
1270 hostHex = ":".join( a + b for a, b in zip( i, i ) )
1271 hostHex = hostHex + "/-1"
1272 onosHostList.append( hostHex )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001273
kelvin-onlabd3b64892015-01-20 13:26:24 -08001274 return onosHostList
andrewonlab3f0a4af2014-10-17 12:25:14 -04001275
Jon Halld4d4b372015-01-28 16:02:41 -08001276 except TypeError:
1277 main.log.exception( self.name + ": Object not as expected" )
1278 return None
andrewonlab3f0a4af2014-10-17 12:25:14 -04001279 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001280 main.log.error( self.name + ": EOF exception found" )
1281 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001282 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001283 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001284 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001285 main.cleanAndExit()
andrewonlab3e15ead2014-10-15 14:21:34 -04001286
You Wangbc898b82018-05-03 16:22:34 -07001287 def verifyHostLocation( self, hostIp, location ):
1288 """
1289 Description:
1290 Verify the host given is discovered in all locations expected
1291 Required:
1292 hostIp: IP address of the host
1293 location: expected location(s) of the given host. ex. "of:0000000000000005/8"
1294 Could be a string or list
1295 Returns:
1296 main.TRUE if host is discovered on all locations provided
1297 main.FALSE otherwise
1298 """
You Wangbc898b82018-05-03 16:22:34 -07001299 locations = [ location ] if isinstance( location, str ) else location
1300 assert isinstance( locations, list ), "Wrong type of location: {}".format( type( location ) )
1301 try:
1302 hosts = self.hosts()
1303 hosts = json.loads( hosts )
1304 targetHost = None
1305 for host in hosts:
1306 if hostIp in host[ "ipAddresses" ]:
1307 targetHost = host
You Wangfd80ab42018-05-10 17:21:53 -07001308 assert targetHost, "Not able to find host with IP {}".format( hostIp )
You Wangbc898b82018-05-03 16:22:34 -07001309 result = main.TRUE
1310 locationsDiscovered = [ loc[ "elementId" ] + "/" + loc[ "port" ] for loc in targetHost[ "locations" ] ]
1311 for loc in locations:
1312 discovered = False
1313 for locDiscovered in locationsDiscovered:
You Wang547893e2018-05-08 13:34:59 -07001314 locToMatch = locDiscovered if "/" in loc else locDiscovered.split( "/" )[0]
1315 if loc == locToMatch:
You Wangbc898b82018-05-03 16:22:34 -07001316 main.log.debug( "Host {} discovered with location {}".format( hostIp, loc ) )
You Wang547893e2018-05-08 13:34:59 -07001317 discovered = True
You Wangbc898b82018-05-03 16:22:34 -07001318 break
1319 if discovered:
1320 locationsDiscovered.remove( locDiscovered )
1321 else:
1322 main.log.warn( "Host {} not discovered with location {}".format( hostIp, loc ) )
1323 result = main.FALSE
1324 if locationsDiscovered:
1325 main.log.warn( "Host {} is also discovered with location {}".format( hostIp, locationsDiscovered ) )
1326 result = main.FALSE
1327 return result
1328 except KeyError:
1329 main.log.exception( self.name + ": host data not as expected: " + hosts )
1330 return None
1331 except pexpect.EOF:
1332 main.log.error( self.name + ": EOF exception found" )
1333 main.log.error( self.name + ": " + self.handle.before )
1334 main.cleanAndExit()
1335 except Exception:
1336 main.log.exception( self.name + ": Uncaught exception" )
1337 return None
1338
You Wang53dba1e2018-02-02 17:45:44 -08001339 def verifyHostIp( self, hostList=[], prefix="" ):
1340 """
1341 Description:
1342 Verify that all hosts have IP address assigned to them
1343 Optional:
1344 hostList: If specified, verifications only happen to the hosts
1345 in hostList
1346 prefix: at least one of the ip address assigned to the host
1347 needs to have the specified prefix
1348 Returns:
1349 main.TRUE if all hosts have specific IP address assigned;
1350 main.FALSE otherwise
1351 """
You Wang53dba1e2018-02-02 17:45:44 -08001352 try:
1353 hosts = self.hosts()
1354 hosts = json.loads( hosts )
1355 if not hostList:
1356 hostList = [ host[ "id" ] for host in hosts ]
1357 for host in hosts:
1358 hostId = host[ "id" ]
1359 if hostId not in hostList:
1360 continue
1361 ipList = host[ "ipAddresses" ]
1362 main.log.debug( self.name + ": IP list on host " + str( hostId ) + ": " + str( ipList ) )
1363 if not ipList:
1364 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostId ) )
1365 else:
1366 if not any( ip.startswith( str( prefix ) ) for ip in ipList ):
1367 main.log.warn( self.name + ": None of the IPs on host " + str( hostId ) + " has prefix " + str( prefix ) )
1368 else:
1369 main.log.debug( self.name + ": Found matching IP on host " + str( hostId ) )
1370 hostList.remove( hostId )
1371 if hostList:
1372 main.log.warn( self.name + ": failed to verify IP on following hosts: " + str( hostList) )
Jon Hall43060f62020-06-23 13:13:33 -07001373 # Print info for debugging
1374 main.log.debug( self.name + ": hosts output: " + str( hosts ) )
You Wang53dba1e2018-02-02 17:45:44 -08001375 return main.FALSE
1376 else:
1377 return main.TRUE
1378 except KeyError:
1379 main.log.exception( self.name + ": host data not as expected: " + hosts )
1380 return None
1381 except pexpect.EOF:
1382 main.log.error( self.name + ": EOF exception found" )
1383 main.log.error( self.name + ": " + self.handle.before )
1384 main.cleanAndExit()
1385 except Exception:
1386 main.log.exception( self.name + ": Uncaught exception" )
1387 return None
1388
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001389 def addHostIntent( self, hostIdOne, hostIdTwo, vlanId="", setVlan="", encap="", bandwidth="" ):
kelvin8ec71442015-01-15 16:57:00 -08001390 """
andrewonlabe6745342014-10-17 14:29:13 -04001391 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001392 * hostIdOne: ONOS host id for host1
1393 * hostIdTwo: ONOS host id for host2
Jeremy Songster832f9e92016-05-05 14:30:49 -07001394 Optional:
1395 * vlanId: specify a VLAN id for the intent
Jeremy Songsterff553672016-05-12 17:06:23 -07001396 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001397 * encap: specify an encapsulation type
andrewonlabe6745342014-10-17 14:29:13 -04001398 Description:
Jon Hallefbd9792015-03-05 16:11:36 -08001399 Adds a host-to-host intent ( bidirectional ) by
Jon Hallb1290e82014-11-18 16:17:48 -05001400 specifying the two hosts.
kelvin-onlabfb521662015-02-27 09:52:40 -08001401 Returns:
1402 A string of the intent id or None on Error
kelvin8ec71442015-01-15 16:57:00 -08001403 """
andrewonlabe6745342014-10-17 14:29:13 -04001404 try:
Jeremy Songster832f9e92016-05-05 14:30:49 -07001405 cmdStr = "add-host-intent "
1406 if vlanId:
1407 cmdStr += "-v " + str( vlanId ) + " "
Jeremy Songsterff553672016-05-12 17:06:23 -07001408 if setVlan:
1409 cmdStr += "--setVlan " + str( vlanId ) + " "
Jeremy Songsterc032f162016-08-04 17:14:49 -07001410 if encap:
1411 cmdStr += "--encapsulation " + str( encap ) + " "
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001412 if bandwidth:
1413 cmdStr += "-b " + str( bandwidth ) + " "
Jeremy Songster832f9e92016-05-05 14:30:49 -07001414 cmdStr += str( hostIdOne ) + " " + str( hostIdTwo )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001415 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001416 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001417 assert "Command not found:" not in handle, handle
Hari Krishnaac4e1782015-01-26 12:09:12 -08001418 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001419 main.log.error( self.name + ": Error in adding Host intent" )
Jon Hall61282e32015-03-19 11:34:11 -07001420 main.log.debug( "Response from ONOS was: " + repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001421 return None
Hari Krishnaac4e1782015-01-26 12:09:12 -08001422 else:
1423 main.log.info( "Host intent installed between " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001424 str( hostIdOne ) + " and " + str( hostIdTwo ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001425 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001426 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001427 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001428 else:
1429 main.log.error( "Error, intent ID not found" )
Jon Hall61282e32015-03-19 11:34:11 -07001430 main.log.debug( "Response from ONOS was: " +
1431 repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001432 return None
Jon Hallc6793552016-01-19 14:18:37 -08001433 except AssertionError:
1434 main.log.exception( "" )
1435 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001436 except TypeError:
1437 main.log.exception( self.name + ": Object not as expected" )
1438 return None
andrewonlabe6745342014-10-17 14:29:13 -04001439 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001440 main.log.error( self.name + ": EOF exception found" )
1441 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001442 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001443 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001444 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001445 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04001446
kelvin-onlabd3b64892015-01-20 13:26:24 -08001447 def addOpticalIntent( self, ingressDevice, egressDevice ):
kelvin8ec71442015-01-15 16:57:00 -08001448 """
andrewonlab7b31d232014-10-24 13:31:47 -04001449 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001450 * ingressDevice: device id of ingress device
1451 * egressDevice: device id of egress device
andrewonlab7b31d232014-10-24 13:31:47 -04001452 Optional:
1453 TODO: Still needs to be implemented via dev side
kelvin-onlabfb521662015-02-27 09:52:40 -08001454 Description:
1455 Adds an optical intent by specifying an ingress and egress device
1456 Returns:
1457 A string of the intent id or None on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08001458 """
andrewonlab7b31d232014-10-24 13:31:47 -04001459 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001460 cmdStr = "add-optical-intent " + str( ingressDevice ) +\
1461 " " + str( egressDevice )
1462 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001463 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001464 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08001465 # If error, return error message
Jon Halle3f39ff2015-01-13 11:50:53 -08001466 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001467 main.log.error( self.name + ": Error in adding Optical intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001468 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001469 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001470 main.log.info( "Optical intent installed between " +
1471 str( ingressDevice ) + " and " +
1472 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001473 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001474 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001475 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001476 else:
1477 main.log.error( "Error, intent ID not found" )
1478 return None
Jon Hallc6793552016-01-19 14:18:37 -08001479 except AssertionError:
1480 main.log.exception( "" )
1481 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001482 except TypeError:
1483 main.log.exception( self.name + ": Object not as expected" )
1484 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001485 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001486 main.log.error( self.name + ": EOF exception found" )
1487 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001488 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001489 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001490 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001491 main.cleanAndExit()
andrewonlab7b31d232014-10-24 13:31:47 -04001492
kelvin-onlabd3b64892015-01-20 13:26:24 -08001493 def addPointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001494 self,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001495 ingressDevice,
1496 egressDevice,
1497 portIngress="",
1498 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001499 ethType="",
1500 ethSrc="",
1501 ethDst="",
1502 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001503 lambdaAlloc=False,
alisonda157272016-12-22 01:13:21 -08001504 protected=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001505 ipProto="",
1506 ipSrc="",
1507 ipDst="",
1508 tcpSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001509 tcpDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001510 vlanId="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001511 setVlan="",
1512 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001513 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001514 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001515 * ingressDevice: device id of ingress device
1516 * egressDevice: device id of egress device
andrewonlab289e4b72014-10-21 21:24:18 -04001517 Optional:
1518 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001519 * ethSrc: specify ethSrc ( i.e. src mac addr )
1520 * ethDst: specify ethDst ( i.e. dst mac addr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001521 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001522 * lambdaAlloc: if True, intent will allocate lambda
andrewonlab40ccd8b2014-11-06 16:23:34 -05001523 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001524 * ipProto: specify ip protocol
andrewonlabf77e0cb2014-11-11 17:17:59 -05001525 * ipSrc: specify ip source address
1526 * ipDst: specify ip destination address
1527 * tcpSrc: specify tcp source port
1528 * tcpDst: specify tcp destination port
Jeremy Songster832f9e92016-05-05 14:30:49 -07001529 * vlanId: specify vlan ID
Jeremy Songsterff553672016-05-12 17:06:23 -07001530 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001531 * encap: specify an Encapsulation type to use
andrewonlab4dbb4d82014-10-17 18:22:31 -04001532 Description:
kelvin8ec71442015-01-15 16:57:00 -08001533 Adds a point-to-point intent ( uni-directional ) by
andrewonlab289e4b72014-10-21 21:24:18 -04001534 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001535 Returns:
1536 A string of the intent id or None on error
andrewonlab289e4b72014-10-21 21:24:18 -04001537
Jon Halle3f39ff2015-01-13 11:50:53 -08001538 NOTE: This function may change depending on the
andrewonlab4dbb4d82014-10-17 18:22:31 -04001539 options developers provide for point-to-point
1540 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001541 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001542 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001543 cmd = "add-point-intent"
andrewonlab36af3822014-11-18 17:48:18 -05001544
Jeremy Songsterff553672016-05-12 17:06:23 -07001545 if ethType:
1546 cmd += " --ethType " + str( ethType )
1547 if ethSrc:
1548 cmd += " --ethSrc " + str( ethSrc )
1549 if ethDst:
1550 cmd += " --ethDst " + str( ethDst )
1551 if bandwidth:
1552 cmd += " --bandwidth " + str( bandwidth )
1553 if lambdaAlloc:
1554 cmd += " --lambda "
1555 if ipProto:
1556 cmd += " --ipProto " + str( ipProto )
1557 if ipSrc:
1558 cmd += " --ipSrc " + str( ipSrc )
1559 if ipDst:
1560 cmd += " --ipDst " + str( ipDst )
1561 if tcpSrc:
1562 cmd += " --tcpSrc " + str( tcpSrc )
1563 if tcpDst:
1564 cmd += " --tcpDst " + str( tcpDst )
1565 if vlanId:
1566 cmd += " -v " + str( vlanId )
1567 if setVlan:
1568 cmd += " --setVlan " + str( setVlan )
Jeremy Songsterc032f162016-08-04 17:14:49 -07001569 if encap:
1570 cmd += " --encapsulation " + str( encap )
alisonda157272016-12-22 01:13:21 -08001571 if protected:
1572 cmd += " --protect "
andrewonlab289e4b72014-10-21 21:24:18 -04001573
kelvin8ec71442015-01-15 16:57:00 -08001574 # Check whether the user appended the port
1575 # or provided it as an input
kelvin-onlabd3b64892015-01-20 13:26:24 -08001576 if "/" in ingressDevice:
1577 cmd += " " + str( ingressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001578 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001579 if not portIngress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001580 main.log.error( "You must specify the ingress port" )
kelvin8ec71442015-01-15 16:57:00 -08001581 # TODO: perhaps more meaningful return
kelvin-onlabfb521662015-02-27 09:52:40 -08001582 # Would it make sense to throw an exception and exit
1583 # the test?
1584 return None
andrewonlab36af3822014-11-18 17:48:18 -05001585
kelvin8ec71442015-01-15 16:57:00 -08001586 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001587 str( ingressDevice ) + "/" +\
1588 str( portIngress ) + " "
andrewonlab36af3822014-11-18 17:48:18 -05001589
kelvin-onlabd3b64892015-01-20 13:26:24 -08001590 if "/" in egressDevice:
1591 cmd += " " + str( egressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001592 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001593 if not portEgress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001594 main.log.error( "You must specify the egress port" )
1595 return None
Jon Halle3f39ff2015-01-13 11:50:53 -08001596
kelvin8ec71442015-01-15 16:57:00 -08001597 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001598 str( egressDevice ) + "/" +\
1599 str( portEgress )
kelvin8ec71442015-01-15 16:57:00 -08001600
kelvin-onlab898a6c62015-01-16 14:13:53 -08001601 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001602 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001603 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001604 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001605 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001606 main.log.error( self.name + ": Error in adding point-to-point intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001607 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001608 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001609 # TODO: print out all the options in this message?
1610 main.log.info( "Point-to-point intent installed between " +
1611 str( ingressDevice ) + " and " +
1612 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001613 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001614 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001615 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001616 else:
1617 main.log.error( "Error, intent ID not found" )
1618 return None
Jon Hallc6793552016-01-19 14:18:37 -08001619 except AssertionError:
1620 main.log.exception( "" )
1621 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001622 except TypeError:
1623 main.log.exception( self.name + ": Object not as expected" )
1624 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001625 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001626 main.log.error( self.name + ": EOF exception found" )
1627 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001628 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001629 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001630 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001631 main.cleanAndExit()
andrewonlab4dbb4d82014-10-17 18:22:31 -04001632
kelvin-onlabd3b64892015-01-20 13:26:24 -08001633 def addMultipointToSinglepointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001634 self,
shahshreyac2f97072015-03-19 17:04:29 -07001635 ingressDeviceList,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001636 egressDevice,
shahshreyac2f97072015-03-19 17:04:29 -07001637 portIngressList=None,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001638 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001639 ethType="",
1640 ethSrc="",
1641 ethDst="",
1642 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001643 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001644 ipProto="",
1645 ipSrc="",
1646 ipDst="",
1647 tcpSrc="",
1648 tcpDst="",
1649 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001650 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001651 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001652 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001653 partial=False,
1654 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001655 """
shahshreyad0c80432014-12-04 16:56:05 -08001656 Note:
shahshreya70622b12015-03-19 17:19:00 -07001657 This function assumes the format of all ingress devices
Jon Hallbe379602015-03-24 13:39:32 -07001658 is same. That is, all ingress devices include port numbers
1659 with a "/" or all ingress devices could specify device
1660 ids and port numbers seperately.
shahshreyad0c80432014-12-04 16:56:05 -08001661 Required:
Jon Hallbe379602015-03-24 13:39:32 -07001662 * ingressDeviceList: List of device ids of ingress device
shahshreyac2f97072015-03-19 17:04:29 -07001663 ( Atleast 2 ingress devices required in the list )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001664 * egressDevice: device id of egress device
shahshreyad0c80432014-12-04 16:56:05 -08001665 Optional:
1666 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001667 * ethSrc: specify ethSrc ( i.e. src mac addr )
1668 * ethDst: specify ethDst ( i.e. dst mac addr )
shahshreyad0c80432014-12-04 16:56:05 -08001669 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001670 * lambdaAlloc: if True, intent will allocate lambda
shahshreyad0c80432014-12-04 16:56:05 -08001671 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001672 * ipProto: specify ip protocol
shahshreyad0c80432014-12-04 16:56:05 -08001673 * ipSrc: specify ip source address
1674 * ipDst: specify ip destination address
1675 * tcpSrc: specify tcp source port
1676 * tcpDst: specify tcp destination port
1677 * setEthSrc: action to Rewrite Source MAC Address
1678 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001679 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001680 * setVlan: specify VLAN Id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001681 * encap: specify a type of encapsulation
shahshreyad0c80432014-12-04 16:56:05 -08001682 Description:
kelvin8ec71442015-01-15 16:57:00 -08001683 Adds a multipoint-to-singlepoint intent ( uni-directional ) by
shahshreyad0c80432014-12-04 16:56:05 -08001684 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001685 Returns:
1686 A string of the intent id or None on error
shahshreyad0c80432014-12-04 16:56:05 -08001687
Jon Halle3f39ff2015-01-13 11:50:53 -08001688 NOTE: This function may change depending on the
Jon Hallefbd9792015-03-05 16:11:36 -08001689 options developers provide for multipoint-to-singlepoint
shahshreyad0c80432014-12-04 16:56:05 -08001690 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001691 """
shahshreyad0c80432014-12-04 16:56:05 -08001692 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001693 cmd = "add-multi-to-single-intent"
shahshreyad0c80432014-12-04 16:56:05 -08001694
Jeremy Songsterff553672016-05-12 17:06:23 -07001695 if ethType:
1696 cmd += " --ethType " + str( ethType )
1697 if ethSrc:
1698 cmd += " --ethSrc " + str( ethSrc )
1699 if ethDst:
1700 cmd += " --ethDst " + str( ethDst )
1701 if bandwidth:
1702 cmd += " --bandwidth " + str( bandwidth )
1703 if lambdaAlloc:
1704 cmd += " --lambda "
1705 if ipProto:
1706 cmd += " --ipProto " + str( ipProto )
1707 if ipSrc:
1708 cmd += " --ipSrc " + str( ipSrc )
1709 if ipDst:
1710 cmd += " --ipDst " + str( ipDst )
1711 if tcpSrc:
1712 cmd += " --tcpSrc " + str( tcpSrc )
1713 if tcpDst:
1714 cmd += " --tcpDst " + str( tcpDst )
1715 if setEthSrc:
1716 cmd += " --setEthSrc " + str( setEthSrc )
1717 if setEthDst:
1718 cmd += " --setEthDst " + str( setEthDst )
1719 if vlanId:
1720 cmd += " -v " + str( vlanId )
1721 if setVlan:
1722 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001723 if partial:
1724 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001725 if encap:
1726 cmd += " --encapsulation " + str( encap )
shahshreyad0c80432014-12-04 16:56:05 -08001727
kelvin8ec71442015-01-15 16:57:00 -08001728 # Check whether the user appended the port
1729 # or provided it as an input
shahshreyac2f97072015-03-19 17:04:29 -07001730
1731 if portIngressList is None:
1732 for ingressDevice in ingressDeviceList:
1733 if "/" in ingressDevice:
1734 cmd += " " + str( ingressDevice )
1735 else:
1736 main.log.error( "You must specify " +
Jon Hallbe379602015-03-24 13:39:32 -07001737 "the ingress port" )
shahshreyac2f97072015-03-19 17:04:29 -07001738 # TODO: perhaps more meaningful return
1739 return main.FALSE
shahshreyad0c80432014-12-04 16:56:05 -08001740 else:
Jon Hall71ce4e72015-03-23 14:05:58 -07001741 if len( ingressDeviceList ) == len( portIngressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001742 for ingressDevice, portIngress in zip( ingressDeviceList,
1743 portIngressList ):
shahshreya70622b12015-03-19 17:19:00 -07001744 cmd += " " + \
1745 str( ingressDevice ) + "/" +\
1746 str( portIngress ) + " "
kelvin-onlab38143812015-04-01 15:03:01 -07001747 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001748 main.log.error( "Device list and port list does not " +
1749 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001750 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001751 if "/" in egressDevice:
1752 cmd += " " + str( egressDevice )
shahshreyad0c80432014-12-04 16:56:05 -08001753 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001754 if not portEgress:
kelvin8ec71442015-01-15 16:57:00 -08001755 main.log.error( "You must specify " +
1756 "the egress port" )
shahshreyad0c80432014-12-04 16:56:05 -08001757 return main.FALSE
Jon Halle3f39ff2015-01-13 11:50:53 -08001758
kelvin8ec71442015-01-15 16:57:00 -08001759 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001760 str( egressDevice ) + "/" +\
1761 str( portEgress )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001762 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001763 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001764 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001765 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001766 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001767 main.log.error( self.name + ": Error in adding multipoint-to-singlepoint " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001768 "intent" )
1769 return None
shahshreyad0c80432014-12-04 16:56:05 -08001770 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001771 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001772 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001773 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001774 else:
1775 main.log.error( "Error, intent ID not found" )
1776 return None
Jon Hallc6793552016-01-19 14:18:37 -08001777 except AssertionError:
1778 main.log.exception( "" )
1779 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001780 except TypeError:
1781 main.log.exception( self.name + ": Object not as expected" )
1782 return None
1783 except pexpect.EOF:
1784 main.log.error( self.name + ": EOF exception found" )
1785 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001786 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001787 except Exception:
1788 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001789 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001790
1791 def addSinglepointToMultipointIntent(
1792 self,
1793 ingressDevice,
1794 egressDeviceList,
1795 portIngress="",
1796 portEgressList=None,
1797 ethType="",
1798 ethSrc="",
1799 ethDst="",
1800 bandwidth="",
1801 lambdaAlloc=False,
1802 ipProto="",
1803 ipSrc="",
1804 ipDst="",
1805 tcpSrc="",
1806 tcpDst="",
1807 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001808 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001809 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001810 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001811 partial=False,
1812 encap="" ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001813 """
1814 Note:
1815 This function assumes the format of all egress devices
1816 is same. That is, all egress devices include port numbers
1817 with a "/" or all egress devices could specify device
1818 ids and port numbers seperately.
1819 Required:
1820 * EgressDeviceList: List of device ids of egress device
1821 ( Atleast 2 eress devices required in the list )
1822 * ingressDevice: device id of ingress device
1823 Optional:
1824 * ethType: specify ethType
1825 * ethSrc: specify ethSrc ( i.e. src mac addr )
1826 * ethDst: specify ethDst ( i.e. dst mac addr )
1827 * bandwidth: specify bandwidth capacity of link
1828 * lambdaAlloc: if True, intent will allocate lambda
1829 for the specified intent
1830 * ipProto: specify ip protocol
1831 * ipSrc: specify ip source address
1832 * ipDst: specify ip destination address
1833 * tcpSrc: specify tcp source port
1834 * tcpDst: specify tcp destination port
1835 * setEthSrc: action to Rewrite Source MAC Address
1836 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001837 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001838 * setVlan: specify VLAN ID treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001839 * encap: specify an encapsulation type
kelvin-onlabb9408212015-04-01 13:34:04 -07001840 Description:
1841 Adds a singlepoint-to-multipoint intent ( uni-directional ) by
1842 specifying device id's and optional fields
1843 Returns:
1844 A string of the intent id or None on error
1845
1846 NOTE: This function may change depending on the
1847 options developers provide for singlepoint-to-multipoint
1848 intent via cli
1849 """
1850 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001851 cmd = "add-single-to-multi-intent"
kelvin-onlabb9408212015-04-01 13:34:04 -07001852
Jeremy Songsterff553672016-05-12 17:06:23 -07001853 if ethType:
1854 cmd += " --ethType " + str( ethType )
1855 if ethSrc:
1856 cmd += " --ethSrc " + str( ethSrc )
1857 if ethDst:
1858 cmd += " --ethDst " + str( ethDst )
1859 if bandwidth:
1860 cmd += " --bandwidth " + str( bandwidth )
1861 if lambdaAlloc:
1862 cmd += " --lambda "
1863 if ipProto:
1864 cmd += " --ipProto " + str( ipProto )
1865 if ipSrc:
1866 cmd += " --ipSrc " + str( ipSrc )
1867 if ipDst:
1868 cmd += " --ipDst " + str( ipDst )
1869 if tcpSrc:
1870 cmd += " --tcpSrc " + str( tcpSrc )
1871 if tcpDst:
1872 cmd += " --tcpDst " + str( tcpDst )
1873 if setEthSrc:
1874 cmd += " --setEthSrc " + str( setEthSrc )
1875 if setEthDst:
1876 cmd += " --setEthDst " + str( setEthDst )
1877 if vlanId:
1878 cmd += " -v " + str( vlanId )
1879 if setVlan:
1880 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001881 if partial:
1882 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001883 if encap:
1884 cmd += " --encapsulation " + str( encap )
kelvin-onlabb9408212015-04-01 13:34:04 -07001885
1886 # Check whether the user appended the port
1887 # or provided it as an input
Jon Hall08f61bc2015-04-13 16:00:30 -07001888
kelvin-onlabb9408212015-04-01 13:34:04 -07001889 if "/" in ingressDevice:
1890 cmd += " " + str( ingressDevice )
1891 else:
1892 if not portIngress:
1893 main.log.error( "You must specify " +
1894 "the Ingress port" )
1895 return main.FALSE
1896
1897 cmd += " " +\
1898 str( ingressDevice ) + "/" +\
1899 str( portIngress )
1900
1901 if portEgressList is None:
1902 for egressDevice in egressDeviceList:
1903 if "/" in egressDevice:
1904 cmd += " " + str( egressDevice )
1905 else:
1906 main.log.error( "You must specify " +
1907 "the egress port" )
1908 # TODO: perhaps more meaningful return
1909 return main.FALSE
1910 else:
1911 if len( egressDeviceList ) == len( portEgressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001912 for egressDevice, portEgress in zip( egressDeviceList,
1913 portEgressList ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001914 cmd += " " + \
1915 str( egressDevice ) + "/" +\
1916 str( portEgress )
kelvin-onlab38143812015-04-01 15:03:01 -07001917 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001918 main.log.error( "Device list and port list does not " +
1919 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001920 return main.FALSE
kelvin-onlabb9408212015-04-01 13:34:04 -07001921 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001922 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001923 assert "Command not found:" not in handle, handle
kelvin-onlabb9408212015-04-01 13:34:04 -07001924 # If error, return error message
1925 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001926 main.log.error( self.name + ": Error in adding singlepoint-to-multipoint " +
kelvin-onlabb9408212015-04-01 13:34:04 -07001927 "intent" )
shahshreyac2f97072015-03-19 17:04:29 -07001928 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001929 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001930 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001931 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001932 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001933 else:
1934 main.log.error( "Error, intent ID not found" )
1935 return None
Jon Hallc6793552016-01-19 14:18:37 -08001936 except AssertionError:
1937 main.log.exception( "" )
1938 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001939 except TypeError:
1940 main.log.exception( self.name + ": Object not as expected" )
1941 return None
shahshreyad0c80432014-12-04 16:56:05 -08001942 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001943 main.log.error( self.name + ": EOF exception found" )
1944 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001945 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001946 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001947 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001948 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001949
Hari Krishna9e232602015-04-13 17:29:08 -07001950 def addMplsIntent(
1951 self,
1952 ingressDevice,
1953 egressDevice,
Hari Krishna87a17f12015-04-13 17:42:23 -07001954 ingressPort="",
1955 egressPort="",
Hari Krishna9e232602015-04-13 17:29:08 -07001956 ethType="",
1957 ethSrc="",
1958 ethDst="",
1959 bandwidth="",
1960 lambdaAlloc=False,
1961 ipProto="",
1962 ipSrc="",
1963 ipDst="",
1964 tcpSrc="",
1965 tcpDst="",
Hari Krishna87a17f12015-04-13 17:42:23 -07001966 ingressLabel="",
Hari Krishnadfff6672015-04-13 17:53:27 -07001967 egressLabel="",
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001968 priority="" ):
Hari Krishna9e232602015-04-13 17:29:08 -07001969 """
1970 Required:
1971 * ingressDevice: device id of ingress device
1972 * egressDevice: device id of egress device
1973 Optional:
1974 * ethType: specify ethType
1975 * ethSrc: specify ethSrc ( i.e. src mac addr )
1976 * ethDst: specify ethDst ( i.e. dst mac addr )
1977 * bandwidth: specify bandwidth capacity of link
1978 * lambdaAlloc: if True, intent will allocate lambda
1979 for the specified intent
1980 * ipProto: specify ip protocol
1981 * ipSrc: specify ip source address
1982 * ipDst: specify ip destination address
1983 * tcpSrc: specify tcp source port
1984 * tcpDst: specify tcp destination port
1985 * ingressLabel: Ingress MPLS label
1986 * egressLabel: Egress MPLS label
1987 Description:
1988 Adds MPLS intent by
1989 specifying device id's and optional fields
1990 Returns:
1991 A string of the intent id or None on error
1992
1993 NOTE: This function may change depending on the
1994 options developers provide for MPLS
1995 intent via cli
1996 """
1997 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001998 cmd = "add-mpls-intent"
Hari Krishna9e232602015-04-13 17:29:08 -07001999
Jeremy Songsterff553672016-05-12 17:06:23 -07002000 if ethType:
2001 cmd += " --ethType " + str( ethType )
2002 if ethSrc:
2003 cmd += " --ethSrc " + str( ethSrc )
2004 if ethDst:
2005 cmd += " --ethDst " + str( ethDst )
2006 if bandwidth:
2007 cmd += " --bandwidth " + str( bandwidth )
2008 if lambdaAlloc:
2009 cmd += " --lambda "
2010 if ipProto:
2011 cmd += " --ipProto " + str( ipProto )
2012 if ipSrc:
2013 cmd += " --ipSrc " + str( ipSrc )
2014 if ipDst:
2015 cmd += " --ipDst " + str( ipDst )
2016 if tcpSrc:
2017 cmd += " --tcpSrc " + str( tcpSrc )
2018 if tcpDst:
2019 cmd += " --tcpDst " + str( tcpDst )
2020 if ingressLabel:
2021 cmd += " --ingressLabel " + str( ingressLabel )
2022 if egressLabel:
2023 cmd += " --egressLabel " + str( egressLabel )
2024 if priority:
2025 cmd += " --priority " + str( priority )
Hari Krishna9e232602015-04-13 17:29:08 -07002026
2027 # Check whether the user appended the port
2028 # or provided it as an input
2029 if "/" in ingressDevice:
2030 cmd += " " + str( ingressDevice )
2031 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002032 if not ingressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002033 main.log.error( "You must specify the ingress port" )
2034 return None
2035
2036 cmd += " " + \
2037 str( ingressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002038 str( ingressPort ) + " "
Hari Krishna9e232602015-04-13 17:29:08 -07002039
2040 if "/" in egressDevice:
2041 cmd += " " + str( egressDevice )
2042 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002043 if not egressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002044 main.log.error( "You must specify the egress port" )
2045 return None
2046
2047 cmd += " " +\
2048 str( egressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002049 str( egressPort )
Hari Krishna9e232602015-04-13 17:29:08 -07002050
2051 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08002052 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002053 assert "Command not found:" not in handle, handle
Hari Krishna9e232602015-04-13 17:29:08 -07002054 # If error, return error message
2055 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002056 main.log.error( self.name + ": Error in adding mpls intent" )
Hari Krishna9e232602015-04-13 17:29:08 -07002057 return None
2058 else:
2059 # TODO: print out all the options in this message?
2060 main.log.info( "MPLS intent installed between " +
2061 str( ingressDevice ) + " and " +
2062 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002063 match = re.search( 'id=0x([\da-f]+),', handle )
Hari Krishna9e232602015-04-13 17:29:08 -07002064 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002065 return match.group()[ 3:-1 ]
Hari Krishna9e232602015-04-13 17:29:08 -07002066 else:
2067 main.log.error( "Error, intent ID not found" )
2068 return None
Jon Hallc6793552016-01-19 14:18:37 -08002069 except AssertionError:
2070 main.log.exception( "" )
2071 return None
Hari Krishna9e232602015-04-13 17:29:08 -07002072 except TypeError:
2073 main.log.exception( self.name + ": Object not as expected" )
2074 return None
2075 except pexpect.EOF:
2076 main.log.error( self.name + ": EOF exception found" )
2077 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002078 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002079 except Exception:
2080 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002081 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002082
Jon Hallefbd9792015-03-05 16:11:36 -08002083 def removeIntent( self, intentId, app='org.onosproject.cli',
2084 purge=False, sync=False ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002085 """
shahshreya1c818fc2015-02-26 13:44:08 -08002086 Remove intent for specified application id and intent id
Jon Hall61282e32015-03-19 11:34:11 -07002087 Optional args:-
shahshreya1c818fc2015-02-26 13:44:08 -08002088 -s or --sync: Waits for the removal before returning
Jon Hall61282e32015-03-19 11:34:11 -07002089 -p or --purge: Purge the intent from the store after removal
2090
Jon Halle3f39ff2015-01-13 11:50:53 -08002091 Returns:
Jon Hall6509dbf2016-06-21 17:01:17 -07002092 main.FALSE on error and
Jon Halle3f39ff2015-01-13 11:50:53 -08002093 cli output otherwise
kelvin-onlab898a6c62015-01-16 14:13:53 -08002094 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002095 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002096 cmdStr = "remove-intent"
shahshreya1c818fc2015-02-26 13:44:08 -08002097 if purge:
2098 cmdStr += " -p"
2099 if sync:
2100 cmdStr += " -s"
2101
2102 cmdStr += " " + app + " " + str( intentId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002103 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002104 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002105 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08002106 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002107 main.log.error( self.name + ": Error in removing intent" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002108 return main.FALSE
andrewonlab9a50dfe2014-10-17 17:22:31 -04002109 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002110 # TODO: Should this be main.TRUE
2111 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002112 except AssertionError:
2113 main.log.exception( "" )
2114 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002115 except TypeError:
2116 main.log.exception( self.name + ": Object not as expected" )
2117 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002118 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002119 main.log.error( self.name + ": EOF exception found" )
2120 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002121 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002122 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002123 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002124 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04002125
YPZhangfebf7302016-05-24 16:45:56 -07002126 def removeAllIntents( self, purge=False, sync=False, app='org.onosproject.cli', timeout=30 ):
Jeremy42df2e72016-02-23 16:37:46 -08002127 """
2128 Description:
2129 Remove all the intents
2130 Optional args:-
2131 -s or --sync: Waits for the removal before returning
2132 -p or --purge: Purge the intent from the store after removal
2133 Returns:
2134 Returns main.TRUE if all intents are removed, otherwise returns
2135 main.FALSE; Returns None for exception
2136 """
2137 try:
2138 cmdStr = "remove-intent"
2139 if purge:
2140 cmdStr += " -p"
2141 if sync:
2142 cmdStr += " -s"
2143
2144 cmdStr += " " + app
YPZhangfebf7302016-05-24 16:45:56 -07002145 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08002146 assert handle is not None, "Error in sendline"
Jeremy42df2e72016-02-23 16:37:46 -08002147 assert "Command not found:" not in handle, handle
2148 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002149 main.log.error( self.name + ": Error in removing intent" )
Jeremy42df2e72016-02-23 16:37:46 -08002150 return main.FALSE
2151 else:
2152 return main.TRUE
2153 except AssertionError:
2154 main.log.exception( "" )
2155 return None
2156 except TypeError:
2157 main.log.exception( self.name + ": Object not as expected" )
2158 return None
2159 except pexpect.EOF:
2160 main.log.error( self.name + ": EOF exception found" )
2161 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002162 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002163 except Exception:
2164 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002165 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002166
Hari Krishnaacabd5a2015-07-01 17:10:19 -07002167 def purgeWithdrawnIntents( self ):
Hari Krishna0ce0e152015-06-23 09:55:29 -07002168 """
2169 Purges all WITHDRAWN Intents
2170 """
2171 try:
2172 cmdStr = "purge-intents"
2173 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002174 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002175 assert "Command not found:" not in handle, handle
Hari Krishna0ce0e152015-06-23 09:55:29 -07002176 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002177 main.log.error( self.name + ": Error in purging intents" )
Hari Krishna0ce0e152015-06-23 09:55:29 -07002178 return main.FALSE
2179 else:
2180 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002181 except AssertionError:
2182 main.log.exception( "" )
2183 return None
Hari Krishna0ce0e152015-06-23 09:55:29 -07002184 except TypeError:
2185 main.log.exception( self.name + ": Object not as expected" )
2186 return None
2187 except pexpect.EOF:
2188 main.log.error( self.name + ": EOF exception found" )
2189 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002190 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002191 except Exception:
2192 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002193 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002194
Devin Lime6fe3c42017-10-18 16:28:40 -07002195 def wipeout( self ):
2196 """
2197 Wipe out the flows,intents,links,devices,hosts, and groups from the ONOS.
2198 """
2199 try:
2200 cmdStr = "wipe-out please"
2201 handle = self.sendline( cmdStr, timeout=60 )
2202 assert handle is not None, "Error in sendline"
2203 assert "Command not found:" not in handle, handle
2204 return main.TRUE
2205 except AssertionError:
2206 main.log.exception( "" )
2207 return None
2208 except TypeError:
2209 main.log.exception( self.name + ": Object not as expected" )
2210 return None
2211 except pexpect.EOF:
2212 main.log.error( self.name + ": EOF exception found" )
2213 main.log.error( self.name + ": " + self.handle.before )
2214 main.cleanAndExit()
2215 except Exception:
2216 main.log.exception( self.name + ": Uncaught exception!" )
2217 main.cleanAndExit()
2218
kelvin-onlabd3b64892015-01-20 13:26:24 -08002219 def routes( self, jsonFormat=False ):
kelvin8ec71442015-01-15 16:57:00 -08002220 """
kelvin-onlab898a6c62015-01-16 14:13:53 -08002221 NOTE: This method should be used after installing application:
2222 onos-app-sdnip
pingping-lin8b306ac2014-11-17 18:13:51 -08002223 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002224 * jsonFormat: enable output formatting in json
pingping-lin8b306ac2014-11-17 18:13:51 -08002225 Description:
2226 Obtain all routes in the system
kelvin8ec71442015-01-15 16:57:00 -08002227 """
pingping-lin8b306ac2014-11-17 18:13:51 -08002228 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002229 cmdStr = "routes"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002230 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002231 cmdStr += " -j"
2232 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002233 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002234 assert "Command not found:" not in handle, handle
pingping-lin8b306ac2014-11-17 18:13:51 -08002235 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002236 except AssertionError:
2237 main.log.exception( "" )
2238 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002239 except TypeError:
2240 main.log.exception( self.name + ": Object not as expected" )
2241 return None
pingping-lin8b306ac2014-11-17 18:13:51 -08002242 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002243 main.log.error( self.name + ": EOF exception found" )
2244 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002245 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002246 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002247 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002248 main.cleanAndExit()
pingping-lin8b306ac2014-11-17 18:13:51 -08002249
pingping-lin54b03372015-08-13 14:43:10 -07002250 def ipv4RouteNumber( self ):
2251 """
2252 NOTE: This method should be used after installing application:
2253 onos-app-sdnip
2254 Description:
2255 Obtain the total IPv4 routes number in the system
2256 """
2257 try:
Pratik Parab57963572017-05-09 11:37:54 -07002258 cmdStr = "routes -j"
pingping-lin54b03372015-08-13 14:43:10 -07002259 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002260 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002261 assert "Command not found:" not in handle, handle
pingping-lin54b03372015-08-13 14:43:10 -07002262 jsonResult = json.loads( handle )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002263 return len( jsonResult[ 'routes4' ] )
Jon Hallc6793552016-01-19 14:18:37 -08002264 except AssertionError:
2265 main.log.exception( "" )
2266 return None
2267 except ( TypeError, ValueError ):
2268 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002269 return None
2270 except pexpect.EOF:
2271 main.log.error( self.name + ": EOF exception found" )
2272 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002273 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002274 except Exception:
2275 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002276 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002277
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002278 # =============Function to check Bandwidth allocation========
Jon Hall0e240372018-05-02 11:21:57 -07002279 def allocations( self, jsonFormat = True ):
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002280 """
2281 Description:
2282 Obtain Bandwidth Allocation Information from ONOS cli.
2283 """
2284 try:
2285 cmdStr = "allocations"
2286 if jsonFormat:
2287 cmdStr += " -j"
Jon Hall0e240372018-05-02 11:21:57 -07002288 handle = self.sendline( cmdStr, timeout=300 )
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002289 assert handle is not None, "Error in sendline"
2290 assert "Command not found:" not in handle, handle
2291 return handle
2292 except AssertionError:
2293 main.log.exception( "" )
2294 return None
2295 except ( TypeError, ValueError ):
2296 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
2297 return None
2298 except pexpect.EOF:
2299 main.log.error( self.name + ": EOF exception found" )
2300 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002301 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002302 except Exception:
2303 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002304 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002305
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002306 def intents( self, jsonFormat = True, summary = False, **intentargs ):
kelvin8ec71442015-01-15 16:57:00 -08002307 """
andrewonlabe6745342014-10-17 14:29:13 -04002308 Description:
Jon Hallff566d52016-01-15 14:45:36 -08002309 Obtain intents from the ONOS cli.
2310 Optional:
2311 * jsonFormat: Enable output formatting in json, default to True
2312 * summary: Whether only output the intent summary, defaults to False
2313 * type: Only output a certain type of intent. This options is valid
2314 only when jsonFormat is True and summary is True.
kelvin-onlab898a6c62015-01-16 14:13:53 -08002315 """
andrewonlabe6745342014-10-17 14:29:13 -04002316 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002317 cmdStr = "intents"
pingping-lin8244a3b2015-09-16 13:36:56 -07002318 if summary:
2319 cmdStr += " -s"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002320 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002321 cmdStr += " -j"
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002322 handle = self.sendline( cmdStr, timeout=300 )
You Wangb5a55f72017-03-03 12:51:05 -08002323 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002324 assert "Command not found:" not in handle, handle
pingping-lin8244a3b2015-09-16 13:36:56 -07002325 args = utilities.parse_args( [ "TYPE" ], **intentargs )
acsmars5b5fbaf2015-09-18 10:38:20 -07002326 if "TYPE" in args.keys():
Jon Hallff566d52016-01-15 14:45:36 -08002327 intentType = args[ "TYPE" ]
acsmars5b5fbaf2015-09-18 10:38:20 -07002328 else:
Jon Hallff566d52016-01-15 14:45:36 -08002329 intentType = ""
2330 # IF we want the summary of a specific intent type
2331 if jsonFormat and summary and ( intentType != "" ):
pingping-lin8244a3b2015-09-16 13:36:56 -07002332 jsonResult = json.loads( handle )
Jon Hallff566d52016-01-15 14:45:36 -08002333 if intentType in jsonResult.keys():
2334 return jsonResult[ intentType ]
pingping-lin8244a3b2015-09-16 13:36:56 -07002335 else:
Jon Hallff566d52016-01-15 14:45:36 -08002336 main.log.error( "unknown TYPE, returning all types of intents" )
pingping-lin8244a3b2015-09-16 13:36:56 -07002337 return handle
2338 else:
2339 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002340 except AssertionError:
2341 main.log.exception( "" )
2342 return None
2343 except ( TypeError, ValueError ):
2344 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002345 return None
2346 except pexpect.EOF:
2347 main.log.error( self.name + ": EOF exception found" )
2348 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002349 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002350 except Exception:
2351 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002352 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002353
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002354 def getIntentState( self, intentsId, intentsJson=None ):
kelvin-onlab54400a92015-02-26 18:05:51 -08002355 """
You Wangfdcbfc42016-05-16 12:16:53 -07002356 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002357 Gets intent state. Accepts a single intent ID (string type) or a
You Wangfdcbfc42016-05-16 12:16:53 -07002358 list of intent IDs.
2359 Parameters:
2360 intentsId: intent ID, both string type and list type are acceptable
kelvin-onlab54400a92015-02-26 18:05:51 -08002361 intentsJson: parsed json object from the onos:intents api
You Wangfdcbfc42016-05-16 12:16:53 -07002362 Returns:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002363 Returns the state (string type) of the ID if a single intent ID is
You Wangfdcbfc42016-05-16 12:16:53 -07002364 accepted.
2365 Returns a list of dictionaries if a list of intent IDs is accepted,
2366 and each dictionary maps 'id' to the Intent ID and 'state' to
2367 corresponding intent state.
kelvin-onlab54400a92015-02-26 18:05:51 -08002368 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002369
kelvin-onlab54400a92015-02-26 18:05:51 -08002370 try:
2371 state = "State is Undefined"
2372 if not intentsJson:
Jon Hallc6793552016-01-19 14:18:37 -08002373 rawJson = self.intents()
kelvin-onlab54400a92015-02-26 18:05:51 -08002374 else:
Jon Hallc6793552016-01-19 14:18:37 -08002375 rawJson = intentsJson
2376 parsedIntentsJson = json.loads( rawJson )
Jon Hallefbd9792015-03-05 16:11:36 -08002377 if isinstance( intentsId, types.StringType ):
Jon Hallc6793552016-01-19 14:18:37 -08002378 for intent in parsedIntentsJson:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002379 if intentsId == intent[ 'id' ]:
2380 state = intent[ 'state' ]
kelvin-onlab54400a92015-02-26 18:05:51 -08002381 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002382 main.log.info( "Cannot find intent ID" + str( intentsId ) +
Jon Hall53158082017-05-18 11:17:00 -07002383 " in the list" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002384 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002385 elif isinstance( intentsId, types.ListType ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002386 dictList = []
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002387 for i in xrange( len( intentsId ) ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002388 stateDict = {}
Jon Hall53158082017-05-18 11:17:00 -07002389 for intent in parsedIntentsJson:
2390 if intentsId[ i ] == intent[ 'id' ]:
2391 stateDict[ 'state' ] = intent[ 'state' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002392 stateDict[ 'id' ] = intentsId[ i ]
Jon Hallefbd9792015-03-05 16:11:36 -08002393 dictList.append( stateDict )
kelvin-onlab54400a92015-02-26 18:05:51 -08002394 break
Jon Hallefbd9792015-03-05 16:11:36 -08002395 if len( intentsId ) != len( dictList ):
Jon Hall53158082017-05-18 11:17:00 -07002396 main.log.warn( "Could not find all intents in ONOS output" )
2397 main.log.debug( "expected ids: {} \n ONOS intents: {}".format( intentsId, parsedIntentsJson ) )
kelvin-onlab07dbd012015-03-04 16:29:39 -08002398 return dictList
kelvin-onlab54400a92015-02-26 18:05:51 -08002399 else:
Jon Hall53158082017-05-18 11:17:00 -07002400 main.log.info( "Invalid type for intentsId argument" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002401 return None
Jon Hallc6793552016-01-19 14:18:37 -08002402 except ( TypeError, ValueError ):
2403 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
kelvin-onlab54400a92015-02-26 18:05:51 -08002404 return None
2405 except pexpect.EOF:
2406 main.log.error( self.name + ": EOF exception found" )
2407 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002408 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002409 except Exception:
kelvin-onlab54400a92015-02-26 18:05:51 -08002410 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002411 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07002412
Jon Hallf539eb92017-05-22 17:18:42 -07002413 def checkIntentState( self, intentsId, expectedState='INSTALLED' ):
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002414 """
2415 Description:
2416 Check intents state
2417 Required:
2418 intentsId - List of intents ID to be checked
2419 Optional:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002420 expectedState - Check the expected state(s) of each intents
kelvin-onlabf512e942015-06-08 19:42:59 -07002421 state in the list.
2422 *NOTE: You can pass in a list of expected state,
2423 Eg: expectedState = [ 'INSTALLED' , 'INSTALLING' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002424 Return:
Jon Hall53158082017-05-18 11:17:00 -07002425 Returns main.TRUE only if all intent are the same as expected states,
2426 otherwise returns main.FALSE.
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002427 """
2428 try:
kelvin-onlabf512e942015-06-08 19:42:59 -07002429 returnValue = main.TRUE
Jon Hallf539eb92017-05-22 17:18:42 -07002430 # Generating a dictionary: intent id as a key and state as value
Devin Lim752dd7b2017-06-27 14:40:03 -07002431
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002432 # intentsDict = self.getIntentState( intentsId )
Devin Lim752dd7b2017-06-27 14:40:03 -07002433 intentsDict = []
2434 for intent in json.loads( self.intents() ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002435 if isinstance( intentsId, types.StringType ) \
2436 and intent.get( 'id' ) == intentsId:
2437 intentsDict.append( intent )
2438 elif isinstance( intentsId, types.ListType ) \
Devin Lim752dd7b2017-06-27 14:40:03 -07002439 and any( intent.get( 'id' ) == ids for ids in intentsId ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002440 intentsDict.append( intent )
Devin Lim752dd7b2017-06-27 14:40:03 -07002441
2442 if not intentsDict:
Jon Hallae04e622016-01-27 10:38:05 -08002443 main.log.info( self.name + ": There is something wrong " +
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002444 "getting intents state" )
2445 return main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002446
2447 if isinstance( expectedState, types.StringType ):
2448 for intents in intentsDict:
2449 if intents.get( 'state' ) != expectedState:
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002450 main.log.debug( self.name + " : Intent ID - " +
2451 intents.get( 'id' ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002452 " actual state = " +
2453 intents.get( 'state' )
2454 + " does not equal expected state = "
2455 + expectedState )
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002456 returnValue = main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002457 elif isinstance( expectedState, types.ListType ):
2458 for intents in intentsDict:
2459 if not any( state == intents.get( 'state' ) for state in
2460 expectedState ):
2461 main.log.debug( self.name + " : Intent ID - " +
2462 intents.get( 'id' ) +
2463 " actual state = " +
2464 intents.get( 'state' ) +
2465 " does not equal expected states = "
2466 + str( expectedState ) )
2467 returnValue = main.FALSE
2468
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002469 if returnValue == main.TRUE:
2470 main.log.info( self.name + ": All " +
2471 str( len( intentsDict ) ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002472 " intents are in " + str( expectedState ) +
2473 " state" )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002474 return returnValue
2475 except TypeError:
2476 main.log.exception( self.name + ": Object not as expected" )
2477 return None
2478 except pexpect.EOF:
2479 main.log.error( self.name + ": EOF exception found" )
2480 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002481 main.cleanAndExit()
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002482 except Exception:
2483 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002484 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04002485
Jon Hallf539eb92017-05-22 17:18:42 -07002486 def compareBandwidthAllocations( self, expectedAllocations ):
2487 """
2488 Description:
2489 Compare the allocated bandwidth with the given allocations
2490 Required:
2491 expectedAllocations - The expected ONOS output of the allocations command
2492 Return:
2493 Returns main.TRUE only if all intent are the same as expected states,
2494 otherwise returns main.FALSE.
2495 """
2496 # FIXME: Convert these string comparisons to object comparisons
2497 try:
2498 returnValue = main.TRUE
2499 bandwidthFailed = False
2500 rawAlloc = self.allocations()
2501 expectedFormat = StringIO( expectedAllocations )
2502 ONOSOutput = StringIO( rawAlloc )
2503 main.log.debug( "ONOSOutput: {}\nexpected output: {}".format( str( ONOSOutput ),
2504 str( expectedFormat ) ) )
2505
2506 for actual, expected in izip( ONOSOutput, expectedFormat ):
2507 actual = actual.rstrip()
2508 expected = expected.rstrip()
2509 main.log.debug( "Expect: {}\nactual: {}".format( expected, actual ) )
2510 if actual != expected and 'allocated' in actual and 'allocated' in expected:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002511 marker1 = actual.find( 'allocated' )
2512 m1 = actual[ :marker1 ]
2513 marker2 = expected.find( 'allocated' )
2514 m2 = expected[ :marker2 ]
Jon Hallf539eb92017-05-22 17:18:42 -07002515 if m1 != m2:
2516 bandwidthFailed = True
2517 elif actual != expected and 'allocated' not in actual and 'allocated' not in expected:
2518 bandwidthFailed = True
2519 expectedFormat.close()
2520 ONOSOutput.close()
2521
2522 if bandwidthFailed:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002523 main.log.error( "Bandwidth not allocated correctly using Intents!!" )
Jon Hallf539eb92017-05-22 17:18:42 -07002524 returnValue = main.FALSE
2525 return returnValue
2526 except TypeError:
2527 main.log.exception( self.name + ": Object not as expected" )
2528 return None
2529 except pexpect.EOF:
2530 main.log.error( self.name + ": EOF exception found" )
2531 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002532 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002533 except Exception:
2534 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002535 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002536
You Wang66518af2016-05-16 15:32:59 -07002537 def compareIntent( self, intentDict ):
2538 """
2539 Description:
2540 Compare the intent ids and states provided in the argument with all intents in ONOS
2541 Return:
2542 Returns main.TRUE if the two sets of intents match exactly, otherwise main.FALSE
2543 Arguments:
2544 intentDict: a dictionary which maps intent ids to intent states
2545 """
2546 try:
2547 intentsRaw = self.intents()
2548 intentsJson = json.loads( intentsRaw )
2549 intentDictONOS = {}
2550 for intent in intentsJson:
2551 intentDictONOS[ intent[ 'id' ] ] = intent[ 'state' ]
You Wang58d04452016-09-21 15:13:05 -07002552 returnValue = main.TRUE
You Wang66518af2016-05-16 15:32:59 -07002553 if len( intentDict ) != len( intentDictONOS ):
You Wang58d04452016-09-21 15:13:05 -07002554 main.log.warn( self.name + ": expected intent count does not match that in ONOS, " +
You Wang66518af2016-05-16 15:32:59 -07002555 str( len( intentDict ) ) + " expected and " +
2556 str( len( intentDictONOS ) ) + " actual" )
You Wang58d04452016-09-21 15:13:05 -07002557 returnValue = main.FALSE
You Wang66518af2016-05-16 15:32:59 -07002558 for intentID in intentDict.keys():
Jon Halle0f0b342017-04-18 11:43:47 -07002559 if intentID not in intentDictONOS.keys():
You Wang66518af2016-05-16 15:32:59 -07002560 main.log.debug( self.name + ": intent ID - " + intentID + " is not in ONOS" )
2561 returnValue = main.FALSE
You Wang58d04452016-09-21 15:13:05 -07002562 else:
2563 if intentDict[ intentID ] != intentDictONOS[ intentID ]:
2564 main.log.debug( self.name + ": intent ID - " + intentID +
2565 " expected state is " + intentDict[ intentID ] +
2566 " but actual state is " + intentDictONOS[ intentID ] )
2567 returnValue = main.FALSE
2568 intentDictONOS.pop( intentID )
2569 if len( intentDictONOS ) > 0:
2570 returnValue = main.FALSE
2571 for intentID in intentDictONOS.keys():
2572 main.log.debug( self.name + ": find extra intent in ONOS: intent ID " + intentID )
You Wang66518af2016-05-16 15:32:59 -07002573 if returnValue == main.TRUE:
2574 main.log.info( self.name + ": all intent IDs and states match that in ONOS" )
2575 return returnValue
You Wang1be9a512016-05-26 16:54:17 -07002576 except KeyError:
2577 main.log.exception( self.name + ": KeyError exception found" )
2578 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002579 except ( TypeError, ValueError ):
2580 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intentsRaw ) )
You Wang85560372016-05-18 10:44:33 -07002581 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002582 except pexpect.EOF:
2583 main.log.error( self.name + ": EOF exception found" )
2584 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002585 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002586 except Exception:
2587 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002588 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002589
YPZhang14a4aa92016-07-15 13:37:15 -07002590 def checkIntentSummary( self, timeout=60, noExit=True ):
GlennRCed771242016-01-13 17:02:47 -08002591 """
2592 Description:
2593 Check the number of installed intents.
2594 Optional:
2595 timeout - the timeout for pexcept
YPZhang14a4aa92016-07-15 13:37:15 -07002596 noExit - If noExit, TestON will not exit if any except.
GlennRCed771242016-01-13 17:02:47 -08002597 Return:
2598 Returns main.TRUE only if the number of all installed intents are the same as total intents number
2599 , otherwise, returns main.FALSE.
2600 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002601
GlennRCed771242016-01-13 17:02:47 -08002602 try:
2603 cmd = "intents -s -j"
2604
2605 # Check response if something wrong
YPZhang14a4aa92016-07-15 13:37:15 -07002606 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002607 if response is None:
YPZhang0584d432016-06-21 15:20:13 -07002608 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002609 response = json.loads( response )
2610
2611 # get total and installed number, see if they are match
2612 allState = response.get( 'all' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002613 if allState.get( 'total' ) == allState.get( 'installed' ):
Jon Halla478b852017-12-04 15:00:15 -08002614 main.log.info( 'Total Intents: {} Installed Intents: {}'.format(
2615 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002616 return main.TRUE
Jon Halla478b852017-12-04 15:00:15 -08002617 main.log.info( 'Verified Intents failed Expected intents: {} installed intents: {}'.format(
2618 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002619 return main.FALSE
2620
Jon Hallc6793552016-01-19 14:18:37 -08002621 except ( TypeError, ValueError ):
2622 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
GlennRCed771242016-01-13 17:02:47 -08002623 return None
2624 except pexpect.EOF:
2625 main.log.error( self.name + ": EOF exception found" )
2626 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002627 if noExit:
2628 return main.FALSE
2629 else:
Devin Lim44075962017-08-11 10:56:37 -07002630 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07002631 except pexpect.TIMEOUT:
2632 main.log.error( self.name + ": ONOS timeout" )
2633 return None
GlennRCed771242016-01-13 17:02:47 -08002634 except Exception:
2635 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002636 if noExit:
2637 return main.FALSE
2638 else:
Devin Lim44075962017-08-11 10:56:37 -07002639 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002640
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002641 def flows( self, state="any", jsonFormat=True, timeout=60, noExit=False, noCore=False, device=""):
kelvin8ec71442015-01-15 16:57:00 -08002642 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002643 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002644 * jsonFormat: enable output formatting in json
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002645 * noCore: suppress core flows
Shreya Shah0f01c812014-10-26 20:15:28 -04002646 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002647 Obtain flows currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08002648 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002649 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002650 cmdStr = "flows"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002651 if jsonFormat:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002652 cmdStr += " -j"
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002653 if noCore:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002654 cmdStr += " -n"
2655 cmdStr += " " + state
2656 cmdStr += " " + device
YPZhangebf9eb52016-05-12 15:20:24 -07002657 handle = self.sendline( cmdStr, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002658 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002659 assert "Command not found:" not in handle, handle
2660 if re.search( "Error:", handle ):
2661 main.log.error( self.name + ": flows() response: " +
2662 str( handle ) )
2663 return handle
2664 except AssertionError:
2665 main.log.exception( "" )
GlennRCed771242016-01-13 17:02:47 -08002666 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002667 except TypeError:
2668 main.log.exception( self.name + ": Object not as expected" )
2669 return None
Jon Hallc6793552016-01-19 14:18:37 -08002670 except pexpect.TIMEOUT:
2671 main.log.error( self.name + ": ONOS timeout" )
2672 return None
Shreya Shah0f01c812014-10-26 20:15:28 -04002673 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002674 main.log.error( self.name + ": EOF exception found" )
2675 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002676 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002677 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002678 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002679 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002680
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002681 def checkFlowCount( self, min=0, timeout=60 ):
Flavio Castroa1286fe2016-07-25 14:48:51 -07002682 count = self.getTotalFlowsNum( timeout=timeout )
Jon Halle0f0b342017-04-18 11:43:47 -07002683 count = int( count ) if count else 0
steven30801eccfe212019-01-24 13:00:42 +08002684 main.log.debug( "found {} flows".format( count ) )
Jon Halle0f0b342017-04-18 11:43:47 -07002685 return count if ( count > min ) else False
GlennRCed771242016-01-13 17:02:47 -08002686
Jon Halle0f0b342017-04-18 11:43:47 -07002687 def checkFlowsState( self, isPENDING=True, timeout=60, noExit=False ):
kelvin-onlab4df89f22015-04-13 18:10:23 -07002688 """
2689 Description:
GlennRCed771242016-01-13 17:02:47 -08002690 Check the if all the current flows are in ADDED state
Jon Hallc6793552016-01-19 14:18:37 -08002691 We check PENDING_ADD, PENDING_REMOVE, REMOVED, and FAILED flows,
2692 if the count of those states is 0, which means all current flows
2693 are in ADDED state, and return main.TRUE otherwise return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002694 Optional:
GlennRCed771242016-01-13 17:02:47 -08002695 * isPENDING: whether the PENDING_ADD is also a correct status
kelvin-onlab4df89f22015-04-13 18:10:23 -07002696 Return:
2697 returnValue - Returns main.TRUE only if all flows are in
Jon Hallc6793552016-01-19 14:18:37 -08002698 ADDED state or PENDING_ADD if the isPENDING
pingping-linbab7f8a2015-09-21 17:33:36 -07002699 parameter is set true, return main.FALSE otherwise.
kelvin-onlab4df89f22015-04-13 18:10:23 -07002700 """
2701 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002702 states = [ "PENDING_ADD", "PENDING_REMOVE", "REMOVED", "FAILED" ]
GlennRCed771242016-01-13 17:02:47 -08002703 checkedStates = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002704 statesCount = [ 0, 0, 0, 0 ]
GlennRCed771242016-01-13 17:02:47 -08002705 for s in states:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002706 rawFlows = self.flows( state=s, timeout = timeout )
YPZhang240842b2016-05-17 12:00:50 -07002707 if rawFlows:
2708 # if we didn't get flows or flows function return None, we should return
2709 # main.Flase
2710 checkedStates.append( json.loads( rawFlows ) )
2711 else:
2712 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002713 for i in range( len( states ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002714 for c in checkedStates[ i ]:
Jon Hallc6793552016-01-19 14:18:37 -08002715 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002716 statesCount[ i ] += int( c.get( "flowCount" ) )
Jon Hallc6793552016-01-19 14:18:37 -08002717 except TypeError:
2718 main.log.exception( "Json object not as expected" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002719 main.log.info( states[ i ] + " flows: " + str( statesCount[ i ] ) )
kelvin-onlabf2ec6e02015-05-27 14:15:28 -07002720
GlennRCed771242016-01-13 17:02:47 -08002721 # We want to count PENDING_ADD if isPENDING is true
2722 if isPENDING:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002723 if statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002724 return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002725 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002726 if statesCount[ 0 ] + statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002727 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002728 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002729 except ( TypeError, ValueError ):
2730 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawFlows ) )
kelvin-onlab4df89f22015-04-13 18:10:23 -07002731 return None
Jeremy Songster9385d412016-06-02 17:57:36 -07002732
YPZhang240842b2016-05-17 12:00:50 -07002733 except AssertionError:
2734 main.log.exception( "" )
2735 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002736 except pexpect.TIMEOUT:
2737 main.log.error( self.name + ": ONOS timeout" )
2738 return None
kelvin-onlab4df89f22015-04-13 18:10:23 -07002739 except pexpect.EOF:
2740 main.log.error( self.name + ": EOF exception found" )
2741 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002742 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002743 except Exception:
2744 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002745 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002746
GlennRCed771242016-01-13 17:02:47 -08002747 def pushTestIntents( self, ingress, egress, batchSize, offset="",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002748 options="", timeout=10, background = False, noExit=False, getResponse=False ):
kelvin8ec71442015-01-15 16:57:00 -08002749 """
andrewonlab87852b02014-11-19 18:44:19 -05002750 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002751 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05002752 a specific point-to-point intent definition
2753 Required:
GlennRCed771242016-01-13 17:02:47 -08002754 * ingress: specify source dpid
2755 * egress: specify destination dpid
2756 * batchSize: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05002757 Optional:
GlennRCed771242016-01-13 17:02:47 -08002758 * offset: the keyOffset is where the next batch of intents
2759 will be installed
YPZhangb34b7e12016-06-14 14:28:19 -07002760 * noExit: If set to True, TestON will not exit if any error when issus command
2761 * getResponse: If set to True, function will return ONOS response.
2762
GlennRCed771242016-01-13 17:02:47 -08002763 Returns: If failed to push test intents, it will returen None,
2764 if successful, return true.
2765 Timeout expection will return None,
2766 TypeError will return false
2767 other expections will exit()
kelvin8ec71442015-01-15 16:57:00 -08002768 """
andrewonlab87852b02014-11-19 18:44:19 -05002769 try:
GlennRCed771242016-01-13 17:02:47 -08002770 if background:
2771 back = "&"
andrewonlab87852b02014-11-19 18:44:19 -05002772 else:
GlennRCed771242016-01-13 17:02:47 -08002773 back = ""
2774 cmd = "push-test-intents {} {} {} {} {} {}".format( options,
Jon Hallc6793552016-01-19 14:18:37 -08002775 ingress,
2776 egress,
2777 batchSize,
2778 offset,
2779 back )
YPZhangebf9eb52016-05-12 15:20:24 -07002780 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002781 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002782 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08002783 main.log.info( response )
YPZhangb34b7e12016-06-14 14:28:19 -07002784 if getResponse:
2785 return response
2786
GlennRCed771242016-01-13 17:02:47 -08002787 # TODO: We should handle if there is failure in installation
2788 return main.TRUE
2789
Jon Hallc6793552016-01-19 14:18:37 -08002790 except AssertionError:
2791 main.log.exception( "" )
2792 return None
GlennRCed771242016-01-13 17:02:47 -08002793 except pexpect.TIMEOUT:
2794 main.log.error( self.name + ": ONOS timeout" )
Jon Halld4d4b372015-01-28 16:02:41 -08002795 return None
andrewonlab87852b02014-11-19 18:44:19 -05002796 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002797 main.log.error( self.name + ": EOF exception found" )
2798 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002799 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002800 except TypeError:
2801 main.log.exception( self.name + ": Object not as expected" )
Jon Hallc6793552016-01-19 14:18:37 -08002802 return None
Jon Hallfebb1c72015-03-05 13:30:09 -08002803 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002804 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002805 main.cleanAndExit()
andrewonlab87852b02014-11-19 18:44:19 -05002806
YPZhangebf9eb52016-05-12 15:20:24 -07002807 def getTotalFlowsNum( self, timeout=60, noExit=False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002808 """
2809 Description:
YPZhangf6f14a02016-01-28 15:17:31 -08002810 Get the number of ADDED flows.
YPZhangb5d3f832016-01-23 22:54:26 -08002811 Return:
YPZhangf6f14a02016-01-28 15:17:31 -08002812 The number of ADDED flows
YPZhang14a4aa92016-07-15 13:37:15 -07002813 Or return None if any exceptions
YPZhangb5d3f832016-01-23 22:54:26 -08002814 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002815
YPZhangb5d3f832016-01-23 22:54:26 -08002816 try:
YPZhange3109a72016-02-02 11:25:37 -08002817 # get total added flows number
YPZhang14a4aa92016-07-15 13:37:15 -07002818 cmd = "flows -c added"
2819 rawFlows = self.sendline( cmd, timeout=timeout, noExit=noExit )
2820 if rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002821 rawFlows = rawFlows.split( "\n" )
YPZhange3109a72016-02-02 11:25:37 -08002822 totalFlows = 0
YPZhang14a4aa92016-07-15 13:37:15 -07002823 for l in rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002824 totalFlows += int( l.split( "Count=" )[ 1 ] )
YPZhang14a4aa92016-07-15 13:37:15 -07002825 else:
You Wang68568b12019-03-04 11:49:57 -08002826 main.log.warn( "Response not as expected!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002827 return None
2828 return totalFlows
YPZhange3109a72016-02-02 11:25:37 -08002829
You Wangd3097f72018-12-12 11:56:03 -08002830 except IndexError:
2831 main.log.exception( "{}: Object not as expected!".format( self.name ) )
2832 main.log.debug( "rawFlows: {}".format( rawFlows ) )
2833 return None
You Wangd3cb2ce2016-05-16 14:01:24 -07002834 except ( TypeError, ValueError ):
YPZhang14a4aa92016-07-15 13:37:15 -07002835 main.log.exception( "{}: Object not as expected!".format( self.name ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002836 return None
2837 except pexpect.EOF:
2838 main.log.error( self.name + ": EOF exception found" )
2839 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002840 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002841 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002842 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002843 except pexpect.TIMEOUT:
2844 main.log.error( self.name + ": ONOS timeout" )
2845 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002846 except Exception:
2847 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002848 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002849 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002850 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002851
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002852 def getTotalIntentsNum( self, timeout=60, noExit = False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002853 """
2854 Description:
2855 Get the total number of intents, include every states.
YPZhang14a4aa92016-07-15 13:37:15 -07002856 Optional:
2857 noExit - If noExit, TestON will not exit if any except.
YPZhangb5d3f832016-01-23 22:54:26 -08002858 Return:
2859 The number of intents
2860 """
2861 try:
2862 cmd = "summary -j"
YPZhang14a4aa92016-07-15 13:37:15 -07002863 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002864 if response is None:
2865 return -1
YPZhangb5d3f832016-01-23 22:54:26 -08002866 response = json.loads( response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002867 return int( response.get( "intents" ) )
You Wangd3cb2ce2016-05-16 14:01:24 -07002868 except ( TypeError, ValueError ):
2869 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002870 return None
2871 except pexpect.EOF:
2872 main.log.error( self.name + ": EOF exception found" )
2873 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002874 if noExit:
2875 return -1
2876 else:
Devin Lim44075962017-08-11 10:56:37 -07002877 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002878 except Exception:
2879 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002880 if noExit:
2881 return -1
2882 else:
Devin Lim44075962017-08-11 10:56:37 -07002883 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002884
kelvin-onlabd3b64892015-01-20 13:26:24 -08002885 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002886 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002887 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002888 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002889 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002890 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002891 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002892 cmdStr = "intents-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002893 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002894 cmdStr += " -j"
2895 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002896 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002897 assert "Command not found:" not in handle, handle
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002898 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002899 except AssertionError:
2900 main.log.exception( "" )
2901 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002902 except TypeError:
2903 main.log.exception( self.name + ": Object not as expected" )
2904 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002905 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002906 main.log.error( self.name + ": EOF exception found" )
2907 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002908 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002909 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002910 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002911 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002912
kelvin-onlabd3b64892015-01-20 13:26:24 -08002913 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002914 """
2915 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04002916 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002917 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002918 """
andrewonlab867212a2014-10-22 20:13:38 -04002919 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002920 cmdStr = "topology-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002921 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002922 cmdStr += " -j"
2923 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002924 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002925 assert "Command not found:" not in handle, handle
jenkins7ead5a82015-03-13 10:28:21 -07002926 if handle:
2927 return handle
Jon Hallc6358dd2015-04-10 12:44:28 -07002928 elif jsonFormat:
Jon Hallbe379602015-03-24 13:39:32 -07002929 # Return empty json
jenkins7ead5a82015-03-13 10:28:21 -07002930 return '{}'
Jon Hallc6358dd2015-04-10 12:44:28 -07002931 else:
2932 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002933 except AssertionError:
2934 main.log.exception( "" )
2935 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002936 except TypeError:
2937 main.log.exception( self.name + ": Object not as expected" )
2938 return None
andrewonlab867212a2014-10-22 20:13:38 -04002939 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002940 main.log.error( self.name + ": EOF exception found" )
2941 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002942 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002943 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002944 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002945 main.cleanAndExit()
andrewonlab867212a2014-10-22 20:13:38 -04002946
kelvin8ec71442015-01-15 16:57:00 -08002947 # Wrapper functions ****************
2948 # Wrapper functions use existing driver
2949 # functions and extends their use case.
2950 # For example, we may use the output of
2951 # a normal driver function, and parse it
2952 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04002953
kelvin-onlabd3b64892015-01-20 13:26:24 -08002954 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002955 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002956 Description:
2957 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08002958 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002959 try:
kelvin8ec71442015-01-15 16:57:00 -08002960 # Obtain output of intents function
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002961 intentsStr = self.intents( jsonFormat=True )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07002962 if intentsStr is None:
2963 raise TypeError
Jon Hall6021e062017-01-30 11:10:06 -08002964 # Convert to a dictionary
2965 intents = json.loads( intentsStr )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002966 intentIdList = []
Jon Hall6021e062017-01-30 11:10:06 -08002967 for intent in intents:
2968 intentIdList.append( intent[ 'id' ] )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002969 return intentIdList
Jon Halld4d4b372015-01-28 16:02:41 -08002970 except TypeError:
2971 main.log.exception( self.name + ": Object not as expected" )
2972 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002973 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002974 main.log.error( self.name + ": EOF exception found" )
2975 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002976 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002977 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002978 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002979 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04002980
You Wang3c276252016-09-21 15:21:36 -07002981 def flowAddedCount( self, deviceId, core=False ):
Jon Hall30b82fa2015-03-04 17:15:43 -08002982 """
2983 Determine the number of flow rules for the given device id that are
2984 in the added state
You Wang3c276252016-09-21 15:21:36 -07002985 Params:
2986 core: if True, only return the number of core flows added
Jon Hall30b82fa2015-03-04 17:15:43 -08002987 """
2988 try:
You Wang3c276252016-09-21 15:21:36 -07002989 if core:
2990 cmdStr = "flows any " + str( deviceId ) + " | " +\
2991 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
2992 else:
2993 cmdStr = "flows any " + str( deviceId ) + " | " +\
2994 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08002995 handle = self.lineCount( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002996 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002997 assert "Command not found:" not in handle, handle
Jon Hall30b82fa2015-03-04 17:15:43 -08002998 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002999 except AssertionError:
3000 main.log.exception( "" )
3001 return None
Jon Hall30b82fa2015-03-04 17:15:43 -08003002 except pexpect.EOF:
3003 main.log.error( self.name + ": EOF exception found" )
3004 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003005 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003006 except Exception:
Jon Hall30b82fa2015-03-04 17:15:43 -08003007 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003008 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -04003009
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003010 def groupAddedCount( self, deviceId, core=False ):
3011 """
3012 Determine the number of group rules for the given device id that are
3013 in the added state
3014 Params:
3015 core: if True, only return the number of core groups added
3016 """
3017 try:
3018 if core:
3019 cmdStr = "groups any " + str( deviceId ) + " | " +\
3020 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
3021 else:
3022 cmdStr = "groups any " + str( deviceId ) + " | " +\
3023 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003024 handle = self.lineCount( cmdStr )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003025 assert handle is not None, "Error in sendline"
3026 assert "Command not found:" not in handle, handle
3027 return handle
3028 except AssertionError:
3029 main.log.exception( "" )
3030 return None
3031 except pexpect.EOF:
3032 main.log.error( self.name + ": EOF exception found" )
3033 main.log.error( self.name + ": " + self.handle.before )
3034 main.cleanAndExit()
3035 except Exception:
3036 main.log.exception( self.name + ": Uncaught exception!" )
3037 main.cleanAndExit()
3038
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003039 def addStaticRoute( self, subnet, intf):
3040 """
3041 Adds a static route to onos.
3042 Params:
3043 subnet: The subnet reaching through this route
3044 intf: The interface this route is reachable through
3045 """
3046 try:
3047 cmdStr = "route-add " + subnet + " " + intf
3048 handle = self.sendline( cmdStr )
3049 assert handle is not None, "Error in sendline"
3050 assert "Command not found:" not in handle, handle
3051 return handle
3052 except AssertionError:
3053 main.log.exception( "" )
3054 return None
3055 except pexpect.EOF:
3056 main.log.error( self.name + ": EOF exception found" )
3057 main.log.error( self.name + ": " + self.handle.before )
3058 main.cleanAndExit()
3059 except Exception:
3060 main.log.exception( self.name + ": Uncaught exception!" )
3061 main.cleanAndExit()
3062
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003063 def checkGroupAddedCount( self, deviceId, expectedGroupCount=0, core=False, comparison=0):
3064 """
3065 Description:
3066 Check whether the number of groups for the given device id that
3067 are in ADDED state is bigger than minGroupCount.
3068 Required:
3069 * deviceId: device id to check the number of added group rules
3070 Optional:
3071 * minGroupCount: the number of groups to compare
3072 * core: if True, only check the number of core groups added
3073 * comparison: if 0, compare with greater than minFlowCount
3074 * if 1, compare with equal to minFlowCount
3075 Return:
3076 Returns the number of groups if it is bigger than minGroupCount,
3077 returns main.FALSE otherwise.
3078 """
3079 count = self.groupAddedCount( deviceId, core )
3080 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003081 main.log.debug( "found {} groups".format( count ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003082 return count if ((count > expectedGroupCount) if (comparison == 0) else (count == expectedGroupCount)) else main.FALSE
3083
You Wangc02f3be2018-05-18 12:14:23 -07003084 def getGroups( self, deviceId, groupType="any" ):
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003085 """
3086 Retrieve groups from a specific device.
You Wangc02f3be2018-05-18 12:14:23 -07003087 deviceId: Id of the device from which we retrieve groups
3088 groupType: Type of group
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003089 """
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003090 try:
You Wangc02f3be2018-05-18 12:14:23 -07003091 groupCmd = "groups -t {0} any {1}".format( groupType, deviceId )
3092 handle = self.sendline( groupCmd )
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003093 assert handle is not None, "Error in sendline"
3094 assert "Command not found:" not in handle, handle
3095 return handle
3096 except AssertionError:
3097 main.log.exception( "" )
3098 return None
3099 except TypeError:
3100 main.log.exception( self.name + ": Object not as expected" )
3101 return None
3102 except pexpect.EOF:
3103 main.log.error( self.name + ": EOF exception found" )
3104 main.log.error( self.name + ": " + self.handle.before )
3105 main.cleanAndExit()
3106 except Exception:
3107 main.log.exception( self.name + ": Uncaught exception!" )
3108 main.cleanAndExit()
3109
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003110 def checkFlowAddedCount( self, deviceId, expectedFlowCount=0, core=False, comparison=0):
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003111 """
3112 Description:
3113 Check whether the number of flow rules for the given device id that
3114 are in ADDED state is bigger than minFlowCount.
3115 Required:
3116 * deviceId: device id to check the number of added flow rules
3117 Optional:
3118 * minFlowCount: the number of flow rules to compare
3119 * core: if True, only check the number of core flows added
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003120 * comparison: if 0, compare with greater than minFlowCount
3121 * if 1, compare with equal to minFlowCount
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003122 Return:
3123 Returns the number of flow rules if it is bigger than minFlowCount,
3124 returns main.FALSE otherwise.
3125 """
3126 count = self.flowAddedCount( deviceId, core )
3127 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003128 main.log.debug( "found {} flows".format( count ) )
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003129 return count if ((count > expectedFlowCount) if (comparison == 0) else (count == expectedFlowCount)) else main.FALSE
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003130
kelvin-onlabd3b64892015-01-20 13:26:24 -08003131 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003132 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003133 Use 'devices' function to obtain list of all devices
3134 and parse the result to obtain a list of all device
3135 id's. Returns this list. Returns empty list if no
3136 devices exist
kelvin8ec71442015-01-15 16:57:00 -08003137 List is ordered sequentially
3138
andrewonlab3e15ead2014-10-15 14:21:34 -04003139 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08003140 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04003141 the ids. By obtaining the list of device ids on the fly,
3142 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08003143 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003144 try:
kelvin8ec71442015-01-15 16:57:00 -08003145 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08003146 devicesStr = self.devices( jsonFormat=False )
3147 idList = []
kelvin8ec71442015-01-15 16:57:00 -08003148
kelvin-onlabd3b64892015-01-20 13:26:24 -08003149 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08003150 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003151 return idList
kelvin8ec71442015-01-15 16:57:00 -08003152
3153 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08003154 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08003155 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08003156 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08003157 # Split list further into arguments before and after string
3158 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08003159 # append to idList
3160 for arg in tempList:
3161 idList.append( arg.split( "id=" )[ 1 ] )
3162 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04003163
Jon Halld4d4b372015-01-28 16:02:41 -08003164 except TypeError:
3165 main.log.exception( self.name + ": Object not as expected" )
3166 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04003167 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003168 main.log.error( self.name + ": EOF exception found" )
3169 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003170 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003171 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003172 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003173 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003174
kelvin-onlabd3b64892015-01-20 13:26:24 -08003175 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003176 """
andrewonlab7c211572014-10-15 16:45:20 -04003177 Uses 'nodes' function to obtain list of all nodes
3178 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08003179 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04003180 Returns:
3181 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08003182 """
andrewonlab7c211572014-10-15 16:45:20 -04003183 try:
Jon Hall5aa168b2015-03-23 14:23:09 -07003184 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003185 idList = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003186 # Sample nodesStr output
Jon Hallbd182782016-03-28 16:42:22 -07003187 # id=local, address=127.0.0.1:9876, state=READY *
kelvin-onlabd3b64892015-01-20 13:26:24 -08003188 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08003189 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003190 return idList
Jon Hall5aa168b2015-03-23 14:23:09 -07003191 nodesJson = json.loads( nodesStr )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003192 idList = [ node.get( 'id' ) for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08003193 return idList
Jon Hallc6793552016-01-19 14:18:37 -08003194 except ( TypeError, ValueError ):
3195 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, nodesStr ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003196 return None
andrewonlab7c211572014-10-15 16:45:20 -04003197 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003198 main.log.error( self.name + ": EOF exception found" )
3199 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003200 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003201 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003202 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003203 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003204
kelvin-onlabd3b64892015-01-20 13:26:24 -08003205 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08003206 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003207 Return the first device from the devices api whose 'id' contains 'dpid'
3208 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08003209 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003210 try:
kelvin8ec71442015-01-15 16:57:00 -08003211 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04003212 return None
3213 else:
kelvin8ec71442015-01-15 16:57:00 -08003214 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003215 rawDevices = self.devices()
3216 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08003217 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08003218 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08003219 # print "%s in %s?" % ( dpid, device[ 'id' ] )
3220 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04003221 return device
3222 return None
Jon Hallc6793552016-01-19 14:18:37 -08003223 except ( TypeError, ValueError ):
3224 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawDevices ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003225 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04003226 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003227 main.log.error( self.name + ": EOF exception found" )
3228 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003229 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003230 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003231 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003232 main.cleanAndExit()
Jon Halla91c4dc2014-10-22 12:57:04 -04003233
You Wang24139872016-05-03 11:48:47 -07003234 def getTopology( self, topologyOutput ):
3235 """
3236 Definition:
3237 Loads a json topology output
3238 Return:
3239 topology = current ONOS topology
3240 """
You Wang24139872016-05-03 11:48:47 -07003241 try:
3242 # either onos:topology or 'topology' will work in CLI
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003243 topology = json.loads( topologyOutput )
Jeremy Songsterbc2d8ac2016-05-04 11:25:42 -07003244 main.log.debug( topology )
You Wang24139872016-05-03 11:48:47 -07003245 return topology
You Wangd3cb2ce2016-05-16 14:01:24 -07003246 except ( TypeError, ValueError ):
3247 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, topologyOutput ) )
3248 return None
You Wang24139872016-05-03 11:48:47 -07003249 except pexpect.EOF:
3250 main.log.error( self.name + ": EOF exception found" )
3251 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003252 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003253 except Exception:
3254 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003255 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003256
Pier6a0c4de2018-03-18 16:01:30 -07003257 def checkStatus( self, numoswitch, numolink = -1, numoctrl = -1, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08003258 """
Jon Hallefbd9792015-03-05 16:11:36 -08003259 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08003260 supplied values. By default this will report to main.log, but the
You Wang24139872016-05-03 11:48:47 -07003261 log level can be specific.
kelvin8ec71442015-01-15 16:57:00 -08003262
Flavio Castro82ee2f62016-06-07 15:04:12 -07003263 Params: numoswitch = expected number of switches
Jon Hallefbd9792015-03-05 16:11:36 -08003264 numolink = expected number of links
Flavio Castro82ee2f62016-06-07 15:04:12 -07003265 numoctrl = expected number of controllers
You Wang24139872016-05-03 11:48:47 -07003266 logLevel = level to log to.
3267 Currently accepts 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04003268
Jon Hallefbd9792015-03-05 16:11:36 -08003269 Returns: main.TRUE if the number of switches and links are correct,
3270 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04003271 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08003272 """
Jon Hall42db6dc2014-10-24 19:03:48 -04003273 try:
You Wang13310252016-07-31 10:56:14 -07003274 summary = self.summary()
3275 summary = json.loads( summary )
Flavio Castrof5b3f872016-06-23 17:52:31 -07003276 except ( TypeError, ValueError ):
3277 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summary ) )
3278 return main.ERROR
3279 try:
3280 topology = self.getTopology( self.topology() )
Jon Halle0f0b342017-04-18 11:43:47 -07003281 if topology == {} or topology is None or summary == {} or summary is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04003282 return main.ERROR
3283 output = ""
kelvin8ec71442015-01-15 16:57:00 -08003284 # Is the number of switches is what we expected
3285 devices = topology.get( 'devices', False )
3286 links = topology.get( 'links', False )
Flavio Castro82ee2f62016-06-07 15:04:12 -07003287 nodes = summary.get( 'nodes', False )
3288 if devices is False or links is False or nodes is False:
Jon Hall42db6dc2014-10-24 19:03:48 -04003289 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08003290 switchCheck = ( int( devices ) == int( numoswitch ) )
kelvin8ec71442015-01-15 16:57:00 -08003291 # Is the number of links is what we expected
Pier6a0c4de2018-03-18 16:01:30 -07003292 linkCheck = ( int( links ) == int( numolink ) ) or int( numolink ) == -1
Flavio Castro82ee2f62016-06-07 15:04:12 -07003293 nodeCheck = ( int( nodes ) == int( numoctrl ) ) or int( numoctrl ) == -1
3294 if switchCheck and linkCheck and nodeCheck:
kelvin8ec71442015-01-15 16:57:00 -08003295 # We expected the correct numbers
You Wang24139872016-05-03 11:48:47 -07003296 output = output + "The number of links and switches match "\
3297 + "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003298 result = main.TRUE
3299 else:
You Wang24139872016-05-03 11:48:47 -07003300 output = output + \
3301 "The number of links and switches does not match " + \
3302 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003303 result = main.FALSE
You Wang24139872016-05-03 11:48:47 -07003304 output = output + "\n ONOS sees %i devices" % int( devices )
3305 output = output + " (%i expected) " % int( numoswitch )
Pier6a0c4de2018-03-18 16:01:30 -07003306 if int( numolink ) > 0:
3307 output = output + "and %i links " % int( links )
3308 output = output + "(%i expected)" % int( numolink )
YPZhangd7e4b6e2016-06-17 16:07:55 -07003309 if int( numoctrl ) > 0:
Flavio Castro82ee2f62016-06-07 15:04:12 -07003310 output = output + "and %i controllers " % int( nodes )
3311 output = output + "(%i expected)" % int( numoctrl )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003312 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08003313 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003314 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08003315 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04003316 else:
You Wang24139872016-05-03 11:48:47 -07003317 main.log.info( output )
kelvin8ec71442015-01-15 16:57:00 -08003318 return result
Jon Hall42db6dc2014-10-24 19:03:48 -04003319 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003320 main.log.error( self.name + ": EOF exception found" )
3321 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003322 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003323 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003324 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003325 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003326
kelvin-onlabd3b64892015-01-20 13:26:24 -08003327 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08003328 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003329 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08003330 deviceId must be the id of a device as seen in the onos devices command
3331 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04003332 role must be either master, standby, or none
3333
Jon Halle3f39ff2015-01-13 11:50:53 -08003334 Returns:
3335 main.TRUE or main.FALSE based on argument verification and
3336 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003337 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003338 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003339 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04003340 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08003341 cmdStr = "device-role " +\
3342 str( deviceId ) + " " +\
3343 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003344 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003345 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003346 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003347 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08003348 if re.search( "Error", handle ):
3349 # end color output to escape any colours
3350 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08003351 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003352 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08003353 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08003354 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04003355 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003356 main.log.error( "Invalid 'role' given to device_role(). " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003357 "Value was '" + str( role ) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04003358 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003359 except AssertionError:
3360 main.log.exception( "" )
3361 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003362 except TypeError:
3363 main.log.exception( self.name + ": Object not as expected" )
3364 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04003365 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003366 main.log.error( self.name + ": EOF exception found" )
3367 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003368 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003369 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003370 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003371 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003372
kelvin-onlabd3b64892015-01-20 13:26:24 -08003373 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08003374 """
Jon Hall0dd09952018-04-19 09:59:11 -07003375 Lists all topology clusters
Jon Hallffb386d2014-11-21 13:43:38 -08003376 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003377 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08003378 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08003379 try:
Jon Hall0dd09952018-04-19 09:59:11 -07003380 cmdStr = "topo-clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003381 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003382 cmdStr += " -j"
3383 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003384 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003385 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07003386 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003387 except AssertionError:
3388 main.log.exception( "" )
3389 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003390 except TypeError:
3391 main.log.exception( self.name + ": Object not as expected" )
3392 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08003393 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003394 main.log.error( self.name + ": EOF exception found" )
3395 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003396 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003397 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003398 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003399 main.cleanAndExit()
Jon Hall73cf9cc2014-11-20 22:28:38 -08003400
kelvin-onlabd3b64892015-01-20 13:26:24 -08003401 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003402 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003403 CLI command to get the current leader for the Election test application
3404 NOTE: Requires installation of the onos-app-election feature
3405 Returns: Node IP of the leader if one exists
3406 None if none exists
3407 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003408 """
Jon Hall94fd0472014-12-08 11:52:42 -08003409 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003410 cmdStr = "election-test-leader"
3411 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003412 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003413 assert "Command not found:" not in response, response
Jon Halle3f39ff2015-01-13 11:50:53 -08003414 # Leader
3415 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003416 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08003417 nodeSearch = re.search( leaderPattern, response )
3418 if nodeSearch:
3419 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08003420 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003421 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08003422 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08003423 # no leader
3424 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003425 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003426 nullSearch = re.search( nullPattern, response )
3427 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08003428 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003429 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08003430 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08003431 # error
Jon Hall0e240372018-05-02 11:21:57 -07003432 main.log.error( self.name + ": Error in electionTestLeader on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003433 ": " + "unexpected response" )
3434 main.log.error( repr( response ) )
3435 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003436 except AssertionError:
3437 main.log.exception( "" )
3438 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003439 except TypeError:
3440 main.log.exception( self.name + ": Object not as expected" )
3441 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003442 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003443 main.log.error( self.name + ": EOF exception found" )
3444 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003445 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003446 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003447 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003448 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003449
kelvin-onlabd3b64892015-01-20 13:26:24 -08003450 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003451 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003452 CLI command to run for leadership of the Election test application.
3453 NOTE: Requires installation of the onos-app-election feature
3454 Returns: Main.TRUE on success
3455 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003456 """
Jon Hall94fd0472014-12-08 11:52:42 -08003457 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003458 cmdStr = "election-test-run"
3459 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003460 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003461 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003462 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003463 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003464 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003465 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08003466 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08003467 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003468 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003469 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003470 # error
Jon Hall0e240372018-05-02 11:21:57 -07003471 main.log.error( self.name + ": Error in electionTestRun on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003472 ": " + "unexpected response" )
3473 main.log.error( repr( response ) )
3474 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003475 except AssertionError:
3476 main.log.exception( "" )
3477 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003478 except TypeError:
3479 main.log.exception( self.name + ": Object not as expected" )
3480 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003481 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003482 main.log.error( self.name + ": EOF exception found" )
3483 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003484 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003485 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003486 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003487 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003488
kelvin-onlabd3b64892015-01-20 13:26:24 -08003489 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08003490 """
Jon Hall94fd0472014-12-08 11:52:42 -08003491 * CLI command to withdraw the local node from leadership election for
3492 * the Election test application.
3493 #NOTE: Requires installation of the onos-app-election feature
3494 Returns: Main.TRUE on success
3495 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08003496 """
Jon Hall94fd0472014-12-08 11:52:42 -08003497 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003498 cmdStr = "election-test-withdraw"
3499 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003500 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003501 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003502 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003503 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003504 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003505 if re.search( successPattern, response ):
3506 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003507 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003508 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003509 # error
Jon Hall0e240372018-05-02 11:21:57 -07003510 main.log.error( self.name + ": Error in electionTestWithdraw on " +
Jon Hall97cf84a2016-06-20 13:35:58 -07003511 self.name + ": " + "unexpected response" )
3512 main.log.error( repr( response ) )
3513 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003514 except AssertionError:
3515 main.log.exception( "" )
3516 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003517 except TypeError:
3518 main.log.exception( self.name + ": Object not as expected" )
3519 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003520 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003521 main.log.error( self.name + ": EOF exception found" )
3522 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003523 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003524 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003525 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003526 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003527
kelvin8ec71442015-01-15 16:57:00 -08003528 def getDevicePortsEnabledCount( self, dpid ):
3529 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003530 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003531 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003532 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003533 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003534 cmdStr = "onos:ports -e " + dpid + " | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003535 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003536 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003537 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003538 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003539 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003540 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003541 return output
Jon Hallc6793552016-01-19 14:18:37 -08003542 except AssertionError:
3543 main.log.exception( "" )
3544 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003545 except TypeError:
3546 main.log.exception( self.name + ": Object not as expected" )
3547 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003548 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003549 main.log.error( self.name + ": EOF exception found" )
3550 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003551 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003552 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003553 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003554 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003555
kelvin8ec71442015-01-15 16:57:00 -08003556 def getDeviceLinksActiveCount( self, dpid ):
3557 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003558 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003559 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003560 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003561 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003562 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003563 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003564 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003565 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003566 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003567 main.log.error( self.name + ": Error in getting ports " )
kelvin-onlab898a6c62015-01-16 14:13:53 -08003568 return ( output, "Error " )
Jon Halla495f562016-05-16 18:03:26 -07003569 return output
Jon Hallc6793552016-01-19 14:18:37 -08003570 except AssertionError:
3571 main.log.exception( "" )
3572 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003573 except TypeError:
3574 main.log.exception( self.name + ": Object not as expected" )
3575 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003576 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003577 main.log.error( self.name + ": EOF exception found" )
3578 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003579 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003580 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003581 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003582 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003583
kelvin8ec71442015-01-15 16:57:00 -08003584 def getAllIntentIds( self ):
3585 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003586 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08003587 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003588 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003589 cmdStr = "onos:intents | grep id="
3590 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003591 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003592 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003593 if re.search( "Error", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003594 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003595 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003596 return output
Jon Hallc6793552016-01-19 14:18:37 -08003597 except AssertionError:
3598 main.log.exception( "" )
3599 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003600 except TypeError:
3601 main.log.exception( self.name + ": Object not as expected" )
3602 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003603 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003604 main.log.error( self.name + ": EOF exception found" )
3605 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003606 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003607 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003608 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003609 main.cleanAndExit()
Jon Halld4d4b372015-01-28 16:02:41 -08003610
Jon Hall73509952015-02-24 16:42:56 -08003611 def intentSummary( self ):
3612 """
Jon Hallefbd9792015-03-05 16:11:36 -08003613 Returns a dictionary containing the current intent states and the count
Jon Hall73509952015-02-24 16:42:56 -08003614 """
3615 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003616 intents = self.intents( )
Jon Hall08f61bc2015-04-13 16:00:30 -07003617 states = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003618 for intent in json.loads( intents ):
Jon Hall08f61bc2015-04-13 16:00:30 -07003619 states.append( intent.get( 'state', None ) )
3620 out = [ ( i, states.count( i ) ) for i in set( states ) ]
Jon Hall63604932015-02-26 17:09:50 -08003621 main.log.info( dict( out ) )
Jon Hall73509952015-02-24 16:42:56 -08003622 return dict( out )
Jon Hallc6793552016-01-19 14:18:37 -08003623 except ( TypeError, ValueError ):
3624 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intents ) )
Jon Hall73509952015-02-24 16:42:56 -08003625 return None
3626 except pexpect.EOF:
3627 main.log.error( self.name + ": EOF exception found" )
3628 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003629 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003630 except Exception:
Jon Hall73509952015-02-24 16:42:56 -08003631 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003632 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003633
Jon Hall61282e32015-03-19 11:34:11 -07003634 def leaders( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003635 """
3636 Returns the output of the leaders command.
Jon Hall61282e32015-03-19 11:34:11 -07003637 Optional argument:
3638 * jsonFormat - boolean indicating if you want output in json
Jon Hall63604932015-02-26 17:09:50 -08003639 """
Jon Hall63604932015-02-26 17:09:50 -08003640 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003641 cmdStr = "onos:leaders"
Jon Hall61282e32015-03-19 11:34:11 -07003642 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003643 cmdStr += " -j"
3644 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003645 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003646 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003647 return output
Jon Hallc6793552016-01-19 14:18:37 -08003648 except AssertionError:
3649 main.log.exception( "" )
3650 return None
Jon Hall63604932015-02-26 17:09:50 -08003651 except TypeError:
3652 main.log.exception( self.name + ": Object not as expected" )
3653 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003654 except pexpect.EOF:
3655 main.log.error( self.name + ": EOF exception found" )
3656 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003657 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003658 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003659 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003660 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003661
acsmarsa4a4d1e2015-07-10 16:01:24 -07003662 def leaderCandidates( self, jsonFormat=True ):
3663 """
3664 Returns the output of the leaders -c command.
3665 Optional argument:
3666 * jsonFormat - boolean indicating if you want output in json
3667 """
3668 try:
3669 cmdStr = "onos:leaders -c"
3670 if jsonFormat:
3671 cmdStr += " -j"
3672 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003673 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003674 assert "Command not found:" not in output, output
acsmarsa4a4d1e2015-07-10 16:01:24 -07003675 return output
Jon Hallc6793552016-01-19 14:18:37 -08003676 except AssertionError:
3677 main.log.exception( "" )
3678 return None
acsmarsa4a4d1e2015-07-10 16:01:24 -07003679 except TypeError:
3680 main.log.exception( self.name + ": Object not as expected" )
3681 return None
3682 except pexpect.EOF:
3683 main.log.error( self.name + ": EOF exception found" )
3684 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003685 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003686 except Exception:
3687 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003688 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003689
Jon Hallc6793552016-01-19 14:18:37 -08003690 def specificLeaderCandidate( self, topic ):
acsmarsa4a4d1e2015-07-10 16:01:24 -07003691 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003692 Returns a list in format [leader,candidate1,candidate2,...] for a given
acsmarsa4a4d1e2015-07-10 16:01:24 -07003693 topic parameter and an empty list if the topic doesn't exist
3694 If no leader is elected leader in the returned list will be "none"
3695 Returns None if there is a type error processing the json object
3696 """
3697 try:
Jon Hall6e709752016-02-01 13:38:46 -08003698 cmdStr = "onos:leaders -j"
Jon Hallc6793552016-01-19 14:18:37 -08003699 rawOutput = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003700 assert rawOutput is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003701 assert "Command not found:" not in rawOutput, rawOutput
3702 output = json.loads( rawOutput )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003703 results = []
3704 for dict in output:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003705 if dict[ "topic" ] == topic:
3706 leader = dict[ "leader" ]
3707 candidates = re.split( ", ", dict[ "candidates" ][ 1:-1 ] )
Jon Hallc6793552016-01-19 14:18:37 -08003708 results.append( leader )
3709 results.extend( candidates )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003710 return results
Jon Hallc6793552016-01-19 14:18:37 -08003711 except AssertionError:
3712 main.log.exception( "" )
3713 return None
3714 except ( TypeError, ValueError ):
3715 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawOutput ) )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003716 return None
3717 except pexpect.EOF:
3718 main.log.error( self.name + ": EOF exception found" )
3719 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003720 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003721 except Exception:
3722 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003723 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003724
Jon Hall61282e32015-03-19 11:34:11 -07003725 def pendingMap( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003726 """
3727 Returns the output of the intent Pending map.
3728 """
Jon Hall63604932015-02-26 17:09:50 -08003729 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003730 cmdStr = "onos:intents -p"
Jon Hall61282e32015-03-19 11:34:11 -07003731 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003732 cmdStr += " -j"
3733 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003734 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003735 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003736 return output
Jon Hallc6793552016-01-19 14:18:37 -08003737 except AssertionError:
3738 main.log.exception( "" )
3739 return None
Jon Hall63604932015-02-26 17:09:50 -08003740 except TypeError:
3741 main.log.exception( self.name + ": Object not as expected" )
3742 return None
3743 except pexpect.EOF:
3744 main.log.error( self.name + ": EOF exception found" )
3745 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003746 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003747 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003748 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003749 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003750
Jon Hall2c8959e2016-12-16 12:17:34 -08003751 def partitions( self, candidates=False, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003752 """
3753 Returns the output of the raft partitions command for ONOS.
3754 """
Jon Hall61282e32015-03-19 11:34:11 -07003755 # Sample JSON
3756 # {
3757 # "leader": "tcp://10.128.30.11:7238",
3758 # "members": [
3759 # "tcp://10.128.30.11:7238",
3760 # "tcp://10.128.30.17:7238",
3761 # "tcp://10.128.30.13:7238",
3762 # ],
3763 # "name": "p1",
3764 # "term": 3
3765 # },
Jon Hall63604932015-02-26 17:09:50 -08003766 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003767 cmdStr = "onos:partitions"
Jon Hall2c8959e2016-12-16 12:17:34 -08003768 if candidates:
3769 cmdStr += " -c"
Jon Hall61282e32015-03-19 11:34:11 -07003770 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003771 cmdStr += " -j"
3772 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003773 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003774 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003775 return output
Jon Hallc6793552016-01-19 14:18:37 -08003776 except AssertionError:
3777 main.log.exception( "" )
3778 return None
Jon Hall63604932015-02-26 17:09:50 -08003779 except TypeError:
3780 main.log.exception( self.name + ": Object not as expected" )
3781 return None
3782 except pexpect.EOF:
3783 main.log.error( self.name + ": EOF exception found" )
3784 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003785 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003786 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003787 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003788 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003789
Jon Halle9f909e2016-09-23 10:43:12 -07003790 def apps( self, summary=False, active=False, jsonFormat=True ):
Jon Hallbe379602015-03-24 13:39:32 -07003791 """
3792 Returns the output of the apps command for ONOS. This command lists
3793 information about installed ONOS applications
3794 """
3795 # Sample JSON object
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003796 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
Jon Hallbe379602015-03-24 13:39:32 -07003797 # "description":"ONOS OpenFlow protocol southbound providers",
3798 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003799 # "features":"[onos-openflow]","state":"ACTIVE"}]
Jon Hallbe379602015-03-24 13:39:32 -07003800 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003801 cmdStr = "onos:apps"
Jon Hallf03ae762019-01-22 13:25:27 -08003802 expectJson = False
Jon Halle9f909e2016-09-23 10:43:12 -07003803 if summary:
3804 cmdStr += " -s"
3805 if active:
3806 cmdStr += " -a"
Jon Hallbe379602015-03-24 13:39:32 -07003807 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003808 cmdStr += " -j"
Jon Hallf03ae762019-01-22 13:25:27 -08003809 expectJson = True
3810 output = self.sendline( cmdStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07003811 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003812 assert "Command not found:" not in output, output
3813 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003814 return output
Jon Hallbe379602015-03-24 13:39:32 -07003815 # FIXME: look at specific exceptions/Errors
3816 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07003817 main.log.exception( self.name + ": Error in processing onos:app command." )
Jon Hallbe379602015-03-24 13:39:32 -07003818 return None
3819 except TypeError:
3820 main.log.exception( self.name + ": Object not as expected" )
3821 return None
3822 except pexpect.EOF:
3823 main.log.error( self.name + ": EOF exception found" )
3824 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003825 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003826 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003827 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003828 main.cleanAndExit()
Jon Hallbe379602015-03-24 13:39:32 -07003829
You Wangcdc51fe2018-08-12 17:14:56 -07003830 def appStatus( self, appName ):
Jon Hall146f1522015-03-24 15:33:24 -07003831 """
3832 Uses the onos:apps cli command to return the status of an application.
3833 Returns:
3834 "ACTIVE" - If app is installed and activated
3835 "INSTALLED" - If app is installed and deactivated
3836 "UNINSTALLED" - If app is not installed
3837 None - on error
3838 """
Jon Hall146f1522015-03-24 15:33:24 -07003839 try:
3840 if not isinstance( appName, types.StringType ):
3841 main.log.error( self.name + ".appStatus(): appName must be" +
3842 " a string" )
3843 return None
3844 output = self.apps( jsonFormat=True )
3845 appsJson = json.loads( output )
3846 state = None
3847 for app in appsJson:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003848 if appName == app.get( 'name' ):
3849 state = app.get( 'state' )
Jon Hall146f1522015-03-24 15:33:24 -07003850 break
3851 if state == "ACTIVE" or state == "INSTALLED":
3852 return state
3853 elif state is None:
You Wang0d9f2c02018-08-10 14:56:32 -07003854 main.log.warn( "{} app not found".format( appName ) )
Jon Hall146f1522015-03-24 15:33:24 -07003855 return "UNINSTALLED"
3856 elif state:
3857 main.log.error( "Unexpected state from 'onos:apps': " +
3858 str( state ) )
3859 return state
Jon Hallc6793552016-01-19 14:18:37 -08003860 except ( TypeError, ValueError ):
3861 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003862 return None
3863 except pexpect.EOF:
3864 main.log.error( self.name + ": EOF exception found" )
3865 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003866 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003867 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003868 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003869 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003870
Jon Hallbe379602015-03-24 13:39:32 -07003871 def app( self, appName, option ):
3872 """
3873 Interacts with the app command for ONOS. This command manages
3874 application inventory.
3875 """
Jon Hallbe379602015-03-24 13:39:32 -07003876 try:
Jon Hallbd16b922015-03-26 17:53:15 -07003877 # Validate argument types
3878 valid = True
3879 if not isinstance( appName, types.StringType ):
3880 main.log.error( self.name + ".app(): appName must be a " +
3881 "string" )
3882 valid = False
3883 if not isinstance( option, types.StringType ):
3884 main.log.error( self.name + ".app(): option must be a string" )
3885 valid = False
3886 if not valid:
3887 return main.FALSE
3888 # Validate Option
3889 option = option.lower()
3890 # NOTE: Install may become a valid option
3891 if option == "activate":
3892 pass
3893 elif option == "deactivate":
3894 pass
3895 elif option == "uninstall":
3896 pass
3897 else:
3898 # Invalid option
3899 main.log.error( "The ONOS app command argument only takes " +
3900 "the values: (activate|deactivate|uninstall)" +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003901 "; was given '" + option + "'" )
Jon Hallbd16b922015-03-26 17:53:15 -07003902 return main.FALSE
Jon Hall146f1522015-03-24 15:33:24 -07003903 cmdStr = "onos:app " + option + " " + appName
Jon Hallbe379602015-03-24 13:39:32 -07003904 output = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003905 assert output is not None, "Error in sendline"
3906 assert "Command not found:" not in output, output
Jon Hallbe379602015-03-24 13:39:32 -07003907 if "Error executing command" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003908 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hallbe379602015-03-24 13:39:32 -07003909 str( output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003910 return main.FALSE
Jon Hallbe379602015-03-24 13:39:32 -07003911 elif "No such application" in output:
3912 main.log.error( "The application '" + appName +
3913 "' is not installed in ONOS" )
Jon Hall146f1522015-03-24 15:33:24 -07003914 return main.FALSE
3915 elif "Command not found:" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003916 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hall146f1522015-03-24 15:33:24 -07003917 str( output ) )
3918 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003919 elif "Unsupported command:" in output:
3920 main.log.error( "Incorrect command given to 'app': " +
3921 str( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003922 # NOTE: we may need to add more checks here
Jon Hallbd16b922015-03-26 17:53:15 -07003923 # else: Command was successful
Jon Hall08f61bc2015-04-13 16:00:30 -07003924 # main.log.debug( "app response: " + repr( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003925 return main.TRUE
You Wangb5a55f72017-03-03 12:51:05 -08003926 except AssertionError:
3927 main.log.exception( self.name + ": AssertionError exception found" )
3928 return main.ERROR
Jon Hallbe379602015-03-24 13:39:32 -07003929 except TypeError:
3930 main.log.exception( self.name + ": Object not as expected" )
3931 return main.ERROR
3932 except pexpect.EOF:
3933 main.log.error( self.name + ": EOF exception found" )
3934 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003935 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003936 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003937 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003938 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003939
Jon Hallbd16b922015-03-26 17:53:15 -07003940 def activateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003941 """
3942 Activate an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003943 appName is the hierarchical app name, not the feature name
3944 If check is True, method will check the status of the app after the
3945 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003946 Returns main.TRUE if the command was successfully sent
3947 main.FALSE if the cli responded with an error or given
3948 incorrect input
3949 """
3950 try:
3951 if not isinstance( appName, types.StringType ):
3952 main.log.error( self.name + ".activateApp(): appName must be" +
3953 " a string" )
3954 return main.FALSE
3955 status = self.appStatus( appName )
3956 if status == "INSTALLED":
3957 response = self.app( appName, "activate" )
Jon Hallbd16b922015-03-26 17:53:15 -07003958 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003959 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07003960 status = self.appStatus( appName )
3961 if status == "ACTIVE":
3962 return main.TRUE
3963 else:
Jon Hall050e1bd2015-03-30 13:33:02 -07003964 main.log.debug( "The state of application " +
3965 appName + " is " + status )
Jon Hallbd16b922015-03-26 17:53:15 -07003966 time.sleep( 1 )
3967 return main.FALSE
3968 else: # not 'check' or command didn't succeed
3969 return response
Jon Hall146f1522015-03-24 15:33:24 -07003970 elif status == "ACTIVE":
3971 return main.TRUE
3972 elif status == "UNINSTALLED":
3973 main.log.error( self.name + ": Tried to activate the " +
3974 "application '" + appName + "' which is not " +
3975 "installed." )
3976 else:
3977 main.log.error( "Unexpected return value from appStatus: " +
3978 str( status ) )
3979 return main.ERROR
3980 except TypeError:
3981 main.log.exception( self.name + ": Object not as expected" )
3982 return main.ERROR
3983 except pexpect.EOF:
3984 main.log.error( self.name + ": EOF exception found" )
3985 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003986 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003987 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003988 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003989 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003990
Jon Hallbd16b922015-03-26 17:53:15 -07003991 def deactivateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003992 """
3993 Deactivate an app that is already activated in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003994 appName is the hierarchical app name, not the feature name
3995 If check is True, method will check the status of the app after the
3996 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07003997 Returns main.TRUE if the command was successfully sent
3998 main.FALSE if the cli responded with an error or given
3999 incorrect input
4000 """
4001 try:
4002 if not isinstance( appName, types.StringType ):
4003 main.log.error( self.name + ".deactivateApp(): appName must " +
4004 "be a string" )
4005 return main.FALSE
4006 status = self.appStatus( appName )
4007 if status == "INSTALLED":
4008 return main.TRUE
4009 elif status == "ACTIVE":
4010 response = self.app( appName, "deactivate" )
Jon Hallbd16b922015-03-26 17:53:15 -07004011 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004012 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004013 status = self.appStatus( appName )
4014 if status == "INSTALLED":
4015 return main.TRUE
4016 else:
4017 time.sleep( 1 )
4018 return main.FALSE
4019 else: # not check or command didn't succeed
4020 return response
Jon Hall146f1522015-03-24 15:33:24 -07004021 elif status == "UNINSTALLED":
4022 main.log.warn( self.name + ": Tried to deactivate the " +
4023 "application '" + appName + "' which is not " +
4024 "installed." )
4025 return main.TRUE
4026 else:
4027 main.log.error( "Unexpected return value from appStatus: " +
4028 str( status ) )
4029 return main.ERROR
4030 except TypeError:
4031 main.log.exception( self.name + ": Object not as expected" )
4032 return main.ERROR
4033 except pexpect.EOF:
4034 main.log.error( self.name + ": EOF exception found" )
4035 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004036 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004037 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004038 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004039 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004040
Jon Hallbd16b922015-03-26 17:53:15 -07004041 def uninstallApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004042 """
4043 Uninstall an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004044 appName is the hierarchical app name, not the feature name
4045 If check is True, method will check the status of the app after the
4046 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004047 Returns main.TRUE if the command was successfully sent
4048 main.FALSE if the cli responded with an error or given
4049 incorrect input
4050 """
4051 # TODO: check with Thomas about the state machine for apps
4052 try:
4053 if not isinstance( appName, types.StringType ):
4054 main.log.error( self.name + ".uninstallApp(): appName must " +
4055 "be a string" )
4056 return main.FALSE
4057 status = self.appStatus( appName )
4058 if status == "INSTALLED":
4059 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004060 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004061 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004062 status = self.appStatus( appName )
4063 if status == "UNINSTALLED":
4064 return main.TRUE
4065 else:
4066 time.sleep( 1 )
4067 return main.FALSE
4068 else: # not check or command didn't succeed
4069 return response
Jon Hall146f1522015-03-24 15:33:24 -07004070 elif status == "ACTIVE":
4071 main.log.warn( self.name + ": Tried to uninstall the " +
4072 "application '" + appName + "' which is " +
4073 "currently active." )
4074 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004075 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004076 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004077 status = self.appStatus( appName )
4078 if status == "UNINSTALLED":
4079 return main.TRUE
4080 else:
4081 time.sleep( 1 )
4082 return main.FALSE
4083 else: # not check or command didn't succeed
4084 return response
Jon Hall146f1522015-03-24 15:33:24 -07004085 elif status == "UNINSTALLED":
4086 return main.TRUE
4087 else:
4088 main.log.error( "Unexpected return value from appStatus: " +
4089 str( status ) )
4090 return main.ERROR
4091 except TypeError:
4092 main.log.exception( self.name + ": Object not as expected" )
4093 return main.ERROR
4094 except pexpect.EOF:
4095 main.log.error( self.name + ": EOF exception found" )
4096 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004097 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004098 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004099 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004100 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004101
4102 def appIDs( self, jsonFormat=True ):
4103 """
4104 Show the mappings between app id and app names given by the 'app-ids'
4105 cli command
4106 """
4107 try:
4108 cmdStr = "app-ids"
4109 if jsonFormat:
4110 cmdStr += " -j"
Jon Hallc6358dd2015-04-10 12:44:28 -07004111 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004112 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004113 assert "Command not found:" not in output, output
4114 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07004115 return output
Jon Hallbd16b922015-03-26 17:53:15 -07004116 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004117 main.log.exception( self.name + ": Error in processing onos:app-ids command." )
Jon Hallbd16b922015-03-26 17:53:15 -07004118 return None
4119 except TypeError:
4120 main.log.exception( self.name + ": Object not as expected" )
4121 return None
4122 except pexpect.EOF:
4123 main.log.error( self.name + ": EOF exception found" )
4124 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004125 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004126 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004127 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004128 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004129
4130 def appToIDCheck( self ):
4131 """
4132 This method will check that each application's ID listed in 'apps' is
4133 the same as the ID listed in 'app-ids'. The check will also check that
4134 there are no duplicate IDs issued. Note that an app ID should be
4135 a globaly unique numerical identifier for app/app-like features. Once
4136 an ID is registered, the ID is never freed up so that if an app is
4137 reinstalled it will have the same ID.
4138
4139 Returns: main.TRUE if the check passes and
4140 main.FALSE if the check fails or
4141 main.ERROR if there is some error in processing the test
4142 """
4143 try:
Jon Hall0e240372018-05-02 11:21:57 -07004144 # Grab IDs
Jon Hallc6793552016-01-19 14:18:37 -08004145 rawJson = self.appIDs( jsonFormat=True )
4146 if rawJson:
4147 ids = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004148 else:
Jon Hall0e240372018-05-02 11:21:57 -07004149 main.log.error( "app-ids returned nothing: " + repr( rawJson ) )
4150 return main.FALSE
4151
4152 # Grab Apps
Jon Hallc6793552016-01-19 14:18:37 -08004153 rawJson = self.apps( jsonFormat=True )
4154 if rawJson:
4155 apps = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004156 else:
Jon Hallc6793552016-01-19 14:18:37 -08004157 main.log.error( "apps returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07004158 return main.FALSE
Jon Hall0e240372018-05-02 11:21:57 -07004159
Jon Hallbd16b922015-03-26 17:53:15 -07004160 result = main.TRUE
4161 for app in apps:
4162 appID = app.get( 'id' )
4163 if appID is None:
4164 main.log.error( "Error parsing app: " + str( app ) )
4165 result = main.FALSE
4166 appName = app.get( 'name' )
4167 if appName is None:
4168 main.log.error( "Error parsing app: " + str( app ) )
4169 result = main.FALSE
4170 # get the entry in ids that has the same appID
Jon Hall390696c2015-05-05 17:13:41 -07004171 current = filter( lambda item: item[ 'id' ] == appID, ids )
Jon Hallbd16b922015-03-26 17:53:15 -07004172 if not current: # if ids doesn't have this id
4173 result = main.FALSE
4174 main.log.error( "'app-ids' does not have the ID for " +
4175 str( appName ) + " that apps does." )
Jon Hallb9d381e2018-02-05 12:02:10 -08004176 main.log.debug( "apps command returned: " + str( app ) +
4177 "; app-ids has: " + str( ids ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004178 elif len( current ) > 1:
4179 # there is more than one app with this ID
4180 result = main.FALSE
4181 # We will log this later in the method
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004182 elif not current[ 0 ][ 'name' ] == appName:
4183 currentName = current[ 0 ][ 'name' ]
Jon Hallbd16b922015-03-26 17:53:15 -07004184 result = main.FALSE
4185 main.log.error( "'app-ids' has " + str( currentName ) +
4186 " registered under id:" + str( appID ) +
4187 " but 'apps' has " + str( appName ) )
4188 else:
4189 pass # id and name match!
Jon Hall0e240372018-05-02 11:21:57 -07004190
Jon Hallbd16b922015-03-26 17:53:15 -07004191 # now make sure that app-ids has no duplicates
4192 idsList = []
4193 namesList = []
4194 for item in ids:
4195 idsList.append( item[ 'id' ] )
4196 namesList.append( item[ 'name' ] )
4197 if len( idsList ) != len( set( idsList ) ) or\
4198 len( namesList ) != len( set( namesList ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004199 main.log.error( "'app-ids' has some duplicate entries: \n"
4200 + json.dumps( ids,
4201 sort_keys=True,
4202 indent=4,
4203 separators=( ',', ': ' ) ) )
4204 result = main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07004205 return result
Jon Hallc6793552016-01-19 14:18:37 -08004206 except ( TypeError, ValueError ):
4207 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004208 return main.ERROR
4209 except pexpect.EOF:
4210 main.log.error( self.name + ": EOF exception found" )
4211 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004212 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004213 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004214 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004215 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004216
Jon Hallfb760a02015-04-13 15:35:03 -07004217 def getCfg( self, component=None, propName=None, short=False,
4218 jsonFormat=True ):
4219 """
4220 Get configuration settings from onos cli
4221 Optional arguments:
4222 component - Optionally only list configurations for a specific
4223 component. If None, all components with configurations
4224 are displayed. Case Sensitive string.
4225 propName - If component is specified, propName option will show
4226 only this specific configuration from that component.
4227 Case Sensitive string.
4228 jsonFormat - Returns output as json. Note that this will override
4229 the short option
4230 short - Short, less verbose, version of configurations.
4231 This is overridden by the json option
4232 returns:
4233 Output from cli as a string or None on error
4234 """
4235 try:
4236 baseStr = "cfg"
4237 cmdStr = " get"
4238 componentStr = ""
4239 if component:
4240 componentStr += " " + component
4241 if propName:
4242 componentStr += " " + propName
4243 if jsonFormat:
4244 baseStr += " -j"
Jon Hall22e94ce2019-01-15 14:52:17 -08004245 expectJson = True
Jon Hallfb760a02015-04-13 15:35:03 -07004246 elif short:
4247 baseStr += " -s"
Jon Hall22e94ce2019-01-15 14:52:17 -08004248 expectJson = False
4249 output = self.sendline( baseStr + cmdStr + componentStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07004250 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004251 assert "Command not found:" not in output, output
4252 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004253 return output
4254 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004255 main.log.exception( self.name + ": Error in processing 'cfg get' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004256 return None
4257 except TypeError:
4258 main.log.exception( self.name + ": Object not as expected" )
4259 return None
4260 except pexpect.EOF:
4261 main.log.error( self.name + ": EOF exception found" )
4262 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004263 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004264 except Exception:
4265 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004266 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004267
4268 def setCfg( self, component, propName, value=None, check=True ):
4269 """
4270 Set/Unset configuration settings from ONOS cli
Jon Hall390696c2015-05-05 17:13:41 -07004271 Required arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004272 component - The case sensitive name of the component whose
4273 property is to be set
4274 propName - The case sensitive name of the property to be set/unset
Jon Hall390696c2015-05-05 17:13:41 -07004275 Optional arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004276 value - The value to set the property to. If None, will unset the
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004277 property and revert it to it's default value(if applicable)
Jon Hallfb760a02015-04-13 15:35:03 -07004278 check - Boolean, Check whether the option was successfully set this
4279 only applies when a value is given.
4280 returns:
4281 main.TRUE on success or main.FALSE on failure. If check is False,
4282 will return main.TRUE unless there is an error
4283 """
4284 try:
4285 baseStr = "cfg"
4286 cmdStr = " set " + str( component ) + " " + str( propName )
4287 if value is not None:
4288 cmdStr += " " + str( value )
4289 output = self.sendline( baseStr + cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004290 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004291 assert "Command not found:" not in output, output
4292 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004293 if value and check:
4294 results = self.getCfg( component=str( component ),
4295 propName=str( propName ),
4296 jsonFormat=True )
4297 # Check if current value is what we just set
4298 try:
4299 jsonOutput = json.loads( results )
4300 current = jsonOutput[ 'value' ]
Jon Hallc6793552016-01-19 14:18:37 -08004301 except ( TypeError, ValueError ):
Jon Hallfb760a02015-04-13 15:35:03 -07004302 main.log.exception( "Error parsing cfg output" )
4303 main.log.error( "output:" + repr( results ) )
4304 return main.FALSE
4305 if current == str( value ):
4306 return main.TRUE
4307 return main.FALSE
4308 return main.TRUE
4309 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004310 main.log.exception( self.name + ": Error in processing 'cfg set' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004311 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08004312 except ( TypeError, ValueError ):
4313 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, results ) )
Jon Hallfb760a02015-04-13 15:35:03 -07004314 return main.FALSE
4315 except pexpect.EOF:
4316 main.log.error( self.name + ": EOF exception found" )
4317 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004318 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004319 except Exception:
4320 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004321 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004322
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004323 def distPrimitivesSend( self, cmd ):
4324 """
4325 Function to handle sending cli commands for the distributed primitives test app
4326
4327 This command will catch some exceptions and retry the command on some
4328 specific store exceptions.
4329
4330 Required arguments:
4331 cmd - The command to send to the cli
4332 returns:
4333 string containing the cli output
4334 None on Error
4335 """
4336 try:
4337 output = self.sendline( cmd )
4338 try:
4339 assert output is not None, "Error in sendline"
4340 # TODO: Maybe make this less hardcoded
4341 # ConsistentMap Exceptions
4342 assert "org.onosproject.store.service" not in output
4343 # Node not leader
4344 assert "java.lang.IllegalStateException" not in output
4345 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004346 main.log.error( self.name + ": Error in processing '" + cmd + "' " +
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004347 "command: " + str( output ) )
4348 retryTime = 30 # Conservative time, given by Madan
4349 main.log.info( "Waiting " + str( retryTime ) +
4350 "seconds before retrying." )
4351 time.sleep( retryTime ) # Due to change in mastership
4352 output = self.sendline( cmd )
4353 assert output is not None, "Error in sendline"
4354 assert "Command not found:" not in output, output
4355 assert "Error executing command" not in output, output
4356 main.log.info( self.name + ": " + output )
4357 return output
4358 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004359 main.log.exception( self.name + ": Error in processing '" + cmd + "' command." )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004360 return None
4361 except TypeError:
4362 main.log.exception( self.name + ": Object not as expected" )
4363 return None
4364 except pexpect.EOF:
4365 main.log.error( self.name + ": EOF exception found" )
4366 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004367 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004368 except Exception:
4369 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004370 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004371
Jon Hall390696c2015-05-05 17:13:41 -07004372 def setTestAdd( self, setName, values ):
4373 """
4374 CLI command to add elements to a distributed set.
4375 Arguments:
4376 setName - The name of the set to add to.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004377 values - The value(s) to add to the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004378 Example usages:
4379 setTestAdd( "set1", "a b c" )
4380 setTestAdd( "set2", "1" )
4381 returns:
4382 main.TRUE on success OR
4383 main.FALSE if elements were already in the set OR
4384 main.ERROR on error
4385 """
4386 try:
4387 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004388 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004389 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
4390 negativeMatch = "\[(.*)\] was already in set " + str( setName )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004391 if re.search( positiveMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004392 return main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004393 elif re.search( negativeMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004394 return main.FALSE
4395 else:
4396 main.log.error( self.name + ": setTestAdd did not" +
4397 " match expected output" )
Jon Hall390696c2015-05-05 17:13:41 -07004398 main.log.debug( self.name + " actual: " + repr( output ) )
4399 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004400 except TypeError:
4401 main.log.exception( self.name + ": Object not as expected" )
4402 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004403 except Exception:
4404 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004405 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004406
4407 def setTestRemove( self, setName, values, clear=False, retain=False ):
4408 """
4409 CLI command to remove elements from a distributed set.
4410 Required arguments:
4411 setName - The name of the set to remove from.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004412 values - The value(s) to remove from the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004413 Optional arguments:
4414 clear - Clear all elements from the set
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004415 retain - Retain only the given values. (intersection of the
4416 original set and the given set)
Jon Hall390696c2015-05-05 17:13:41 -07004417 returns:
4418 main.TRUE on success OR
4419 main.FALSE if the set was not changed OR
4420 main.ERROR on error
4421 """
4422 try:
4423 cmdStr = "set-test-remove "
4424 if clear:
4425 cmdStr += "-c " + str( setName )
4426 elif retain:
4427 cmdStr += "-r " + str( setName ) + " " + str( values )
4428 else:
4429 cmdStr += str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004430 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004431 if clear:
4432 pattern = "Set " + str( setName ) + " cleared"
4433 if re.search( pattern, output ):
4434 return main.TRUE
4435 elif retain:
4436 positivePattern = str( setName ) + " was pruned to contain " +\
4437 "only elements of set \[(.*)\]"
4438 negativePattern = str( setName ) + " was not changed by " +\
4439 "retaining only elements of the set " +\
4440 "\[(.*)\]"
4441 if re.search( positivePattern, output ):
4442 return main.TRUE
4443 elif re.search( negativePattern, output ):
4444 return main.FALSE
4445 else:
4446 positivePattern = "\[(.*)\] was removed from the set " +\
4447 str( setName )
4448 if ( len( values.split() ) == 1 ):
4449 negativePattern = "\[(.*)\] was not in set " +\
4450 str( setName )
4451 else:
4452 negativePattern = "No element of \[(.*)\] was in set " +\
4453 str( setName )
4454 if re.search( positivePattern, output ):
4455 return main.TRUE
4456 elif re.search( negativePattern, output ):
4457 return main.FALSE
4458 main.log.error( self.name + ": setTestRemove did not" +
4459 " match expected output" )
4460 main.log.debug( self.name + " expected: " + pattern )
4461 main.log.debug( self.name + " actual: " + repr( output ) )
4462 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004463 except TypeError:
4464 main.log.exception( self.name + ": Object not as expected" )
4465 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004466 except Exception:
4467 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004468 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004469
4470 def setTestGet( self, setName, values="" ):
4471 """
4472 CLI command to get the elements in a distributed set.
4473 Required arguments:
4474 setName - The name of the set to remove from.
4475 Optional arguments:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004476 values - The value(s) to check if in the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004477 returns:
4478 main.ERROR on error OR
4479 A list of elements in the set if no optional arguments are
4480 supplied OR
4481 A tuple containing the list then:
4482 main.FALSE if the given values are not in the set OR
4483 main.TRUE if the given values are in the set OR
4484 """
4485 try:
4486 values = str( values ).strip()
4487 setName = str( setName ).strip()
4488 length = len( values.split() )
4489 containsCheck = None
4490 # Patterns to match
4491 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004492 pattern = "Items in set " + setName + ":\r\n" + setPattern
Jon Hall390696c2015-05-05 17:13:41 -07004493 containsTrue = "Set " + setName + " contains the value " + values
4494 containsFalse = "Set " + setName + " did not contain the value " +\
4495 values
4496 containsAllTrue = "Set " + setName + " contains the the subset " +\
4497 setPattern
4498 containsAllFalse = "Set " + setName + " did not contain the the" +\
4499 " subset " + setPattern
4500
4501 cmdStr = "set-test-get "
4502 cmdStr += setName + " " + values
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004503 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004504 if length == 0:
4505 match = re.search( pattern, output )
4506 else: # if given values
4507 if length == 1: # Contains output
Jon Hall54b994f2016-12-05 10:48:59 -08004508 patternTrue = pattern + "\r\n" + containsTrue
4509 patternFalse = pattern + "\r\n" + containsFalse
Jon Hall390696c2015-05-05 17:13:41 -07004510 else: # ContainsAll output
Jon Hall54b994f2016-12-05 10:48:59 -08004511 patternTrue = pattern + "\r\n" + containsAllTrue
4512 patternFalse = pattern + "\r\n" + containsAllFalse
Jon Hall390696c2015-05-05 17:13:41 -07004513 matchTrue = re.search( patternTrue, output )
4514 matchFalse = re.search( patternFalse, output )
4515 if matchTrue:
4516 containsCheck = main.TRUE
4517 match = matchTrue
4518 elif matchFalse:
4519 containsCheck = main.FALSE
4520 match = matchFalse
4521 else:
Jon Halle0f0b342017-04-18 11:43:47 -07004522 main.log.error( self.name + " setTestGet did not match " +
Jon Hall390696c2015-05-05 17:13:41 -07004523 "expected output" )
4524 main.log.debug( self.name + " expected: " + pattern )
4525 main.log.debug( self.name + " actual: " + repr( output ) )
4526 match = None
4527 if match:
4528 setMatch = match.group( 1 )
4529 if setMatch == '':
4530 setList = []
4531 else:
4532 setList = setMatch.split( ", " )
4533 if length > 0:
4534 return ( setList, containsCheck )
4535 else:
4536 return setList
4537 else: # no match
4538 main.log.error( self.name + ": setTestGet did not" +
4539 " match expected output" )
4540 main.log.debug( self.name + " expected: " + pattern )
4541 main.log.debug( self.name + " actual: " + repr( output ) )
4542 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004543 except TypeError:
4544 main.log.exception( self.name + ": Object not as expected" )
4545 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004546 except Exception:
4547 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004548 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004549
4550 def setTestSize( self, setName ):
4551 """
4552 CLI command to get the elements in a distributed set.
4553 Required arguments:
4554 setName - The name of the set to remove from.
4555 returns:
Jon Hallfeff3082015-05-19 10:23:26 -07004556 The integer value of the size returned or
Jon Hall390696c2015-05-05 17:13:41 -07004557 None on error
4558 """
4559 try:
4560 # TODO: Should this check against the number of elements returned
4561 # and then return true/false based on that?
4562 setName = str( setName ).strip()
4563 # Patterns to match
4564 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004565 pattern = "There are (\d+) items in set " + setName + ":\r\n" +\
Jon Hall390696c2015-05-05 17:13:41 -07004566 setPattern
4567 cmdStr = "set-test-get -s "
4568 cmdStr += setName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004569 output = self.distPrimitivesSend( cmdStr )
Jon Hall0e240372018-05-02 11:21:57 -07004570 if output:
4571 match = re.search( pattern, output )
4572 if match:
4573 setSize = int( match.group( 1 ) )
4574 setMatch = match.group( 2 )
4575 if len( setMatch.split() ) == setSize:
4576 main.log.info( "The size returned by " + self.name +
4577 " matches the number of elements in " +
4578 "the returned set" )
4579 else:
4580 main.log.error( "The size returned by " + self.name +
4581 " does not match the number of " +
4582 "elements in the returned set." )
4583 return setSize
Jon Hall390696c2015-05-05 17:13:41 -07004584 else: # no match
4585 main.log.error( self.name + ": setTestGet did not" +
4586 " match expected output" )
4587 main.log.debug( self.name + " expected: " + pattern )
4588 main.log.debug( self.name + " actual: " + repr( output ) )
4589 return None
Jon Hall390696c2015-05-05 17:13:41 -07004590 except TypeError:
4591 main.log.exception( self.name + ": Object not as expected" )
4592 return None
Jon Hall390696c2015-05-05 17:13:41 -07004593 except Exception:
4594 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004595 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004596
Jon Hall80daded2015-05-27 16:07:00 -07004597 def counters( self, jsonFormat=True ):
Jon Hall390696c2015-05-05 17:13:41 -07004598 """
4599 Command to list the various counters in the system.
4600 returns:
Jon Hall80daded2015-05-27 16:07:00 -07004601 if jsonFormat, a string of the json object returned by the cli
4602 command
4603 if not jsonFormat, the normal string output of the cli command
Jon Hall390696c2015-05-05 17:13:41 -07004604 None on error
4605 """
Jon Hall390696c2015-05-05 17:13:41 -07004606 try:
Jon Hall390696c2015-05-05 17:13:41 -07004607 cmdStr = "counters"
Jon Hall80daded2015-05-27 16:07:00 -07004608 if jsonFormat:
4609 cmdStr += " -j"
Jon Hall390696c2015-05-05 17:13:41 -07004610 output = self.sendline( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004611 main.log.debug( self.name + ": Counters unparsed: " + output )
4612 output = output.split( "\r\n" )[ -1 ]
4613 main.log.debug( self.name + ": Counters parsed: " + output )
Jon Halla495f562016-05-16 18:03:26 -07004614 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004615 assert "Command not found:" not in output, output
4616 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004617 main.log.info( self.name + ": " + output )
Jon Hall80daded2015-05-27 16:07:00 -07004618 return output
Jon Hall390696c2015-05-05 17:13:41 -07004619 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004620 main.log.exception( self.name + ": Error in processing 'counters' command." )
Jon Hall80daded2015-05-27 16:07:00 -07004621 return None
Jon Hall390696c2015-05-05 17:13:41 -07004622 except TypeError:
4623 main.log.exception( self.name + ": Object not as expected" )
Jon Hall80daded2015-05-27 16:07:00 -07004624 return None
Jon Hall390696c2015-05-05 17:13:41 -07004625 except pexpect.EOF:
4626 main.log.error( self.name + ": EOF exception found" )
4627 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004628 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004629 except Exception:
4630 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004631 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004632
Jon Hall935db192016-04-19 00:22:04 -07004633 def counterTestAddAndGet( self, counter, delta=1 ):
Jon Hall390696c2015-05-05 17:13:41 -07004634 """
Jon Halle1a3b752015-07-22 13:02:46 -07004635 CLI command to add a delta to then get a distributed counter.
Jon Hall390696c2015-05-05 17:13:41 -07004636 Required arguments:
4637 counter - The name of the counter to increment.
4638 Optional arguments:
Jon Halle1a3b752015-07-22 13:02:46 -07004639 delta - The long to add to the counter
Jon Hall390696c2015-05-05 17:13:41 -07004640 returns:
4641 integer value of the counter or
4642 None on Error
4643 """
4644 try:
4645 counter = str( counter )
Jon Halle1a3b752015-07-22 13:02:46 -07004646 delta = int( delta )
Jon Hall390696c2015-05-05 17:13:41 -07004647 cmdStr = "counter-test-increment "
Jon Hall390696c2015-05-05 17:13:41 -07004648 cmdStr += counter
Jon Halle1a3b752015-07-22 13:02:46 -07004649 if delta != 1:
4650 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004651 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004652 pattern = counter + " was updated to (-?\d+)"
Jon Hall390696c2015-05-05 17:13:41 -07004653 match = re.search( pattern, output )
4654 if match:
4655 return int( match.group( 1 ) )
4656 else:
Jon Halle1a3b752015-07-22 13:02:46 -07004657 main.log.error( self.name + ": counterTestAddAndGet did not" +
Jon Hall390696c2015-05-05 17:13:41 -07004658 " match expected output." )
4659 main.log.debug( self.name + " expected: " + pattern )
4660 main.log.debug( self.name + " actual: " + repr( output ) )
4661 return None
Jon Hall390696c2015-05-05 17:13:41 -07004662 except TypeError:
4663 main.log.exception( self.name + ": Object not as expected" )
4664 return None
Jon Hall390696c2015-05-05 17:13:41 -07004665 except Exception:
4666 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004667 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004668
Jon Hall935db192016-04-19 00:22:04 -07004669 def counterTestGetAndAdd( self, counter, delta=1 ):
Jon Halle1a3b752015-07-22 13:02:46 -07004670 """
4671 CLI command to get a distributed counter then add a delta to it.
4672 Required arguments:
4673 counter - The name of the counter to increment.
4674 Optional arguments:
4675 delta - The long to add to the counter
Jon Halle1a3b752015-07-22 13:02:46 -07004676 returns:
4677 integer value of the counter or
4678 None on Error
4679 """
4680 try:
4681 counter = str( counter )
4682 delta = int( delta )
4683 cmdStr = "counter-test-increment -g "
Jon Halle1a3b752015-07-22 13:02:46 -07004684 cmdStr += counter
4685 if delta != 1:
4686 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004687 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004688 pattern = counter + " was updated to (-?\d+)"
4689 match = re.search( pattern, output )
4690 if match:
4691 return int( match.group( 1 ) )
4692 else:
4693 main.log.error( self.name + ": counterTestGetAndAdd did not" +
4694 " match expected output." )
4695 main.log.debug( self.name + " expected: " + pattern )
4696 main.log.debug( self.name + " actual: " + repr( output ) )
4697 return None
Jon Halle1a3b752015-07-22 13:02:46 -07004698 except TypeError:
4699 main.log.exception( self.name + ": Object not as expected" )
4700 return None
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004701 except Exception:
4702 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004703 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004704
4705 def valueTestGet( self, valueName ):
4706 """
4707 CLI command to get the value of an atomic value.
4708 Required arguments:
4709 valueName - The name of the value to get.
4710 returns:
4711 string value of the value or
4712 None on Error
4713 """
4714 try:
4715 valueName = str( valueName )
4716 cmdStr = "value-test "
4717 operation = "get"
4718 cmdStr = "value-test {} {}".format( valueName,
4719 operation )
4720 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004721 main.log.debug( self.name + ": value test unparsed: " + output )
4722 output = output.split( "\r\n" )[ -1 ]
4723 main.log.debug( self.name + ": value test parsed: " + output )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004724 pattern = "(\w+)"
4725 match = re.search( pattern, output )
4726 if match:
4727 return match.group( 1 )
4728 else:
4729 main.log.error( self.name + ": valueTestGet did not" +
4730 " match expected output." )
4731 main.log.debug( self.name + " expected: " + pattern )
4732 main.log.debug( self.name + " actual: " + repr( output ) )
4733 return None
4734 except TypeError:
4735 main.log.exception( self.name + ": Object not as expected" )
4736 return None
4737 except Exception:
4738 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004739 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004740
4741 def valueTestSet( self, valueName, newValue ):
4742 """
4743 CLI command to set the value of an atomic value.
4744 Required arguments:
4745 valueName - The name of the value to set.
4746 newValue - The value to assign to the given value.
4747 returns:
4748 main.TRUE on success or
4749 main.ERROR on Error
4750 """
4751 try:
4752 valueName = str( valueName )
4753 newValue = str( newValue )
4754 operation = "set"
4755 cmdStr = "value-test {} {} {}".format( valueName,
4756 operation,
4757 newValue )
4758 output = self.distPrimitivesSend( cmdStr )
4759 if output is not None:
4760 return main.TRUE
4761 else:
4762 return main.ERROR
4763 except TypeError:
4764 main.log.exception( self.name + ": Object not as expected" )
4765 return main.ERROR
4766 except Exception:
4767 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004768 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004769
4770 def valueTestCompareAndSet( self, valueName, oldValue, newValue ):
4771 """
4772 CLI command to compareAndSet the value of an atomic value.
4773 Required arguments:
4774 valueName - The name of the value.
4775 oldValue - Compare the current value of the atomic value to this
4776 newValue - If the value equals oldValue, set the value to newValue
4777 returns:
4778 main.TRUE on success or
4779 main.FALSE on failure or
4780 main.ERROR on Error
4781 """
4782 try:
4783 valueName = str( valueName )
4784 oldValue = str( oldValue )
4785 newValue = str( newValue )
4786 operation = "compareAndSet"
4787 cmdStr = "value-test {} {} {} {}".format( valueName,
4788 operation,
4789 oldValue,
4790 newValue )
4791 output = self.distPrimitivesSend( cmdStr )
4792 pattern = "(\w+)"
4793 match = re.search( pattern, output )
4794 if match:
4795 result = match.group( 1 )
4796 if result == "true":
4797 return main.TRUE
4798 elif result == "false":
4799 return main.FALSE
4800 else:
4801 main.log.error( self.name + ": valueTestCompareAndSet did not" +
4802 " match expected output." )
4803 main.log.debug( self.name + " expected: " + pattern )
4804 main.log.debug( self.name + " actual: " + repr( output ) )
4805 return main.ERROR
4806 except TypeError:
4807 main.log.exception( self.name + ": Object not as expected" )
4808 return main.ERROR
4809 except Exception:
4810 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004811 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004812
4813 def valueTestGetAndSet( self, valueName, newValue ):
4814 """
4815 CLI command to getAndSet the value of an atomic value.
4816 Required arguments:
4817 valueName - The name of the value to get.
4818 newValue - The value to assign to the given value
4819 returns:
4820 string value of the value or
4821 None on Error
4822 """
4823 try:
4824 valueName = str( valueName )
4825 cmdStr = "value-test "
4826 operation = "getAndSet"
4827 cmdStr += valueName + " " + operation
4828 cmdStr = "value-test {} {} {}".format( valueName,
4829 operation,
4830 newValue )
4831 output = self.distPrimitivesSend( cmdStr )
4832 pattern = "(\w+)"
4833 match = re.search( pattern, output )
4834 if match:
4835 return match.group( 1 )
4836 else:
4837 main.log.error( self.name + ": valueTestGetAndSet did not" +
4838 " match expected output." )
4839 main.log.debug( self.name + " expected: " + pattern )
4840 main.log.debug( self.name + " actual: " + repr( output ) )
4841 return None
4842 except TypeError:
4843 main.log.exception( self.name + ": Object not as expected" )
4844 return None
4845 except Exception:
4846 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004847 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004848
4849 def valueTestDestroy( self, valueName ):
4850 """
4851 CLI command to destroy an atomic value.
4852 Required arguments:
4853 valueName - The name of the value to destroy.
4854 returns:
4855 main.TRUE on success or
4856 main.ERROR on Error
4857 """
4858 try:
4859 valueName = str( valueName )
4860 cmdStr = "value-test "
4861 operation = "destroy"
4862 cmdStr += valueName + " " + operation
4863 output = self.distPrimitivesSend( cmdStr )
4864 if output is not None:
4865 return main.TRUE
4866 else:
4867 return main.ERROR
4868 except TypeError:
4869 main.log.exception( self.name + ": Object not as expected" )
4870 return main.ERROR
Jon Halle1a3b752015-07-22 13:02:46 -07004871 except Exception:
4872 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004873 main.cleanAndExit()
Jon Halle1a3b752015-07-22 13:02:46 -07004874
YPZhangfebf7302016-05-24 16:45:56 -07004875 def summary( self, jsonFormat=True, timeout=30 ):
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004876 """
4877 Description: Execute summary command in onos
4878 Returns: json object ( summary -j ), returns main.FALSE if there is
4879 no output
4880
4881 """
4882 try:
4883 cmdStr = "summary"
4884 if jsonFormat:
4885 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07004886 handle = self.sendline( cmdStr, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07004887 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004888 assert "Command not found:" not in handle, handle
Jon Hall6e709752016-02-01 13:38:46 -08004889 assert "Error:" not in handle, handle
Devin Lima7cfdbd2017-09-29 15:02:22 -07004890 assert "Error executing" not in handle, handle
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004891 if not handle:
4892 main.log.error( self.name + ": There is no output in " +
4893 "summary command" )
4894 return main.FALSE
4895 return handle
Jon Hallc6793552016-01-19 14:18:37 -08004896 except AssertionError:
Jon Hall6e709752016-02-01 13:38:46 -08004897 main.log.exception( "{} Error in summary output:".format( self.name ) )
Jon Hallc6793552016-01-19 14:18:37 -08004898 return None
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004899 except TypeError:
4900 main.log.exception( self.name + ": Object not as expected" )
4901 return None
4902 except pexpect.EOF:
4903 main.log.error( self.name + ": EOF exception found" )
4904 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004905 main.cleanAndExit()
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004906 except Exception:
4907 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004908 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004909
Jon Hall935db192016-04-19 00:22:04 -07004910 def transactionalMapGet( self, keyName ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004911 """
4912 CLI command to get the value of a key in a consistent map using
4913 transactions. This a test function and can only get keys from the
4914 test map hard coded into the cli command
4915 Required arguments:
4916 keyName - The name of the key to get
Jon Hall2a5002c2015-08-21 16:49:11 -07004917 returns:
4918 The string value of the key or
4919 None on Error
4920 """
4921 try:
4922 keyName = str( keyName )
4923 cmdStr = "transactional-map-test-get "
Jon Hall2a5002c2015-08-21 16:49:11 -07004924 cmdStr += keyName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004925 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07004926 pattern = "Key-value pair \(" + keyName + ", (?P<value>.+)\) found."
4927 if "Key " + keyName + " not found." in output:
Jon Hall9bfadd22016-05-11 14:48:07 -07004928 main.log.warn( output )
Jon Hall2a5002c2015-08-21 16:49:11 -07004929 return None
4930 else:
4931 match = re.search( pattern, output )
4932 if match:
4933 return match.groupdict()[ 'value' ]
4934 else:
4935 main.log.error( self.name + ": transactionlMapGet did not" +
4936 " match expected output." )
4937 main.log.debug( self.name + " expected: " + pattern )
4938 main.log.debug( self.name + " actual: " + repr( output ) )
4939 return None
4940 except TypeError:
4941 main.log.exception( self.name + ": Object not as expected" )
4942 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004943 except Exception:
4944 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004945 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004946
Jon Hall935db192016-04-19 00:22:04 -07004947 def transactionalMapPut( self, numKeys, value ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004948 """
4949 CLI command to put a value into 'numKeys' number of keys in a
4950 consistent map using transactions. This a test function and can only
4951 put into keys named 'Key#' of the test map hard coded into the cli command
4952 Required arguments:
4953 numKeys - Number of keys to add the value to
4954 value - The string value to put into the keys
Jon Hall2a5002c2015-08-21 16:49:11 -07004955 returns:
4956 A dictionary whose keys are the name of the keys put into the map
4957 and the values of the keys are dictionaries whose key-values are
4958 'value': value put into map and optionaly
4959 'oldValue': Previous value in the key or
4960 None on Error
4961
4962 Example output
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004963 { 'Key1': {'oldValue': 'oldTestValue', 'value': 'Testing'},
4964 'Key2': {'value': 'Testing'} }
Jon Hall2a5002c2015-08-21 16:49:11 -07004965 """
4966 try:
4967 numKeys = str( numKeys )
4968 value = str( value )
4969 cmdStr = "transactional-map-test-put "
Jon Hall2a5002c2015-08-21 16:49:11 -07004970 cmdStr += numKeys + " " + value
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004971 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07004972 newPattern = 'Created Key (?P<key>(\w)+) with value (?P<value>(.)+)\.'
4973 updatedPattern = "Put (?P<value>(.)+) into key (?P<key>(\w)+)\. The old value was (?P<oldValue>(.)+)\."
4974 results = {}
4975 for line in output.splitlines():
4976 new = re.search( newPattern, line )
4977 updated = re.search( updatedPattern, line )
4978 if new:
4979 results[ new.groupdict()[ 'key' ] ] = { 'value': new.groupdict()[ 'value' ] }
4980 elif updated:
4981 results[ updated.groupdict()[ 'key' ] ] = { 'value': updated.groupdict()[ 'value' ],
Jon Hallc6793552016-01-19 14:18:37 -08004982 'oldValue': updated.groupdict()[ 'oldValue' ] }
Jon Hall2a5002c2015-08-21 16:49:11 -07004983 else:
4984 main.log.error( self.name + ": transactionlMapGet did not" +
4985 " match expected output." )
Jon Hallc6793552016-01-19 14:18:37 -08004986 main.log.debug( "{} expected: {!r} or {!r}".format( self.name,
4987 newPattern,
4988 updatedPattern ) )
Jon Hall2a5002c2015-08-21 16:49:11 -07004989 main.log.debug( self.name + " actual: " + repr( output ) )
4990 return results
Jon Hall0e240372018-05-02 11:21:57 -07004991 except ( TypeError, AttributeError ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004992 main.log.exception( self.name + ": Object not as expected" )
4993 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07004994 except Exception:
4995 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004996 main.cleanAndExit()
Jon Hallc6793552016-01-19 14:18:37 -08004997
acsmarsdaea66c2015-09-03 11:44:06 -07004998 def maps( self, jsonFormat=True ):
4999 """
5000 Description: Returns result of onos:maps
5001 Optional:
5002 * jsonFormat: enable json formatting of output
5003 """
5004 try:
5005 cmdStr = "maps"
5006 if jsonFormat:
5007 cmdStr += " -j"
5008 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07005009 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005010 assert "Command not found:" not in handle, handle
acsmarsdaea66c2015-09-03 11:44:06 -07005011 return handle
Jon Hallc6793552016-01-19 14:18:37 -08005012 except AssertionError:
5013 main.log.exception( "" )
5014 return None
acsmarsdaea66c2015-09-03 11:44:06 -07005015 except TypeError:
5016 main.log.exception( self.name + ": Object not as expected" )
5017 return None
5018 except pexpect.EOF:
5019 main.log.error( self.name + ": EOF exception found" )
5020 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005021 main.cleanAndExit()
acsmarsdaea66c2015-09-03 11:44:06 -07005022 except Exception:
5023 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005024 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005025
5026 def getSwController( self, uri, jsonFormat=True ):
5027 """
5028 Descrition: Gets the controller information from the device
5029 """
5030 try:
5031 cmd = "device-controllers "
5032 if jsonFormat:
5033 cmd += "-j "
5034 response = self.sendline( cmd + uri )
Jon Halla495f562016-05-16 18:03:26 -07005035 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005036 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005037 return response
Jon Hallc6793552016-01-19 14:18:37 -08005038 except AssertionError:
5039 main.log.exception( "" )
5040 return None
GlennRC050596c2015-11-18 17:06:41 -08005041 except TypeError:
5042 main.log.exception( self.name + ": Object not as expected" )
5043 return None
5044 except pexpect.EOF:
5045 main.log.error( self.name + ": EOF exception found" )
5046 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005047 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005048 except Exception:
5049 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005050 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005051
5052 def setSwController( self, uri, ip, proto="tcp", port="6653", jsonFormat=True ):
5053 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005054 Descrition: sets the controller(s) for the specified device
GlennRC050596c2015-11-18 17:06:41 -08005055
5056 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005057 Required: uri - String: The uri of the device(switch).
GlennRC050596c2015-11-18 17:06:41 -08005058 ip - String or List: The ip address of the controller.
5059 This parameter can be formed in a couple of different ways.
5060 VALID:
5061 10.0.0.1 - just the ip address
5062 tcp:10.0.0.1 - the protocol and the ip address
5063 tcp:10.0.0.1:6653 - the protocol and port can be specified,
5064 so that you can add controllers with different
5065 protocols and ports
5066 INVALID:
5067 10.0.0.1:6653 - this is not supported by ONOS
5068
5069 Optional: proto - The type of connection e.g. tcp, ssl. If a list of ips are given
5070 port - The port number.
5071 jsonFormat - If set ONOS will output in json NOTE: This is currently not supported
5072
5073 Returns: main.TRUE if ONOS returns without any errors, otherwise returns main.FALSE
5074 """
5075 try:
5076 cmd = "device-setcontrollers"
5077
5078 if jsonFormat:
5079 cmd += " -j"
5080 cmd += " " + uri
5081 if isinstance( ip, str ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005082 ip = [ ip ]
GlennRC050596c2015-11-18 17:06:41 -08005083 for item in ip:
5084 if ":" in item:
5085 sitem = item.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005086 if len( sitem ) == 3:
GlennRC050596c2015-11-18 17:06:41 -08005087 cmd += " " + item
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005088 elif "." in sitem[ 1 ]:
5089 cmd += " {}:{}".format( item, port )
GlennRC050596c2015-11-18 17:06:41 -08005090 else:
5091 main.log.error( "Malformed entry: " + item )
5092 raise TypeError
5093 else:
5094 cmd += " {}:{}:{}".format( proto, item, port )
GlennRC050596c2015-11-18 17:06:41 -08005095 response = self.sendline( cmd )
Jon Halla495f562016-05-16 18:03:26 -07005096 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005097 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005098 if "Error" in response:
5099 main.log.error( response )
5100 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005101 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005102 except AssertionError:
5103 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005104 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005105 except TypeError:
5106 main.log.exception( self.name + ": Object not as expected" )
5107 return main.FALSE
5108 except pexpect.EOF:
5109 main.log.error( self.name + ": EOF exception found" )
5110 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005111 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005112 except Exception:
5113 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005114 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005115
5116 def removeDevice( self, device ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005117 '''
GlennRC20fc6522015-12-23 23:26:57 -08005118 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005119 Remove a device from ONOS by passing the uri of the device(s).
GlennRC20fc6522015-12-23 23:26:57 -08005120 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005121 device - (str or list) the id or uri of the device ex. "of:0000000000000001"
GlennRC20fc6522015-12-23 23:26:57 -08005122 Returns:
5123 Returns main.FALSE if an exception is thrown or an error is present
5124 in the response. Otherwise, returns main.TRUE.
5125 NOTE:
5126 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005127 '''
GlennRC20fc6522015-12-23 23:26:57 -08005128 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005129 if isinstance( device, str ):
You Wang823f5022016-08-18 15:24:41 -07005130 deviceStr = device
5131 device = []
5132 device.append( deviceStr )
GlennRC20fc6522015-12-23 23:26:57 -08005133
5134 for d in device:
5135 time.sleep( 1 )
5136 response = self.sendline( "device-remove {}".format( d ) )
Jon Halla495f562016-05-16 18:03:26 -07005137 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005138 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005139 if "Error" in response:
5140 main.log.warn( "Error for device: {}\nResponse: {}".format( d, response ) )
5141 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005142 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005143 except AssertionError:
5144 main.log.exception( "" )
5145 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005146 except TypeError:
5147 main.log.exception( self.name + ": Object not as expected" )
5148 return main.FALSE
5149 except pexpect.EOF:
5150 main.log.error( self.name + ": EOF exception found" )
5151 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005152 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005153 except Exception:
5154 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005155 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005156
5157 def removeHost( self, host ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005158 '''
GlennRC20fc6522015-12-23 23:26:57 -08005159 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005160 Remove a host from ONOS by passing the id of the host(s)
GlennRC20fc6522015-12-23 23:26:57 -08005161 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005162 hostId - (str or list) the id or mac of the host ex. "00:00:00:00:00:01"
GlennRC20fc6522015-12-23 23:26:57 -08005163 Returns:
5164 Returns main.FALSE if an exception is thrown or an error is present
5165 in the response. Otherwise, returns main.TRUE.
5166 NOTE:
5167 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005168 '''
GlennRC20fc6522015-12-23 23:26:57 -08005169 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005170 if isinstance( host, str ):
GlennRC20fc6522015-12-23 23:26:57 -08005171 host = list( host )
5172
5173 for h in host:
5174 time.sleep( 1 )
5175 response = self.sendline( "host-remove {}".format( h ) )
Jon Halla495f562016-05-16 18:03:26 -07005176 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005177 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005178 if "Error" in response:
5179 main.log.warn( "Error for host: {}\nResponse: {}".format( h, response ) )
5180 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005181 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005182 except AssertionError:
5183 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005184 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005185 except TypeError:
5186 main.log.exception( self.name + ": Object not as expected" )
5187 return main.FALSE
5188 except pexpect.EOF:
5189 main.log.error( self.name + ": EOF exception found" )
5190 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005191 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005192 except Exception:
5193 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005194 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005195
YPZhangfebf7302016-05-24 16:45:56 -07005196 def link( self, begin, end, state, timeout=30, showResponse=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005197 '''
GlennRCed771242016-01-13 17:02:47 -08005198 Description:
5199 Bring link down or up in the null-provider.
5200 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005201 begin - (string) One end of a device or switch.
5202 end - (string) the other end of the device or switch
GlennRCed771242016-01-13 17:02:47 -08005203 returns:
5204 main.TRUE if no exceptions were thrown and no Errors are
5205 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005206 '''
GlennRCed771242016-01-13 17:02:47 -08005207 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005208 cmd = "null-link null:{} null:{} {}".format( begin, end, state )
YPZhangfebf7302016-05-24 16:45:56 -07005209 response = self.sendline( cmd, showResponse=showResponse, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07005210 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005211 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08005212 if "Error" in response or "Failure" in response:
5213 main.log.error( response )
5214 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005215 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005216 except AssertionError:
5217 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005218 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005219 except TypeError:
5220 main.log.exception( self.name + ": Object not as expected" )
5221 return main.FALSE
5222 except pexpect.EOF:
5223 main.log.error( self.name + ": EOF exception found" )
5224 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005225 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005226 except Exception:
5227 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005228 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005229
Jon Hall2c8959e2016-12-16 12:17:34 -08005230 def portstate( self, dpid, port, state ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005231 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005232 Description:
5233 Changes the state of port in an OF switch by means of the
5234 PORTSTATUS OF messages.
5235 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005236 dpid - (string) Datapath ID of the device. Ex: 'of:0000000000000102'
5237 port - (string) target port in the device. Ex: '2'
5238 state - (string) target state (enable or disable)
Flavio Castro82ee2f62016-06-07 15:04:12 -07005239 returns:
5240 main.TRUE if no exceptions were thrown and no Errors are
5241 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005242 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005243 try:
Jon Hall2c8959e2016-12-16 12:17:34 -08005244 state = state.lower()
5245 assert state == 'enable' or state == 'disable', "Unknown state"
Jon Halle0f0b342017-04-18 11:43:47 -07005246 cmd = "portstate {} {} {}".format( dpid, port, state )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005247 response = self.sendline( cmd, showResponse=True )
5248 assert response is not None, "Error in sendline"
5249 assert "Command not found:" not in response, response
5250 if "Error" in response or "Failure" in response:
5251 main.log.error( response )
5252 return main.FALSE
5253 return main.TRUE
5254 except AssertionError:
5255 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005256 return main.FALSE
Flavio Castro82ee2f62016-06-07 15:04:12 -07005257 except TypeError:
5258 main.log.exception( self.name + ": Object not as expected" )
5259 return main.FALSE
5260 except pexpect.EOF:
5261 main.log.error( self.name + ": EOF exception found" )
5262 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005263 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005264 except Exception:
5265 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005266 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005267
5268 def logSet( self, level="INFO", app="org.onosproject" ):
5269 """
5270 Set the logging level to lvl for a specific app
5271 returns main.TRUE on success
5272 returns main.FALSE if Error occurred
5273 if noExit is True, TestON will not exit, but clean up
5274 Available level: DEBUG, TRACE, INFO, WARN, ERROR
5275 Level defaults to INFO
5276 """
5277 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005278 self.handle.sendline( "log:set %s %s" % ( level, app ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -08005279 self.handle.expect( self.karafPrompt )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005280
5281 response = self.handle.before
5282 if re.search( "Error", response ):
5283 return main.FALSE
5284 return main.TRUE
5285 except pexpect.TIMEOUT:
5286 main.log.exception( self.name + ": TIMEOUT exception found" )
Devin Lim44075962017-08-11 10:56:37 -07005287 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005288 except pexpect.EOF:
5289 main.log.error( self.name + ": EOF exception found" )
5290 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005291 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005292 except Exception:
5293 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005294 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07005295
5296 def getGraphDict( self, timeout=60, includeHost=False ):
5297 """
5298 Return a dictionary which describes the latest network topology data as a
5299 graph.
5300 An example of the dictionary:
5301 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
5302 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
5303 Each vertex should at least have an 'edges' attribute which describes the
5304 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005305 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07005306 list of attributes.
5307 An example of the edges dictionary:
5308 'edges': { vertex2: { 'port': ..., 'weight': ... },
5309 vertex3: { 'port': ..., 'weight': ... } }
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005310 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07005311 in topology data.
5312 """
5313 graphDict = {}
5314 try:
5315 links = self.links()
5316 links = json.loads( links )
5317 devices = self.devices()
5318 devices = json.loads( devices )
5319 idToDevice = {}
5320 for device in devices:
5321 idToDevice[ device[ 'id' ] ] = device
5322 if includeHost:
5323 hosts = self.hosts()
5324 # FIXME: support 'includeHost' argument
5325 for link in links:
5326 nodeA = link[ 'src' ][ 'device' ]
5327 nodeB = link[ 'dst' ][ 'device' ]
5328 assert idToDevice[ nodeA ][ 'available' ] and idToDevice[ nodeB ][ 'available' ]
Jon Halle0f0b342017-04-18 11:43:47 -07005329 if nodeA not in graphDict.keys():
5330 graphDict[ nodeA ] = { 'edges': {},
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005331 'dpid': idToDevice[ nodeA ][ 'id' ][ 3: ],
Jon Halle0f0b342017-04-18 11:43:47 -07005332 'type': idToDevice[ nodeA ][ 'type' ],
5333 'available': idToDevice[ nodeA ][ 'available' ],
5334 'role': idToDevice[ nodeA ][ 'role' ],
5335 'mfr': idToDevice[ nodeA ][ 'mfr' ],
5336 'hw': idToDevice[ nodeA ][ 'hw' ],
5337 'sw': idToDevice[ nodeA ][ 'sw' ],
5338 'serial': idToDevice[ nodeA ][ 'serial' ],
5339 'chassisId': idToDevice[ nodeA ][ 'chassisId' ],
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005340 'annotations': idToDevice[ nodeA ][ 'annotations' ]}
You Wangdb8cd0a2016-05-26 15:19:45 -07005341 else:
5342 # Assert nodeB is not connected to any current links of nodeA
You Wang7d14d642019-01-23 15:10:08 -08005343 # assert nodeB not in graphDict[ nodeA ][ 'edges' ].keys()
5344 pass
Jon Halle0f0b342017-04-18 11:43:47 -07005345 graphDict[ nodeA ][ 'edges' ][ nodeB ] = { 'port': link[ 'src' ][ 'port' ],
5346 'type': link[ 'type' ],
5347 'state': link[ 'state' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07005348 return graphDict
5349 except ( TypeError, ValueError ):
5350 main.log.exception( self.name + ": Object not as expected" )
5351 return None
5352 except KeyError:
5353 main.log.exception( self.name + ": KeyError exception found" )
5354 return None
5355 except AssertionError:
5356 main.log.exception( self.name + ": AssertionError exception found" )
5357 return None
5358 except pexpect.EOF:
5359 main.log.error( self.name + ": EOF exception found" )
5360 main.log.error( self.name + ": " + self.handle.before )
5361 return None
5362 except Exception:
5363 main.log.exception( self.name + ": Uncaught exception!" )
5364 return None
YPZhangcbc2a062016-07-11 10:55:44 -07005365
5366 def getIntentPerfSummary( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005367 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005368 Send command to check intent-perf summary
5369 Returns: dictionary for intent-perf summary
5370 if something wrong, function will return None
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005371 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005372 cmd = "intent-perf -s"
5373 respDic = {}
5374 resp = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08005375 assert resp is not None, "Error in sendline"
5376 assert "Command not found:" not in resp, resp
YPZhangcbc2a062016-07-11 10:55:44 -07005377 try:
5378 # Generate the dictionary to return
5379 for l in resp.split( "\n" ):
5380 # Delete any white space in line
5381 temp = re.sub( r'\s+', '', l )
5382 temp = temp.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005383 respDic[ temp[ 0 ] ] = temp[ 1 ]
YPZhangcbc2a062016-07-11 10:55:44 -07005384
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005385 except ( TypeError, ValueError ):
YPZhangcbc2a062016-07-11 10:55:44 -07005386 main.log.exception( self.name + ": Object not as expected" )
5387 return None
5388 except KeyError:
5389 main.log.exception( self.name + ": KeyError exception found" )
5390 return None
5391 except AssertionError:
5392 main.log.exception( self.name + ": AssertionError exception found" )
5393 return None
5394 except pexpect.EOF:
5395 main.log.error( self.name + ": EOF exception found" )
5396 main.log.error( self.name + ": " + self.handle.before )
5397 return None
5398 except Exception:
5399 main.log.exception( self.name + ": Uncaught exception!" )
5400 return None
5401 return respDic
5402
Chiyu Chengec63bde2016-11-17 18:11:36 -08005403 def logSearch( self, mode='all', searchTerm='', startLine='', logNum=1 ):
chengchiyu08303a02016-09-08 17:40:26 -07005404 """
5405 Searches the latest ONOS log file for the given search term and
5406 return a list that contains all the lines that have the search term.
YPZhangcbc2a062016-07-11 10:55:44 -07005407
chengchiyu08303a02016-09-08 17:40:26 -07005408 Arguments:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005409 searchTerm:
5410 The string to grep from the ONOS log.
5411 startLine:
5412 The term that decides which line is the start to search the searchTerm in
5413 the karaf log. For now, startTerm only works in 'first' mode.
5414 logNum:
5415 In some extreme cases, one karaf log is not big enough to contain all the
5416 information.Because of this, search mutiply logs is necessary to capture
5417 the right result. logNum is the number of karaf logs that we need to search
5418 the searchTerm.
chengchiyu08303a02016-09-08 17:40:26 -07005419 mode:
5420 all: return all the strings that contain the search term
5421 last: return the last string that contains the search term
5422 first: return the first string that contains the search term
Chiyu Chengec63bde2016-11-17 18:11:36 -08005423 num: return the number of times that the searchTerm appears in the log
5424 total: return how many lines in karaf log
chengchiyu08303a02016-09-08 17:40:26 -07005425 """
5426 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005427 assert isinstance( searchTerm, str )
Jon Halle0f0b342017-04-18 11:43:47 -07005428 # Build the log paths string
Chiyu Chengec63bde2016-11-17 18:11:36 -08005429 logPath = '/opt/onos/log/karaf.log.'
5430 logPaths = '/opt/onos/log/karaf.log'
5431 for i in range( 1, logNum ):
5432 logPaths = logPath + str( i ) + " " + logPaths
5433 cmd = "cat " + logPaths
You Wang6d301d42017-04-21 10:49:33 -07005434 if startLine:
Jon Halla478b852017-12-04 15:00:15 -08005435 # 100000000 is just a extreme large number to make sure this function can
5436 # grep all the lines after startLine
You Wang6d301d42017-04-21 10:49:33 -07005437 cmd = cmd + " | grep -A 100000000 \'" + startLine + "\'"
Chiyu Chengec63bde2016-11-17 18:11:36 -08005438 if mode == 'all':
5439 cmd = cmd + " | grep \'" + searchTerm + "\'"
You Wang6d301d42017-04-21 10:49:33 -07005440 elif mode == 'last':
Chiyu Chengec63bde2016-11-17 18:11:36 -08005441 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | tail -n 1"
You Wang6d301d42017-04-21 10:49:33 -07005442 elif mode == 'first':
5443 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | head -n 1"
5444 elif mode == 'num':
You Wangd91a70f2019-01-03 15:28:10 -08005445 cmd = cmd + " | grep \'" + searchTerm + "\' | wc -l"
5446 num = self.lineCount( cmd )
Chiyu Chengb8c2c842016-10-05 12:40:49 -07005447 return num
You Wang6d301d42017-04-21 10:49:33 -07005448 elif mode == 'total':
Jon Halld5a94fb2018-11-13 14:32:23 -08005449 totalLines = self.lineCount( "cat /opt/onos/log/karaf.log | wc -l" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005450 return int( totalLines )
You Wang6d301d42017-04-21 10:49:33 -07005451 else:
5452 main.log.error( self.name + " unsupported mode" )
5453 return main.ERROR
chengchiyu08303a02016-09-08 17:40:26 -07005454 before = self.sendline( cmd )
5455 before = before.splitlines()
5456 # make sure the returned list only contains the search term
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005457 returnLines = [ line for line in before if searchTerm in line ]
chengchiyu08303a02016-09-08 17:40:26 -07005458 return returnLines
5459 except AssertionError:
5460 main.log.error( self.name + " searchTerm is not string type" )
5461 return None
5462 except pexpect.EOF:
5463 main.log.error( self.name + ": EOF exception found" )
5464 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005465 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005466 except pexpect.TIMEOUT:
5467 main.log.error( self.name + ": TIMEOUT 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 Exception:
5471 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005472 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005473
5474 def vplsShow( self, jsonFormat=True ):
5475 """
5476 Description: Returns result of onos:vpls show, which should list the
5477 configured VPLS networks and the assigned interfaces.
5478 Optional:
5479 * jsonFormat: enable json formatting of output
5480 Returns:
5481 The output of the command or None on error.
5482 """
5483 try:
5484 cmdStr = "vpls show"
5485 if jsonFormat:
5486 raise NotImplementedError
5487 cmdStr += " -j"
5488 handle = self.sendline( cmdStr )
5489 assert handle is not None, "Error in sendline"
5490 assert "Command not found:" not in handle, handle
5491 return handle
5492 except AssertionError:
5493 main.log.exception( "" )
5494 return None
5495 except TypeError:
5496 main.log.exception( self.name + ": Object not as expected" )
5497 return None
5498 except pexpect.EOF:
5499 main.log.error( self.name + ": EOF exception found" )
5500 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005501 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005502 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005503 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005504 return None
5505 except Exception:
5506 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005507 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005508
5509 def parseVplsShow( self ):
5510 """
5511 Parse the cli output of 'vpls show' into json output. This is required
5512 as there is currently no json output available.
5513 """
5514 try:
5515 output = []
5516 raw = self.vplsShow( jsonFormat=False )
5517 namePat = "VPLS name: (?P<name>\w+)"
5518 interfacesPat = "Associated interfaces: \[(?P<interfaces>.*)\]"
5519 encapPat = "Encapsulation: (?P<encap>\w+)"
5520 pattern = "\s+".join( [ namePat, interfacesPat, encapPat ] )
5521 mIter = re.finditer( pattern, raw )
5522 for match in mIter:
5523 item = {}
5524 item[ 'name' ] = match.group( 'name' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005525 ifaces = match.group( 'interfaces' ).split( ', ' )
Jon Hall2c8959e2016-12-16 12:17:34 -08005526 if ifaces == [ "" ]:
5527 ifaces = []
5528 item[ 'interfaces' ] = ifaces
5529 encap = match.group( 'encap' )
5530 if encap != 'NONE':
5531 item[ 'encapsulation' ] = encap.lower()
5532 output.append( item )
5533 return output
5534 except Exception:
5535 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005536 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005537
5538 def vplsList( self, jsonFormat=True ):
5539 """
5540 Description: Returns result of onos:vpls list, which should list the
5541 configured VPLS networks.
5542 Optional:
5543 * jsonFormat: enable json formatting of output
5544 """
5545 try:
5546 cmdStr = "vpls list"
5547 if jsonFormat:
5548 raise NotImplementedError
5549 cmdStr += " -j"
5550 handle = self.sendline( cmdStr )
5551 assert handle is not None, "Error in sendline"
5552 assert "Command not found:" not in handle, handle
5553 return handle
5554 except AssertionError:
5555 main.log.exception( "" )
5556 return None
5557 except TypeError:
5558 main.log.exception( self.name + ": Object not as expected" )
5559 return None
5560 except pexpect.EOF:
5561 main.log.error( self.name + ": EOF exception found" )
5562 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005563 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005564 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005565 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005566 return None
5567 except Exception:
5568 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005569 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005570
5571 def vplsCreate( self, network ):
5572 """
5573 CLI command to create a new VPLS network.
5574 Required arguments:
5575 network - String name of the network to create.
5576 returns:
5577 main.TRUE on success and main.FALSE on failure
5578 """
5579 try:
5580 network = str( network )
5581 cmdStr = "vpls create "
5582 cmdStr += network
5583 output = self.sendline( cmdStr )
5584 assert output is not None, "Error in sendline"
5585 assert "Command not found:" not in output, output
5586 assert "Error executing command" not in output, output
5587 assert "VPLS already exists:" not in output, output
5588 return main.TRUE
5589 except AssertionError:
5590 main.log.exception( "" )
5591 return main.FALSE
5592 except TypeError:
5593 main.log.exception( self.name + ": Object not as expected" )
5594 return main.FALSE
5595 except pexpect.EOF:
5596 main.log.error( self.name + ": EOF exception found" )
5597 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005598 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005599 except Exception:
5600 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005601 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005602
5603 def vplsDelete( self, network ):
5604 """
5605 CLI command to delete a VPLS network.
5606 Required arguments:
5607 network - Name of the network to delete.
5608 returns:
5609 main.TRUE on success and main.FALSE on failure
5610 """
5611 try:
5612 network = str( network )
5613 cmdStr = "vpls delete "
5614 cmdStr += network
5615 output = self.sendline( cmdStr )
5616 assert output is not None, "Error in sendline"
5617 assert "Command not found:" not in output, output
5618 assert "Error executing command" not in output, output
5619 assert " not found" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005620 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005621 return main.TRUE
5622 except AssertionError:
5623 main.log.exception( "" )
5624 return main.FALSE
5625 except TypeError:
5626 main.log.exception( self.name + ": Object not as expected" )
5627 return main.FALSE
5628 except pexpect.EOF:
5629 main.log.error( self.name + ": EOF exception found" )
5630 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005631 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005632 except Exception:
5633 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005634 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005635
5636 def vplsAddIface( self, network, iface ):
5637 """
5638 CLI command to add an interface to a VPLS network.
5639 Required arguments:
5640 network - Name of the network to add the interface to.
5641 iface - The ONOS name for an interface.
5642 returns:
5643 main.TRUE on success and main.FALSE on failure
5644 """
5645 try:
5646 network = str( network )
5647 iface = str( iface )
5648 cmdStr = "vpls add-if "
5649 cmdStr += network + " " + iface
5650 output = self.sendline( cmdStr )
5651 assert output is not None, "Error in sendline"
5652 assert "Command not found:" not in output, output
5653 assert "Error executing command" not in output, output
5654 assert "already associated to network" not in output, output
5655 assert "Interface cannot be added." not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005656 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005657 return main.TRUE
5658 except AssertionError:
5659 main.log.exception( "" )
5660 return main.FALSE
5661 except TypeError:
5662 main.log.exception( self.name + ": Object not as expected" )
5663 return main.FALSE
5664 except pexpect.EOF:
5665 main.log.error( self.name + ": EOF exception found" )
5666 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005667 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005668 except Exception:
5669 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005670 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005671
5672 def vplsRemIface( self, network, iface ):
5673 """
5674 CLI command to remove an interface from a VPLS network.
5675 Required arguments:
5676 network - Name of the network to remove the interface from.
5677 iface - Name of the interface to remove.
5678 returns:
5679 main.TRUE on success and main.FALSE on failure
5680 """
5681 try:
5682 iface = str( iface )
5683 cmdStr = "vpls rem-if "
5684 cmdStr += network + " " + iface
5685 output = self.sendline( cmdStr )
5686 assert output is not None, "Error in sendline"
5687 assert "Command not found:" not in output, output
5688 assert "Error executing command" not in output, output
5689 assert "is not configured" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005690 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005691 return main.TRUE
5692 except AssertionError:
5693 main.log.exception( "" )
5694 return main.FALSE
5695 except TypeError:
5696 main.log.exception( self.name + ": Object not as expected" )
5697 return main.FALSE
5698 except pexpect.EOF:
5699 main.log.error( self.name + ": EOF exception found" )
5700 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005701 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005702 except Exception:
5703 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005704 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005705
5706 def vplsClean( self ):
5707 """
5708 Description: Clears the VPLS app configuration.
5709 Returns: main.TRUE on success and main.FALSE on failure
5710 """
5711 try:
5712 cmdStr = "vpls clean"
5713 handle = self.sendline( cmdStr )
5714 assert handle is not None, "Error in sendline"
5715 assert "Command not found:" not in handle, handle
Jon Hallcf97cf12017-06-06 09:37:51 -07005716 assert "still updating" not in handle, handle
Jon Hall2c8959e2016-12-16 12:17:34 -08005717 return handle
5718 except AssertionError:
5719 main.log.exception( "" )
5720 return main.FALSE
5721 except TypeError:
5722 main.log.exception( self.name + ": Object not as expected" )
5723 return main.FALSE
5724 except pexpect.EOF:
5725 main.log.error( self.name + ": EOF exception found" )
5726 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005727 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005728 except Exception:
5729 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005730 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005731
5732 def vplsSetEncap( self, network, encapType ):
5733 """
5734 CLI command to add an interface to a VPLS network.
5735 Required arguments:
5736 network - Name of the network to create.
5737 encapType - Type of encapsulation.
5738 returns:
5739 main.TRUE on success and main.FALSE on failure
5740 """
5741 try:
5742 network = str( network )
5743 encapType = str( encapType ).upper()
5744 assert encapType in [ "MPLS", "VLAN", "NONE" ], "Incorrect type"
5745 cmdStr = "vpls set-encap "
5746 cmdStr += network + " " + encapType
5747 output = self.sendline( cmdStr )
5748 assert output is not None, "Error in sendline"
5749 assert "Command not found:" not in output, output
5750 assert "Error executing command" not in output, output
5751 assert "already associated to network" not in output, output
5752 assert "Encapsulation type " not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005753 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005754 return main.TRUE
5755 except AssertionError:
5756 main.log.exception( "" )
5757 return main.FALSE
5758 except TypeError:
5759 main.log.exception( self.name + ": Object not as expected" )
5760 return main.FALSE
5761 except pexpect.EOF:
5762 main.log.error( self.name + ": EOF exception found" )
5763 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005764 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005765 except Exception:
5766 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005767 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005768
5769 def interfaces( self, jsonFormat=True ):
5770 """
5771 Description: Returns result of interfaces command.
5772 Optional:
5773 * jsonFormat: enable json formatting of output
5774 Returns:
5775 The output of the command or None on error.
5776 """
5777 try:
5778 cmdStr = "interfaces"
5779 if jsonFormat:
Jon Halle0f0b342017-04-18 11:43:47 -07005780 raise NotImplementedError
Jon Hall2c8959e2016-12-16 12:17:34 -08005781 cmdStr += " -j"
5782 handle = self.sendline( cmdStr )
5783 assert handle is not None, "Error in sendline"
5784 assert "Command not found:" not in handle, handle
5785 return handle
5786 except AssertionError:
5787 main.log.exception( "" )
5788 return None
5789 except TypeError:
5790 main.log.exception( self.name + ": Object not as expected" )
5791 return None
5792 except pexpect.EOF:
5793 main.log.error( self.name + ": EOF exception found" )
5794 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005795 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005796 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005797 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005798 return None
5799 except Exception:
5800 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005801 main.cleanAndExit()
Chiyu Chengec63bde2016-11-17 18:11:36 -08005802
5803 def getTimeStampFromLog( self, mode, searchTerm, splitTerm_before, splitTerm_after, startLine='', logNum=1 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005804 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005805 Get the timestamp of searchTerm from karaf log.
5806
5807 Arguments:
5808 splitTerm_before and splitTerm_after:
5809
5810 The terms that split the string that contains the timeStamp of
5811 searchTerm. For example, if that string is "xxxxxxxcreationTime =
5812 1419510501xxxxxx", then the splitTerm_before is "CreationTime = "
5813 and the splitTerm_after is "x"
5814
5815 others:
Jon Halle0f0b342017-04-18 11:43:47 -07005816 Please look at the "logsearch" Function in onosclidriver.py
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005817 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005818 if logNum < 0:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005819 main.log.error( "Get wrong log number ")
Chiyu Chengec63bde2016-11-17 18:11:36 -08005820 return main.ERROR
5821 lines = self.logSearch( mode=mode, searchTerm=searchTerm, startLine=startLine, logNum=logNum )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005822 if len( lines ) == 0:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005823 main.log.warn( "Captured timestamp string is empty" )
5824 return main.ERROR
5825 lines = lines[ 0 ]
5826 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005827 assert isinstance( lines, str )
Chiyu Chengec63bde2016-11-17 18:11:36 -08005828 # get the target value
5829 line = lines.split( splitTerm_before )
5830 key = line[ 1 ].split( splitTerm_after )
5831 return int( key[ 0 ] )
5832 except IndexError:
5833 main.log.warn( "Index Error!" )
5834 return main.ERROR
5835 except AssertionError:
5836 main.log.warn( "Search Term Not Found " )
5837 return main.ERROR
Jon Halle0f0b342017-04-18 11:43:47 -07005838
5839 def workQueueAdd( self, queueName, value ):
5840 """
5841 CLI command to add a string to the specified Work Queue.
5842 This function uses the distributed primitives test app, which
5843 gives some cli access to distributed primitives for testing
5844 purposes only.
5845
5846 Required arguments:
5847 queueName - The name of the queue to add to
5848 value - The value to add to the queue
5849 returns:
5850 main.TRUE on success, main.FALSE on failure and
5851 main.ERROR on error.
5852 """
5853 try:
5854 queueName = str( queueName )
5855 value = str( value )
5856 prefix = "work-queue-test"
5857 operation = "add"
5858 cmdStr = " ".join( [ prefix, queueName, operation, value ] )
5859 output = self.distPrimitivesSend( cmdStr )
5860 if "Invalid operation name" in output:
5861 main.log.warn( output )
5862 return main.ERROR
5863 elif "Done" in output:
5864 return main.TRUE
5865 except TypeError:
5866 main.log.exception( self.name + ": Object not as expected" )
5867 return main.ERROR
5868 except Exception:
5869 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005870 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005871
5872 def workQueueAddMultiple( self, queueName, value1, value2 ):
5873 """
5874 CLI command to add two strings to the specified Work Queue.
5875 This function uses the distributed primitives test app, which
5876 gives some cli access to distributed primitives for testing
5877 purposes only.
5878
5879 Required arguments:
5880 queueName - The name of the queue to add to
5881 value1 - The first value to add to the queue
5882 value2 - The second value to add to the queue
5883 returns:
5884 main.TRUE on success, main.FALSE on failure and
5885 main.ERROR on error.
5886 """
5887 try:
5888 queueName = str( queueName )
5889 value1 = str( value1 )
5890 value2 = str( value2 )
5891 prefix = "work-queue-test"
5892 operation = "addMultiple"
5893 cmdStr = " ".join( [ prefix, queueName, operation, value1, value2 ] )
5894 output = self.distPrimitivesSend( cmdStr )
5895 if "Invalid operation name" in output:
5896 main.log.warn( output )
5897 return main.ERROR
5898 elif "Done" in output:
5899 return main.TRUE
5900 except TypeError:
5901 main.log.exception( self.name + ": Object not as expected" )
5902 return main.ERROR
5903 except Exception:
5904 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005905 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005906
5907 def workQueueTakeAndComplete( self, queueName, number=1 ):
5908 """
5909 CLI command to take a value from the specified Work Queue and compelte it.
5910 This function uses the distributed primitives test app, which
5911 gives some cli access to distributed primitives for testing
5912 purposes only.
5913
5914 Required arguments:
5915 queueName - The name of the queue to add to
5916 number - The number of items to take and complete
5917 returns:
5918 main.TRUE on success, main.FALSE on failure and
5919 main.ERROR on error.
5920 """
5921 try:
5922 queueName = str( queueName )
5923 number = str( int( number ) )
5924 prefix = "work-queue-test"
5925 operation = "takeAndComplete"
5926 cmdStr = " ".join( [ prefix, queueName, operation, number ] )
5927 output = self.distPrimitivesSend( cmdStr )
5928 if "Invalid operation name" in output:
5929 main.log.warn( output )
5930 return main.ERROR
5931 elif "Done" in output:
5932 return main.TRUE
5933 except TypeError:
5934 main.log.exception( self.name + ": Object not as expected" )
5935 return main.ERROR
5936 except Exception:
5937 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005938 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005939
5940 def workQueueDestroy( self, queueName ):
5941 """
5942 CLI command to destroy the specified Work Queue.
5943 This function uses the distributed primitives test app, which
5944 gives some cli access to distributed primitives for testing
5945 purposes only.
5946
5947 Required arguments:
5948 queueName - The name of the queue to add to
5949 returns:
5950 main.TRUE on success, main.FALSE on failure and
5951 main.ERROR on error.
5952 """
5953 try:
5954 queueName = str( queueName )
5955 prefix = "work-queue-test"
5956 operation = "destroy"
5957 cmdStr = " ".join( [ prefix, queueName, operation ] )
5958 output = self.distPrimitivesSend( cmdStr )
5959 if "Invalid operation name" in output:
5960 main.log.warn( output )
5961 return main.ERROR
5962 return main.TRUE
5963 except TypeError:
5964 main.log.exception( self.name + ": Object not as expected" )
5965 return main.ERROR
5966 except Exception:
5967 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005968 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005969
5970 def workQueueTotalPending( self, queueName ):
5971 """
5972 CLI command to get the Total Pending items of the specified Work Queue.
5973 This function uses the distributed primitives test app, which
5974 gives some cli access to distributed primitives for testing
5975 purposes only.
5976
5977 Required arguments:
5978 queueName - The name of the queue to add to
5979 returns:
5980 The number of Pending items in the specified work queue or
5981 None on error
5982 """
5983 try:
5984 queueName = str( queueName )
5985 prefix = "work-queue-test"
5986 operation = "totalPending"
5987 cmdStr = " ".join( [ prefix, queueName, operation ] )
5988 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08005989 main.log.debug( self.name + ": work queue unparsed: " + output )
5990 output = output.split( "\r\n" )[ -1 ]
5991 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07005992 pattern = r'\d+'
5993 if "Invalid operation name" in output:
5994 main.log.warn( output )
5995 return None
5996 else:
5997 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005998 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07005999 except ( AttributeError, TypeError ):
6000 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6001 return None
6002 except Exception:
6003 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006004 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006005
6006 def workQueueTotalCompleted( self, queueName ):
6007 """
6008 CLI command to get the Total Completed items of the specified Work Queue.
6009 This function uses the distributed primitives test app, which
6010 gives some cli access to distributed primitives for testing
6011 purposes only.
6012
6013 Required arguments:
6014 queueName - The name of the queue to add to
6015 returns:
6016 The number of complete items in the specified work queue or
6017 None on error
6018 """
6019 try:
6020 queueName = str( queueName )
6021 prefix = "work-queue-test"
6022 operation = "totalCompleted"
6023 cmdStr = " ".join( [ prefix, queueName, operation ] )
6024 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006025 main.log.debug( self.name + ": work queue unparsed: " + output )
6026 output = output.split( "\r\n" )[ -1 ]
6027 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006028 pattern = r'\d+'
6029 if "Invalid operation name" in output:
6030 main.log.warn( output )
6031 return None
6032 else:
6033 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006034 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006035 except ( AttributeError, TypeError ):
6036 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6037 return None
6038 except Exception:
6039 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006040 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006041
6042 def workQueueTotalInProgress( self, queueName ):
6043 """
6044 CLI command to get the Total In Progress items of the specified Work Queue.
6045 This function uses the distributed primitives test app, which
6046 gives some cli access to distributed primitives for testing
6047 purposes only.
6048
6049 Required arguments:
6050 queueName - The name of the queue to add to
6051 returns:
6052 The number of In Progress items in the specified work queue or
6053 None on error
6054 """
6055 try:
6056 queueName = str( queueName )
6057 prefix = "work-queue-test"
6058 operation = "totalInProgress"
6059 cmdStr = " ".join( [ prefix, queueName, operation ] )
6060 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006061 main.log.debug( self.name + ": work queue unparsed: " + output )
6062 output = output.split( "\r\n" )[ -1 ]
6063 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006064 pattern = r'\d+'
6065 if "Invalid operation name" in output:
6066 main.log.warn( output )
6067 return None
6068 else:
6069 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006070 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006071 except ( AttributeError, TypeError ):
6072 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6073 return None
6074 except Exception:
6075 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006076 main.cleanAndExit()
Jeremy Ronquillo818bc7c2017-08-09 17:14:53 +00006077
6078 def events( self, args='-a' ):
6079 """
6080 Description: Returns events -a command output
6081 Optional:
6082 add other arguments
6083 """
6084 try:
6085 cmdStr = "events"
6086 if args:
6087 cmdStr += " " + args
6088 handle = self.sendline( cmdStr )
6089 assert handle is not None, "Error in sendline"
6090 assert "Command not found:" not in handle, handle
6091 return handle
6092 except AssertionError:
6093 main.log.exception( "" )
6094 return None
6095 except TypeError:
6096 main.log.exception( self.name + ": Object not as expected" )
6097 return None
6098 except pexpect.EOF:
6099 main.log.error( self.name + ": EOF exception found" )
6100 main.log.error( self.name + ": " + self.handle.before )
6101 main.cleanAndExit()
6102 except Exception:
6103 main.log.exception( self.name + ": Uncaught exception!" )
6104 main.cleanAndExit()
6105
6106 def getMaster( self, deviceID ):
6107 """
6108 Description: Obtains current master using "roles" command for a specific deviceID
6109 """
6110 try:
6111 return str( self.getRole( deviceID )[ 'master' ] )
6112 except AssertionError:
6113 main.log.exception( "" )
6114 return None
6115 except TypeError:
6116 main.log.exception( self.name + ": Object not as expected" )
6117 return None
6118 except pexpect.EOF:
6119 main.log.error( self.name + ": EOF exception found" )
6120 main.log.error( self.name + ": " + self.handle.before )
6121 main.cleanAndExit()
6122 except Exception:
6123 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lime6fe3c42017-10-18 16:28:40 -07006124 main.cleanAndExit()
Jon Halla478b852017-12-04 15:00:15 -08006125
6126 def issu( self ):
6127 """
6128 Short summary of In-Service Software Upgrade status
6129
6130 Returns the output of the cli command or None on Error
6131 """
6132 try:
6133 cmdStr = "issu"
6134 handle = self.sendline( cmdStr )
6135 assert handle is not None, "Error in sendline"
6136 assert "Command not found:" not in handle, handle
6137 assert "Unsupported command:" not in handle, handle
6138 return handle
6139 except AssertionError:
6140 main.log.exception( "" )
6141 return None
6142 except TypeError:
6143 main.log.exception( self.name + ": Object not as expected" )
6144 return None
6145 except pexpect.EOF:
6146 main.log.error( self.name + ": EOF exception found" )
6147 main.log.error( self.name + ": " + self.handle.before )
6148 main.cleanAndExit()
6149 except Exception:
6150 main.log.exception( self.name + ": Uncaught exception!" )
6151 main.cleanAndExit()
6152
6153 def issuInit( self ):
6154 """
6155 Initiates an In-Service Software Upgrade
6156
6157 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6158 """
6159 try:
6160 cmdStr = "issu init"
6161 handle = self.sendline( cmdStr )
6162 assert handle is not None, "Error in sendline"
6163 assert "Command not found:" not in handle, handle
6164 assert "Unsupported command:" not in handle, handle
6165 if "Initialized" in handle:
6166 return main.TRUE
6167 else:
6168 return main.FALSE
6169 except AssertionError:
6170 main.log.exception( "" )
6171 return main.ERROR
6172 except TypeError:
6173 main.log.exception( self.name + ": Object not as expected" )
6174 return main.ERROR
6175 except pexpect.EOF:
6176 main.log.error( self.name + ": EOF exception found" )
6177 main.log.error( self.name + ": " + self.handle.before )
6178 main.cleanAndExit()
6179 except Exception:
6180 main.log.exception( self.name + ": Uncaught exception!" )
6181 main.cleanAndExit()
6182
6183 def issuUpgrade( self ):
6184 """
6185 Transitions stores to upgraded nodes
6186
6187 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6188 """
6189 try:
6190 cmdStr = "issu upgrade"
6191 handle = self.sendline( cmdStr )
6192 assert handle is not None, "Error in sendline"
6193 assert "Command not found:" not in handle, handle
6194 assert "Unsupported command:" not in handle, handle
6195 if "Upgraded" in handle:
6196 return main.TRUE
6197 else:
6198 return main.FALSE
6199 except AssertionError:
6200 main.log.exception( "" )
6201 return main.ERROR
6202 except TypeError:
6203 main.log.exception( self.name + ": Object not as expected" )
6204 return main.ERROR
6205 except pexpect.EOF:
6206 main.log.error( self.name + ": EOF exception found" )
6207 main.log.error( self.name + ": " + self.handle.before )
6208 main.cleanAndExit()
6209 except Exception:
6210 main.log.exception( self.name + ": Uncaught exception!" )
6211 main.cleanAndExit()
6212
6213 def issuCommit( self ):
6214 """
6215 Finalizes an In-Service Software Upgrade
6216
6217 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6218 """
6219 try:
6220 cmdStr = "issu commit"
6221 handle = self.sendline( cmdStr )
6222 assert handle is not None, "Error in sendline"
6223 assert "Command not found:" not in handle, handle
6224 assert "Unsupported command:" not in handle, handle
6225 # TODO: Check the version returned by this command
6226 if "Committed version" in handle:
6227 return main.TRUE
6228 else:
6229 return main.FALSE
6230 except AssertionError:
6231 main.log.exception( "" )
6232 return main.ERROR
6233 except TypeError:
6234 main.log.exception( self.name + ": Object not as expected" )
6235 return main.ERROR
6236 except pexpect.EOF:
6237 main.log.error( self.name + ": EOF exception found" )
6238 main.log.error( self.name + ": " + self.handle.before )
6239 main.cleanAndExit()
6240 except Exception:
6241 main.log.exception( self.name + ": Uncaught exception!" )
6242 main.cleanAndExit()
6243
6244 def issuRollback( self ):
6245 """
6246 Rolls back an In-Service Software Upgrade
6247
6248 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6249 """
6250 try:
6251 cmdStr = "issu rollback"
6252 handle = self.sendline( cmdStr )
6253 assert handle is not None, "Error in sendline"
6254 assert "Command not found:" not in handle, handle
6255 assert "Unsupported command:" not in handle, handle
6256 # TODO: Check the version returned by this command
6257 if "Rolled back to version" in handle:
6258 return main.TRUE
6259 else:
6260 return main.FALSE
6261 except AssertionError:
6262 main.log.exception( "" )
6263 return main.ERROR
6264 except TypeError:
6265 main.log.exception( self.name + ": Object not as expected" )
6266 return main.ERROR
6267 except pexpect.EOF:
6268 main.log.error( self.name + ": EOF exception found" )
6269 main.log.error( self.name + ": " + self.handle.before )
6270 main.cleanAndExit()
6271 except Exception:
6272 main.log.exception( self.name + ": Uncaught exception!" )
6273 main.cleanAndExit()
6274
6275 def issuReset( self ):
6276 """
6277 Resets the In-Service Software Upgrade status after a rollback
6278
6279 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6280 """
6281 try:
6282 cmdStr = "issu reset"
6283 handle = self.sendline( cmdStr )
6284 assert handle is not None, "Error in sendline"
6285 assert "Command not found:" not in handle, handle
6286 assert "Unsupported command:" not in handle, handle
6287 # TODO: Check the version returned by this command
6288 if "Reset version" in handle:
6289 return main.TRUE
6290 else:
6291 return main.FALSE
6292 except AssertionError:
6293 main.log.exception( "" )
6294 return main.ERROR
6295 except TypeError:
6296 main.log.exception( self.name + ": Object not as expected" )
6297 return main.ERROR
6298 except pexpect.EOF:
6299 main.log.error( self.name + ": EOF exception found" )
6300 main.log.error( self.name + ": " + self.handle.before )
6301 main.cleanAndExit()
6302 except Exception:
6303 main.log.exception( self.name + ": Uncaught exception!" )
6304 main.cleanAndExit()
6305
6306 def issuStatus( self ):
6307 """
6308 Status of an In-Service Software Upgrade
6309
6310 Returns the output of the cli command or None on Error
6311 """
6312 try:
6313 cmdStr = "issu status"
6314 handle = self.sendline( cmdStr )
6315 assert handle is not None, "Error in sendline"
6316 assert "Command not found:" not in handle, handle
6317 assert "Unsupported command:" not in handle, handle
6318 return handle
6319 except AssertionError:
6320 main.log.exception( "" )
6321 return None
6322 except TypeError:
6323 main.log.exception( self.name + ": Object not as expected" )
6324 return None
6325 except pexpect.EOF:
6326 main.log.error( self.name + ": EOF exception found" )
6327 main.log.error( self.name + ": " + self.handle.before )
6328 main.cleanAndExit()
6329 except Exception:
6330 main.log.exception( self.name + ": Uncaught exception!" )
6331 main.cleanAndExit()
6332
6333 def issuVersion( self ):
6334 """
6335 Get the version of an In-Service Software Upgrade
6336
6337 Returns the output of the cli command or None on Error
6338 """
6339 try:
6340 cmdStr = "issu version"
6341 handle = self.sendline( cmdStr )
6342 assert handle is not None, "Error in sendline"
6343 assert "Command not found:" not in handle, handle
6344 assert "Unsupported command:" not in handle, handle
6345 return handle
6346 except AssertionError:
6347 main.log.exception( "" )
6348 return None
6349 except TypeError:
6350 main.log.exception( self.name + ": Object not as expected" )
6351 return None
6352 except pexpect.EOF:
6353 main.log.error( self.name + ": EOF exception found" )
6354 main.log.error( self.name + ": " + self.handle.before )
6355 main.cleanAndExit()
6356 except Exception:
6357 main.log.exception( self.name + ": Uncaught exception!" )
6358 main.cleanAndExit()
You Wange24d6272018-03-27 21:18:50 -07006359
6360 def mcastJoin( self, sIP, groupIP, sPort, dPorts ):
6361 """
6362 Create a multicast route by calling 'mcast-join' command
6363 sIP: source IP of the multicast route
6364 groupIP: group IP of the multicast route
6365 sPort: source port (e.g. of:0000000000000001/3 ) of the multicast route
6366 dPorts: a list of destination ports of the multicast route
6367 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6368 """
6369 try:
6370 cmdStr = "mcast-join"
6371 cmdStr += " " + str( sIP )
6372 cmdStr += " " + str( groupIP )
6373 cmdStr += " " + str( sPort )
6374 assert isinstance( dPorts, list )
6375 for dPort in dPorts:
6376 cmdStr += " " + str( dPort )
6377 handle = self.sendline( cmdStr )
6378 assert handle is not None, "Error in sendline"
6379 assert "Command not found:" not in handle, handle
6380 assert "Unsupported command:" not in handle, handle
6381 assert "Error executing command" not in handle, handle
6382 if "Added the mcast route" in handle:
6383 return main.TRUE
6384 else:
6385 return main.FALSE
6386 except AssertionError:
6387 main.log.exception( "" )
6388 return None
6389 except TypeError:
6390 main.log.exception( self.name + ": Object not as expected" )
6391 return None
6392 except pexpect.EOF:
6393 main.log.error( self.name + ": EOF exception found" )
6394 main.log.error( self.name + ": " + self.handle.before )
6395 main.cleanAndExit()
6396 except Exception:
6397 main.log.exception( self.name + ": Uncaught exception!" )
6398 main.cleanAndExit()
6399
6400 def mcastDelete( self, sIP, groupIP, dPorts ):
6401 """
6402 Delete a multicast route by calling 'mcast-delete' command
6403 sIP: source IP of the multicast route
6404 groupIP: group IP of the multicast route
6405 dPorts: a list of destination ports of the multicast route
6406 Returns main.TRUE if mcast route is deleted; Otherwise main.FALSE
6407 """
6408 try:
6409 cmdStr = "mcast-delete"
6410 cmdStr += " " + str( sIP )
6411 cmdStr += " " + str( groupIP )
6412 assert isinstance( dPorts, list )
6413 for dPort in dPorts:
6414 cmdStr += " " + str( dPort )
6415 handle = self.sendline( cmdStr )
6416 assert handle is not None, "Error in sendline"
6417 assert "Command not found:" not in handle, handle
6418 assert "Unsupported command:" not in handle, handle
6419 assert "Error executing command" not in handle, handle
6420 if "Updated the mcast route" in handle:
6421 return main.TRUE
6422 else:
6423 return main.FALSE
6424 except AssertionError:
6425 main.log.exception( "" )
6426 return None
6427 except TypeError:
6428 main.log.exception( self.name + ": Object not as expected" )
6429 return None
6430 except pexpect.EOF:
6431 main.log.error( self.name + ": EOF exception found" )
6432 main.log.error( self.name + ": " + self.handle.before )
6433 main.cleanAndExit()
6434 except Exception:
6435 main.log.exception( self.name + ": Uncaught exception!" )
6436 main.cleanAndExit()
6437
6438 def mcastHostJoin( self, sAddr, gAddr, srcs, sinks ):
6439 """
6440 Create a multicast route by calling 'mcast-host-join' command
6441 sAddr: we can provide * for ASM or a specific address for SSM
6442 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006443 srcs: a list of HostId of the sources e.g. ["00:AA:00:00:00:01/None"]
You Wange24d6272018-03-27 21:18:50 -07006444 sinks: a list of HostId of the sinks e.g. ["00:AA:00:00:01:05/40"]
6445 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6446 """
6447 try:
6448 cmdStr = "mcast-host-join"
6449 cmdStr += " -sAddr " + str( sAddr )
6450 cmdStr += " -gAddr " + str( gAddr )
6451 assert isinstance( srcs, list )
6452 for src in srcs:
6453 cmdStr += " -srcs " + str( src )
6454 assert isinstance( sinks, list )
6455 for sink in sinks:
6456 cmdStr += " -sinks " + str( sink )
6457 handle = self.sendline( cmdStr )
6458 assert handle is not None, "Error in sendline"
6459 assert "Command not found:" not in handle, handle
6460 assert "Unsupported command:" not in handle, handle
6461 assert "Error executing command" not in handle, handle
6462 if "Added the mcast route" in handle:
6463 return main.TRUE
6464 else:
6465 return main.FALSE
6466 except AssertionError:
6467 main.log.exception( "" )
6468 return None
6469 except TypeError:
6470 main.log.exception( self.name + ": Object not as expected" )
6471 return None
6472 except pexpect.EOF:
6473 main.log.error( self.name + ": EOF exception found" )
6474 main.log.error( self.name + ": " + self.handle.before )
6475 main.cleanAndExit()
6476 except Exception:
6477 main.log.exception( self.name + ": Uncaught exception!" )
6478 main.cleanAndExit()
6479
6480 def mcastHostDelete( self, sAddr, gAddr, host=None ):
6481 """
6482 Delete multicast sink(s) by calling 'mcast-host-delete' command
6483 sAddr: we can provide * for ASM or a specific address for SSM
6484 gAddr: specifies multicast group address
You Wangc02d8352018-04-17 16:42:10 -07006485 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
You Wange24d6272018-03-27 21:18:50 -07006486 will delete the route if not specified
6487 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6488 """
6489 try:
6490 cmdStr = "mcast-host-delete"
6491 cmdStr += " -sAddr " + str( sAddr )
6492 cmdStr += " -gAddr " + str( gAddr )
6493 if host:
6494 cmdStr += " -h " + str( host )
6495 handle = self.sendline( cmdStr )
6496 assert handle is not None, "Error in sendline"
6497 assert "Command not found:" not in handle, handle
6498 assert "Unsupported command:" not in handle, handle
6499 assert "Error executing command" not in handle, handle
6500 if "Updated the mcast route" in handle:
6501 return main.TRUE
6502 elif "Deleted the mcast route" in handle:
6503 return main.TRUE
6504 else:
6505 return main.FALSE
6506 except AssertionError:
6507 main.log.exception( "" )
6508 return None
6509 except TypeError:
6510 main.log.exception( self.name + ": Object not as expected" )
6511 return None
6512 except pexpect.EOF:
6513 main.log.error( self.name + ": EOF exception found" )
6514 main.log.error( self.name + ": " + self.handle.before )
6515 main.cleanAndExit()
6516 except Exception:
6517 main.log.exception( self.name + ": Uncaught exception!" )
6518 main.cleanAndExit()
6519
You Wang547893e2018-05-08 13:34:59 -07006520 def mcastSinkDelete( self, sAddr, gAddr, sink=None ):
6521 """
6522 Delete multicast sink(s) by calling 'mcast-sink-delete' command
6523 sAddr: we can provide * for ASM or a specific address for SSM
6524 gAddr: specifies multicast group address
6525 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
6526 will delete the route if not specified
6527 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6528 """
6529 try:
6530 cmdStr = "mcast-sink-delete"
6531 cmdStr += " -sAddr " + str( sAddr )
6532 cmdStr += " -gAddr " + str( gAddr )
6533 if sink:
6534 cmdStr += " -s " + str( sink )
6535 handle = self.sendline( cmdStr )
6536 assert handle is not None, "Error in sendline"
6537 assert "Command not found:" not in handle, handle
6538 assert "Unsupported command:" not in handle, handle
6539 assert "Error executing command" not in handle, handle
6540 if "Updated the mcast route" in handle:
6541 return main.TRUE
6542 elif "Deleted the mcast route" in handle:
6543 return main.TRUE
6544 else:
6545 return main.FALSE
6546 except AssertionError:
6547 main.log.exception( "" )
6548 return None
6549 except TypeError:
6550 main.log.exception( self.name + ": Object not as expected" )
6551 return None
6552 except pexpect.EOF:
6553 main.log.error( self.name + ": EOF exception found" )
6554 main.log.error( self.name + ": " + self.handle.before )
6555 main.cleanAndExit()
6556 except Exception:
6557 main.log.exception( self.name + ": Uncaught exception!" )
6558 main.cleanAndExit()
6559
You Wange24d6272018-03-27 21:18:50 -07006560 def mcastSourceDelete( self, sAddr, gAddr, srcs=None ):
6561 """
6562 Delete multicast src(s) by calling 'mcast-source-delete' command
6563 sAddr: we can provide * for ASM or a specific address for SSM
6564 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006565 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 -07006566 will delete the route if not specified
6567 Returns main.TRUE if mcast sink is deleted; Otherwise main.FALSE
6568 """
6569 try:
6570 cmdStr = "mcast-source-delete"
6571 cmdStr += " -sAddr " + str( sAddr )
6572 cmdStr += " -gAddr " + str( gAddr )
6573 if srcs:
6574 assert isinstance( srcs, list )
6575 for src in srcs:
6576 cmdStr += " -src " + str( src )
6577 handle = self.sendline( cmdStr )
6578 assert handle is not None, "Error in sendline"
6579 assert "Command not found:" not in handle, handle
6580 assert "Unsupported command:" not in handle, handle
6581 assert "Error executing command" not in handle, handle
6582 if "Updated the mcast route" in handle:
6583 return main.TRUE
6584 elif "Deleted the mcast route" in handle:
6585 return main.TRUE
6586 else:
6587 return main.FALSE
6588 except AssertionError:
6589 main.log.exception( "" )
6590 return None
6591 except TypeError:
6592 main.log.exception( self.name + ": Object not as expected" )
6593 return None
6594 except pexpect.EOF:
6595 main.log.error( self.name + ": EOF exception found" )
6596 main.log.error( self.name + ": " + self.handle.before )
6597 main.cleanAndExit()
6598 except Exception:
6599 main.log.exception( self.name + ": Uncaught exception!" )
6600 main.cleanAndExit()
You Wang5da39c82018-04-26 22:55:08 -07006601
6602 def netcfg( self, jsonFormat=True, args="" ):
6603 """
6604 Run netcfg cli command with given args
6605 """
6606 try:
6607 cmdStr = "netcfg"
6608 if jsonFormat:
6609 cmdStr = cmdStr + " -j"
6610 if args:
6611 cmdStr = cmdStr + " " + str( args )
6612 handle = self.sendline( cmdStr )
6613 assert handle is not None, "Error in sendline"
6614 assert "Command not found:" not in handle, handle
6615 assert "Unsupported command:" not in handle, handle
6616 assert "Error executing command" not in handle, handle
6617 return handle
6618 except AssertionError:
6619 main.log.exception( "" )
6620 return None
6621 except TypeError:
6622 main.log.exception( self.name + ": Object not as expected" )
6623 return None
6624 except pexpect.EOF:
6625 main.log.error( self.name + ": EOF exception found" )
6626 main.log.error( self.name + ": " + self.handle.before )
6627 main.cleanAndExit()
6628 except Exception:
6629 main.log.exception( self.name + ": Uncaught exception!" )
6630 main.cleanAndExit()
6631
You Wang0fa76e72018-05-18 11:33:25 -07006632 def composeT3Command( self, sAddr, dAddr, ipv6=False, verbose=True, simple=False ):
You Wang5da39c82018-04-26 22:55:08 -07006633 """
You Wang54b1d672018-06-11 16:44:13 -07006634 Compose and return a list of t3-troubleshoot cli commands for given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006635 Options:
6636 sAddr: IP address of the source host
6637 dAddr: IP address of the destination host
You Wang0fa76e72018-05-18 11:33:25 -07006638 ipv6: True if hosts are IPv6
6639 verbose: return verbose t3 output if True
6640 simple: compose command for t3-troubleshoot-simple if True
You Wang5da39c82018-04-26 22:55:08 -07006641 """
6642 try:
6643 # Collect information of both hosts from onos
6644 hosts = self.hosts()
6645 hosts = json.loads( hosts )
6646 sHost = None
6647 dHost = None
6648 for host in hosts:
6649 if sAddr in host[ "ipAddresses" ]:
6650 sHost = host
6651 elif dAddr in host[ "ipAddresses" ]:
6652 dHost = host
6653 if sHost and dHost:
6654 break
6655 assert sHost, "Not able to find host with IP {}".format( sAddr )
You Wang54b1d672018-06-11 16:44:13 -07006656 cmdList = []
You Wang5d9527b2018-05-29 17:08:54 -07006657 if simple:
6658 assert dHost, "Not able to find host with IP {}".format( dAddr )
You Wang54b1d672018-06-11 16:44:13 -07006659 cmdStr = "t3-troubleshoot-simple"
6660 if verbose:
6661 cmdStr += " -vv"
6662 if ipv6:
6663 cmdStr += " -et ipv6"
You Wang0fa76e72018-05-18 11:33:25 -07006664 cmdStr += " {}/{} {}/{}".format( sHost[ "mac" ], sHost[ "vlan" ], dHost[ "mac" ], dHost[ "vlan" ] )
You Wang54b1d672018-06-11 16:44:13 -07006665 cmdList.append( cmdStr )
You Wang0fa76e72018-05-18 11:33:25 -07006666 else:
You Wang54b1d672018-06-11 16:44:13 -07006667 for location in sHost[ "locations" ]:
6668 cmdStr = "t3-troubleshoot"
6669 if verbose:
6670 cmdStr += " -vv"
6671 if ipv6:
6672 cmdStr += " -et ipv6"
6673 cmdStr += " -s " + str( sAddr )
6674 cmdStr += " -sp " + str( location[ "elementId" ] ) + "/" + str( location[ "port" ] )
6675 cmdStr += " -sm " + str( sHost[ "mac" ] )
6676 if sHost[ "vlan" ] != "None":
6677 cmdStr += " -vid " + sHost[ "vlan" ]
6678 cmdStr += " -d " + str( dAddr )
6679 netcfg = self.netcfg( args="devices {}".format( location[ "elementId" ] ) )
6680 netcfg = json.loads( netcfg )
6681 assert netcfg, "Failed to get netcfg"
6682 cmdStr += " -dm " + str( netcfg[ "segmentrouting" ][ "routerMac" ] )
6683 cmdList.append( cmdStr )
6684 return cmdList
You Wang5da39c82018-04-26 22:55:08 -07006685 except AssertionError:
6686 main.log.exception( "" )
6687 return None
6688 except ( KeyError, TypeError ):
6689 main.log.exception( self.name + ": Object not as expected" )
6690 return None
6691 except Exception:
6692 main.log.exception( self.name + ": Uncaught exception!" )
6693 main.cleanAndExit()
6694
6695 def t3( self, sAddr, dAddr, ipv6=False ):
6696 """
You Wang54b1d672018-06-11 16:44:13 -07006697 Run t3-troubleshoot cli commands for all posible routes given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006698 Options:
6699 sAddr: IP address of the source host
6700 dAddr: IP address of the destination host
6701 """
6702 try:
You Wang54b1d672018-06-11 16:44:13 -07006703 cmdList = self.composeT3Command( sAddr, dAddr, ipv6 )
6704 assert cmdList is not None, "composeT3Command returned None"
6705 t3Output = ""
6706 for cmdStr in cmdList:
6707 handle = self.sendline( cmdStr )
6708 assert handle is not None, "Error in sendline"
6709 assert "Command not found:" not in handle, handle
6710 assert "Unsupported command:" not in handle, handle
6711 assert "Error executing command" not in handle, handle
6712 assert "Tracing packet" in handle
6713 t3Output += handle
6714 return t3Output
You Wang5da39c82018-04-26 22:55:08 -07006715 except AssertionError:
6716 main.log.exception( "" )
6717 return None
6718 except pexpect.EOF:
6719 main.log.error( self.name + ": EOF exception found" )
6720 main.log.error( self.name + ": " + self.handle.before )
6721 main.cleanAndExit()
6722 except Exception:
6723 main.log.exception( self.name + ": Uncaught exception!" )
6724 main.cleanAndExit()
Jon Hall3c0114c2020-08-11 15:07:42 -07006725
6726 def prepareForCLI( self, debug=True, maxRetries=120 ):
6727 """
6728 Prepare docker container to connect to onos cli
6729 """
6730 try:
6731 # Wait for log files to be created
6732 ready = 0
6733 retries = 0
6734 while not ready and retries < maxRetries:
6735 retries += 1
6736 self.handle.sendline( "ls -al /root/onos/apache-karaf-*/data/log" )
6737 ready = self.handle.expect( [ "No such file or directory", self.dockerPrompt ] )
6738 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6739 if not ready:
6740 self.handle.expect( self.dockerPrompt )
6741 time.sleep( 1 )
6742 #main.log.debug( "%s: It took %s tries for onos log folder to %sbe created" %
6743 # ( self.name, retries, "" if ready else "NOT " ) )
6744
6745 cmdList = []
6746 cmdList.append( "apt-get update" )
6747 cmdList.append( "apt-get install -y openssh-server" )
6748 # Some built in scripts are hardcoded
6749 cmdList.append( "ln -s /root/onos /opt/onos" )
6750 cmdList.append( "ln -s /root/onos/apache-karaf-*/data/log /opt/onos/log" )
6751 cmdList.append( "ls -al /opt/onos" )
6752 output = ""
6753 for cmdStr in cmdList:
6754 self.handle.sendline( cmdStr )
6755 self.handle.expect( self.dockerPrompt )
6756 self.handle.sendline( "" )
6757 self.handle.expect( self.dockerPrompt )
6758 handle = self.handle.before
6759 assert "command not found" not in handle, handle
6760 assert "No such file or directory" not in handle, handle
6761 output += handle
6762 if debug:
6763 main.log.debug( "%s: %s" % ( self.name, output ) )
6764 return output
6765 except AssertionError:
6766 main.log.exception( "" )
6767 return None
6768 except pexpect.EOF:
6769 main.log.error( self.name + ": EOF exception found" )
6770 main.log.error( self.name + ": " + self.handle.before )
6771 main.cleanAndExit()
6772 except Exception:
6773 main.log.exception( self.name + ": Uncaught exception!" )
6774 main.cleanAndExit()
6775
6776 def onosSecureSSH( self, userName="onos", userPWD="rocks" ):
6777 """
6778 Enables secure access to ONOS console
6779 by removing default users & keys.
6780
6781 bin/onos-user-password onos rocks
6782
6783 Returns: main.TRUE on success and main.FALSE on failure
6784 """
6785
6786 try:
6787 self.handle.sendline( "" )
6788 self.handle.expect( self.dockerPrompt )
6789
6790 self.handle.sendline( "[ ! -f ~/.ssh/id_rsa.pub ] && ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' -q" )
6791 self.handle.expect( self.dockerPrompt )
6792 main.log.debug( "%s: %s%s" % ( self.name, self.handle.before, self.handle.after ) )
6793
6794 self.handle.sendline( "bin/onos-user-key $(id -un) $(cut -d\\\\ -f2 ~/.ssh/id_rsa.pub)" )
6795 self.handle.expect( pexpect.TIMEOUT, timeout=10 )
6796 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6797
6798 self.handle.sendline( "bin/onos-user-password %s %s" % ( userName, userPWD ) )
6799 i = self.handle.expect( [ "usage",
6800 self.dockerPrompt,
6801 pexpect.TIMEOUT ] )
6802 if i == 0:
6803 # malformed command
6804 main.log.warn( self.name + ": Could not parse onos-user-password command" )
6805 self.handle.expect( self.dockerPrompt )
6806 return main.FALSE
6807 elif i == 1:
6808 # Process started
6809 main.log.info( self.name + ": SSH password added for user " + userName )
6810 return main.TRUE
6811 elif i == 2:
6812 # timeout
6813 main.log.error( self.name + ": Failed to secure onos ssh " )
6814 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6815 except pexpect.EOF:
6816 main.log.error( self.name + ": EOF exception found" )
6817 main.log.error( self.name + ": " + self.handle.before )
6818 main.cleanAndExit()
6819 except Exception:
6820 main.log.exception( self.name + ": Uncaught exception!" )
6821 main.cleanAndExit()