blob: f4f65db593a4e123a4c949cee345e2ed68e43faf [file] [log] [blame]
andrewonlab95ce8322014-10-13 14:12:04 -04001#!/usr/bin/env python
Jon Hall06fd0df2021-01-25 15:50:06 -08002# -*- coding: utf-8 -*-
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"""
Siddesh715a9192021-11-03 19:51:20 +000039import ipaddress
andrewonlab95ce8322014-10-13 14:12:04 -040040import pexpect
41import re
Jon Hall30b82fa2015-03-04 17:15:43 -080042import json
43import types
Jon Hallbd16b922015-03-26 17:53:15 -070044import time
kelvin-onlaba4074292015-07-09 15:19:49 -070045import os
andrewonlab95ce8322014-10-13 14:12:04 -040046from drivers.common.clidriver import CLI
You Wangdb8cd0a2016-05-26 15:19:45 -070047from core.graph import Graph
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -070048from cStringIO import StringIO
49from itertools import izip
andrewonlab95ce8322014-10-13 14:12:04 -040050
kelvin8ec71442015-01-15 16:57:00 -080051class OnosCliDriver( CLI ):
andrewonlab95ce8322014-10-13 14:12:04 -040052
kelvin8ec71442015-01-15 16:57:00 -080053 def __init__( self ):
54 """
55 Initialize client
56 """
Jon Hallefbd9792015-03-05 16:11:36 -080057 self.name = None
58 self.home = None
59 self.handle = None
Devin Limdc78e202017-06-09 18:30:07 -070060 self.karafUser = None
61 self.karafPass = None
Jon Hall06fd0df2021-01-25 15:50:06 -080062 self.karafPort = None
Jon Hall9b0de1f2020-08-24 15:38:04 -070063 self.karafTimeout = None
Jon Hall06fd0df2021-01-25 15:50:06 -080064 self.address = None
Siddesh52750622021-03-05 19:52:03 +000065 self.karafPromptUser = None
Jon Hall3c0114c2020-08-11 15:07:42 -070066 self.dockerPrompt = None
You Wangdb8cd0a2016-05-26 15:19:45 -070067 self.graph = Graph()
Devin Limdc78e202017-06-09 18:30:07 -070068 super( OnosCliDriver, self ).__init__()
kelvin8ec71442015-01-15 16:57:00 -080069
70 def connect( self, **connectargs ):
71 """
andrewonlab95ce8322014-10-13 14:12:04 -040072 Creates ssh handle for ONOS cli.
kelvin8ec71442015-01-15 16:57:00 -080073 """
andrewonlab95ce8322014-10-13 14:12:04 -040074 try:
75 for key in connectargs:
kelvin8ec71442015-01-15 16:57:00 -080076 vars( self )[ key ] = connectargs[ key ]
andrew@onlab.us658ec012015-03-11 15:13:09 -070077 self.home = "~/onos"
andrewonlab95ce8322014-10-13 14:12:04 -040078 for key in self.options:
79 if key == "home":
Devin Limdc78e202017-06-09 18:30:07 -070080 self.home = self.options[ key ]
81 elif key == "karaf_username":
82 self.karafUser = self.options[ key ]
83 elif key == "karaf_password":
84 self.karafPass = self.options[ key ]
Jon Hall3c0114c2020-08-11 15:07:42 -070085 elif key == "docker_prompt":
86 self.dockerPrompt = self.options[ key ]
Jon Hall9b0de1f2020-08-24 15:38:04 -070087 elif key == "karaf_timeout":
88 self.karafTimeout = self.options[ key ]
Jon Hall06fd0df2021-01-25 15:50:06 -080089 elif key == "karaf_port":
90 self.karafPort = self.options[ key ]
Siddesh52750622021-03-05 19:52:03 +000091 elif key == "karafPromptUser":
92 self.karafPromptUser = self.options[ key ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -070093 self.home = self.checkOptions( self.home, "~/onos" )
94 self.karafUser = self.checkOptions( self.karafUser, self.user_name )
95 self.karafPass = self.checkOptions( self.karafPass, self.pwd )
Jon Hall06fd0df2021-01-25 15:50:06 -080096 self.karafPort = self.checkOptions( self.karafPort, 8101 )
Jon Hall3c0114c2020-08-11 15:07:42 -070097 self.dockerPrompt = self.checkOptions( self.dockerPrompt, "~/onos#" )
Jon Hall9b0de1f2020-08-24 15:38:04 -070098 self.karafTimeout = self.checkOptions( self.karafTimeout, 7200000 )
andrewonlab95ce8322014-10-13 14:12:04 -040099
Siddesh52750622021-03-05 19:52:03 +0000100 self.karafPrompt = self.karafPromptUser + "@root >"
kelvin-onlaba4074292015-07-09 15:19:49 -0700101 for key in self.options:
102 if key == 'onosIp':
103 self.onosIp = self.options[ 'onosIp' ]
104 break
105
kelvin8ec71442015-01-15 16:57:00 -0800106 self.name = self.options[ 'name' ]
kelvin-onlaba4074292015-07-09 15:19:49 -0700107
108 try:
Jon Hallc6793552016-01-19 14:18:37 -0800109 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -0700110 self.ip_address = os.getenv( str( self.ip_address ) )
111 else:
112 main.log.info( self.name +
113 ": Trying to connect to " +
114 self.ip_address )
115
116 except KeyError:
117 main.log.info( "Invalid host name," +
118 " connecting to local host instead" )
119 self.ip_address = 'localhost'
120 except Exception as inst:
121 main.log.error( "Uncaught exception: " + str( inst ) )
122
kelvin8ec71442015-01-15 16:57:00 -0800123 self.handle = super( OnosCliDriver, self ).connect(
kelvin-onlab08679eb2015-01-21 16:11:48 -0800124 user_name=self.user_name,
125 ip_address=self.ip_address,
kelvin-onlab898a6c62015-01-16 14:13:53 -0800126 port=self.port,
127 pwd=self.pwd,
128 home=self.home )
andrewonlab95ce8322014-10-13 14:12:04 -0400129
kelvin8ec71442015-01-15 16:57:00 -0800130 self.handle.sendline( "cd " + self.home )
Devin Limdc78e202017-06-09 18:30:07 -0700131 self.handle.expect( self.prompt )
andrewonlab95ce8322014-10-13 14:12:04 -0400132 if self.handle:
Jon Hall06fd0df2021-01-25 15:50:06 -0800133 self.address = self.ip_address
andrewonlab95ce8322014-10-13 14:12:04 -0400134 return self.handle
kelvin8ec71442015-01-15 16:57:00 -0800135 else:
136 main.log.info( "NO ONOS HANDLE" )
andrewonlab95ce8322014-10-13 14:12:04 -0400137 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -0800138 except TypeError:
139 main.log.exception( self.name + ": Object not as expected" )
140 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400141 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800142 main.log.error( self.name + ": EOF exception found" )
143 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700144 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800145 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800146 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700147 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400148
kelvin8ec71442015-01-15 16:57:00 -0800149 def disconnect( self ):
150 """
andrewonlab95ce8322014-10-13 14:12:04 -0400151 Called when Test is complete to disconnect the ONOS handle.
kelvin8ec71442015-01-15 16:57:00 -0800152 """
Jon Halld61331b2015-02-17 16:35:47 -0800153 response = main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -0400154 try:
Jon Hall61282e32015-03-19 11:34:11 -0700155 if self.handle:
156 i = self.logout()
157 if i == main.TRUE:
158 self.handle.sendline( "" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700159 for l in range( 3 ):
160 p = self.handle.expect( [ self.prompt, self.dockerPrompt ] )
161 if p == 1:
162 self.inDocker = False
163 self.handle.sendline( "exit" )
164 j = self.handle.expect( [ "closed", pexpect.TIMEOUT ], timeout=3 )
165 if j == 0:
166 return response
167 response = main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -0800168 except TypeError:
169 main.log.exception( self.name + ": Object not as expected" )
Jon Halld61331b2015-02-17 16:35:47 -0800170 response = main.FALSE
andrewonlab95ce8322014-10-13 14:12:04 -0400171 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800172 main.log.error( self.name + ": EOF exception found" )
173 main.log.error( self.name + ": " + self.handle.before )
Jon Hall61282e32015-03-19 11:34:11 -0700174 except ValueError:
Jon Hall1a77a1e2015-04-06 10:41:13 -0700175 main.log.exception( "Exception in disconnect of " + self.name )
Jon Hall61282e32015-03-19 11:34:11 -0700176 response = main.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -0800177 except Exception:
Jon Hall3c0114c2020-08-11 15:07:42 -0700178 main.log.exception( self.name + ": disconnection failed from the host" )
andrewonlab95ce8322014-10-13 14:12:04 -0400179 response = main.FALSE
180 return response
181
kelvin8ec71442015-01-15 16:57:00 -0800182 def logout( self ):
183 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500184 Sends 'logout' command to ONOS cli
Jon Hall61282e32015-03-19 11:34:11 -0700185 Returns main.TRUE if exited CLI and
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000186 main.FALSE on timeout (not guranteed you are disconnected)
Jon Hall61282e32015-03-19 11:34:11 -0700187 None on TypeError
188 Exits test on unknown error or pexpect exits unexpectedly
kelvin8ec71442015-01-15 16:57:00 -0800189 """
andrewonlab38d2b4a2014-11-13 16:28:47 -0500190 try:
Jon Hall61282e32015-03-19 11:34:11 -0700191 if self.handle:
192 self.handle.sendline( "" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700193 i = self.handle.expect( [ self.karafPrompt,
194 self.Prompt(),
195 pexpect.TIMEOUT ],
196
Jon Hall61282e32015-03-19 11:34:11 -0700197 timeout=10 )
198 if i == 0: # In ONOS CLI
199 self.handle.sendline( "logout" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700200 j = self.handle.expect( [ self.Prompt(),
Jon Hallbfe00002016-04-05 10:23:54 -0700201 "Command not found:",
202 pexpect.TIMEOUT ] )
203 if j == 0: # Successfully logged out
204 return main.TRUE
205 elif j == 1 or j == 2:
206 # ONOS didn't fully load, and logout command isn't working
207 # or the command timed out
208 self.handle.send( "\x04" ) # send ctrl-d
Jon Hall64ab3bd2016-05-13 11:29:44 -0700209 try:
Jon Hall3c0114c2020-08-11 15:07:42 -0700210 self.handle.expect( self.Prompt() )
Jon Hall64ab3bd2016-05-13 11:29:44 -0700211 except pexpect.TIMEOUT:
212 main.log.error( "ONOS did not respond to 'logout' or CTRL-d" )
Jon Hallbfe00002016-04-05 10:23:54 -0700213 return main.TRUE
Jon Halle0f0b342017-04-18 11:43:47 -0700214 else: # some other output
Jon Hallbfe00002016-04-05 10:23:54 -0700215 main.log.warn( "Unknown repsonse to logout command: '{}'",
216 repr( self.handle.before ) )
217 return main.FALSE
Jon Hall61282e32015-03-19 11:34:11 -0700218 elif i == 1: # not in CLI
219 return main.TRUE
steven30801e42f1fb2019-01-17 11:31:45 +0800220 elif i == 2: # Timeout
Jon Hall61282e32015-03-19 11:34:11 -0700221 return main.FALSE
222 else:
andrewonlab9627f432014-11-14 12:45:10 -0500223 return main.TRUE
Jon Halld4d4b372015-01-28 16:02:41 -0800224 except TypeError:
225 main.log.exception( self.name + ": Object not as expected" )
226 return None
andrewonlab38d2b4a2014-11-13 16:28:47 -0500227 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800228 main.log.error( self.name + ": eof exception found" )
Jon Hall61282e32015-03-19 11:34:11 -0700229 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700230 main.cleanAndExit()
Jon Hall61282e32015-03-19 11:34:11 -0700231 except ValueError:
Jon Hall5aa168b2015-03-23 14:23:09 -0700232 main.log.error( self.name +
233 "ValueError exception in logout method" )
Jon Hallfebb1c72015-03-05 13:30:09 -0800234 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800235 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700236 main.cleanAndExit()
andrewonlab38d2b4a2014-11-13 16:28:47 -0500237
kelvin-onlabd3b64892015-01-20 13:26:24 -0800238 def setCell( self, cellname ):
kelvin8ec71442015-01-15 16:57:00 -0800239 """
andrewonlab95ce8322014-10-13 14:12:04 -0400240 Calls 'cell <name>' to set the environment variables on ONOSbench
kelvin8ec71442015-01-15 16:57:00 -0800241
andrewonlab95ce8322014-10-13 14:12:04 -0400242 Before issuing any cli commands, set the environment variable first.
kelvin8ec71442015-01-15 16:57:00 -0800243 """
andrewonlab95ce8322014-10-13 14:12:04 -0400244 try:
245 if not cellname:
kelvin8ec71442015-01-15 16:57:00 -0800246 main.log.error( "Must define cellname" )
Devin Lim44075962017-08-11 10:56:37 -0700247 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400248 else:
kelvin8ec71442015-01-15 16:57:00 -0800249 self.handle.sendline( "cell " + str( cellname ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800250 # Expect the cellname in the ONOSCELL variable.
kelvin8ec71442015-01-15 16:57:00 -0800251 # Note that this variable name is subject to change
andrewonlab95ce8322014-10-13 14:12:04 -0400252 # and that this driver will have to change accordingly
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700253 self.handle.expect( str( cellname ) )
andrew@onlab.usc400b112015-01-21 15:33:19 -0800254 handleBefore = self.handle.before
255 handleAfter = self.handle.after
kelvin8ec71442015-01-15 16:57:00 -0800256 # Get the rest of the handle
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700257 self.handle.sendline( "" )
258 self.handle.expect( self.prompt )
andrew@onlab.usc400b112015-01-21 15:33:19 -0800259 handleMore = self.handle.before
andrewonlab95ce8322014-10-13 14:12:04 -0400260
kelvin-onlabd3b64892015-01-20 13:26:24 -0800261 main.log.info( "Cell call returned: " + handleBefore +
262 handleAfter + handleMore )
andrewonlab95ce8322014-10-13 14:12:04 -0400263
264 return main.TRUE
265
Jon Halld4d4b372015-01-28 16:02:41 -0800266 except TypeError:
267 main.log.exception( self.name + ": Object not as expected" )
268 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400269 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800270 main.log.error( self.name + ": eof exception found" )
271 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700272 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800273 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800274 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700275 main.cleanAndExit()
kelvin8ec71442015-01-15 16:57:00 -0800276
pingping-lin57a56ce2015-05-20 16:43:48 -0700277 def startOnosCli( self, ONOSIp, karafTimeout="",
Chiyu Chengef109502016-11-21 15:51:38 -0800278 commandlineTimeout=10, onosStartTimeout=60, waitForStart=False ):
kelvin8ec71442015-01-15 16:57:00 -0800279 """
Jon Hallefbd9792015-03-05 16:11:36 -0800280 karafTimeout is an optional argument. karafTimeout value passed
kelvin-onlabd3b64892015-01-20 13:26:24 -0800281 by user would be used to set the current karaf shell idle timeout.
282 Note that when ever this property is modified the shell will exit and
Hari Krishnad7b9c202015-01-05 10:38:14 -0800283 the subsequent login would reflect new idle timeout.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800284 Below is an example to start a session with 60 seconds idle timeout
285 ( input value is in milliseconds ):
kelvin8ec71442015-01-15 16:57:00 -0800286
Hari Krishna25d42f72015-01-05 15:08:28 -0800287 tValue = "60000"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800288 main.ONOScli1.startOnosCli( ONOSIp, karafTimeout=tValue )
kelvin8ec71442015-01-15 16:57:00 -0800289
kelvin-onlabd3b64892015-01-20 13:26:24 -0800290 Note: karafTimeout is left as str so that this could be read
291 and passed to startOnosCli from PARAMS file as str.
kelvin8ec71442015-01-15 16:57:00 -0800292 """
You Wangf69ab392016-01-26 16:34:38 -0800293 self.onosIp = ONOSIp
Jon Hall06fd0df2021-01-25 15:50:06 -0800294 self.address = self.onosIp
andrewonlab95ce8322014-10-13 14:12:04 -0400295 try:
Jon Hall67253832016-12-05 09:47:13 -0800296 # Check if we are already in the cli
kelvin8ec71442015-01-15 16:57:00 -0800297 self.handle.sendline( "" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700298 x = self.handle.expect( [ self.Prompt(), self.karafPrompt ], commandlineTimeout )
andrewonlab48829f62014-11-17 13:49:01 -0500299 if x == 1:
kelvin8ec71442015-01-15 16:57:00 -0800300 main.log.info( "ONOS cli is already running" )
andrewonlab48829f62014-11-17 13:49:01 -0500301 return main.TRUE
andrewonlab95ce8322014-10-13 14:12:04 -0400302
Jon Hall67253832016-12-05 09:47:13 -0800303 # Not in CLI so login
Jon Hall3c0114c2020-08-11 15:07:42 -0700304 if self.inDocker:
305 # The Docker does not have all the wrapper scripts
Jon Hall06fd0df2021-01-25 15:50:06 -0800306 startCliCommand = "ssh -p %s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null %s@localhost" % ( self.karafPort, self.karafUser )
Jon Hall3c0114c2020-08-11 15:07:42 -0700307 elif waitForStart:
Jeremy Ronquilloec916a42018-02-02 13:05:57 -0800308 # Wait for onos start ( onos-wait-for-start ) and enter onos cli
Jon Hall3c0114c2020-08-11 15:07:42 -0700309 startCliCommand = "onos-wait-for-start " + str( ONOSIp )
Chiyu Chengef109502016-11-21 15:51:38 -0800310 else:
Jon Hall3c0114c2020-08-11 15:07:42 -0700311 startCliCommand = "onos " + str( ONOSIp )
312 self.handle.sendline( startCliCommand )
313 tries = 0
Jon Hallf69e3162020-09-01 09:08:44 -0700314 timeoutSet = False
Jon Hall3c0114c2020-08-11 15:07:42 -0700315 while tries < 5:
316 i = self.handle.expect( [
317 self.karafPrompt,
318 "Password:",
319 pexpect.TIMEOUT ], onosStartTimeout )
andrewonlab2a7ea9b2014-10-24 12:21:05 -0400320
andrewonlab3a7c3c72014-10-24 17:21:03 -0400321 if i == 0:
Jon Hallf69e3162020-09-01 09:08:44 -0700322 if not karafTimeout or timeoutSet:
Jon Hall9b0de1f2020-08-24 15:38:04 -0700323 main.log.info( str( ONOSIp ) + " CLI Started successfully" )
324 return main.TRUE
Hari Krishnae36ef212015-01-04 14:09:13 -0800325 if karafTimeout:
kelvin8ec71442015-01-15 16:57:00 -0800326 self.handle.sendline(
kelvin-onlabd3b64892015-01-20 13:26:24 -0800327 "config:property-set -p org.apache.karaf.shell\
Jon Hall3c0114c2020-08-11 15:07:42 -0700328 sshIdleTimeout " +
Jon Hall9b0de1f2020-08-24 15:38:04 -0700329 str( karafTimeout ) )
330 self.handle.expect( "closed by remote host" )
Jon Hallf69e3162020-09-01 09:08:44 -0700331 self.handle.expect( self.Prompt() )
Jon Hall9b0de1f2020-08-24 15:38:04 -0700332 self.handle.sendline( startCliCommand )
Jon Hallf69e3162020-09-01 09:08:44 -0700333 timeoutSet = True
Jon Hall3c0114c2020-08-11 15:07:42 -0700334 elif i == 1:
335 main.log.info( str( ONOSIp ) + " CLI asking for password" )
336 main.log.debug( "Sending %s" % self.karafPass )
337 self.handle.sendline( self.karafPass )
andrewonlab3a7c3c72014-10-24 17:21:03 -0400338 else:
Jon Hall3c0114c2020-08-11 15:07:42 -0700339 # If failed, send ctrl+c to process and try again
340 main.log.info( "Starting CLI failed. Retrying..." )
Jon Hallf69e3162020-09-01 09:08:44 -0700341 time.sleep( 5 )
Jon Hall3c0114c2020-08-11 15:07:42 -0700342 self.handle.send( "\x03" )
343 self.handle.sendline( startCliCommand )
344 tries += 1
345 main.log.error( "Connection to CLI " + str( ONOSIp ) + " timeout" )
346 return main.FALSE
Jon Halld4d4b372015-01-28 16:02:41 -0800347 except TypeError:
348 main.log.exception( self.name + ": Object not as expected" )
349 return None
andrewonlab95ce8322014-10-13 14:12:04 -0400350 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800351 main.log.error( self.name + ": EOF exception found" )
352 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700353 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800354 except Exception:
Jon Hall06fd0df2021-01-25 15:50:06 -0800355 main.log.debug( self.handle.before + str( self.handle.after ) )
Jon Halld4d4b372015-01-28 16:02:41 -0800356 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700357 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400358
suibin zhang116647a2016-05-06 16:30:09 -0700359 def startCellCli( self, karafTimeout="",
360 commandlineTimeout=10, onosStartTimeout=60 ):
361 """
Jon Hall3c0114c2020-08-11 15:07:42 -0700362 Start CLI on onos cell handle.
suibin zhang116647a2016-05-06 16:30:09 -0700363
364 karafTimeout is an optional argument. karafTimeout value passed
365 by user would be used to set the current karaf shell idle timeout.
366 Note that when ever this property is modified the shell will exit and
367 the subsequent login would reflect new idle timeout.
368 Below is an example to start a session with 60 seconds idle timeout
369 ( input value is in milliseconds ):
370
371 tValue = "60000"
372
373 Note: karafTimeout is left as str so that this could be read
374 and passed to startOnosCli from PARAMS file as str.
375 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000376
suibin zhang116647a2016-05-06 16:30:09 -0700377 try:
378 self.handle.sendline( "" )
379 x = self.handle.expect( [
Jon Hall3c0114c2020-08-11 15:07:42 -0700380 self.Prompt(), self.karafPrompt ], commandlineTimeout )
suibin zhang116647a2016-05-06 16:30:09 -0700381
382 if x == 1:
383 main.log.info( "ONOS cli is already running" )
384 return main.TRUE
385
Jeremy Ronquilloec916a42018-02-02 13:05:57 -0800386 # Wait for onos start ( onos-wait-for-start ) and enter onos cli
suibin zhang116647a2016-05-06 16:30:09 -0700387 self.handle.sendline( "/opt/onos/bin/onos" )
388 i = self.handle.expect( [
Jon Hall6c9e2da2018-11-06 12:01:23 -0800389 self.karafPrompt,
suibin zhang116647a2016-05-06 16:30:09 -0700390 pexpect.TIMEOUT ], onosStartTimeout )
391
392 if i == 0:
393 main.log.info( self.name + " CLI Started successfully" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800394 if karafTimeout: # FIXME: This doesn't look right
suibin zhang116647a2016-05-06 16:30:09 -0700395 self.handle.sendline(
396 "config:property-set -p org.apache.karaf.shell\
397 sshIdleTimeout " +
398 karafTimeout )
Jon Hall3c0114c2020-08-11 15:07:42 -0700399 self.handle.expect( self.Prompt() )
suibin zhang116647a2016-05-06 16:30:09 -0700400 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800401 self.handle.expect( self.karafPrompt )
suibin zhang116647a2016-05-06 16:30:09 -0700402 return main.TRUE
403 else:
404 # If failed, send ctrl+c to process and try again
405 main.log.info( "Starting CLI failed. Retrying..." )
406 self.handle.send( "\x03" )
407 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800408 i = self.handle.expect( [ self.karafPrompt, pexpect.TIMEOUT ],
suibin zhang116647a2016-05-06 16:30:09 -0700409 timeout=30 )
410 if i == 0:
411 main.log.info( self.name + " CLI Started " +
412 "successfully after retry attempt" )
413 if karafTimeout:
414 self.handle.sendline(
415 "config:property-set -p org.apache.karaf.shell\
416 sshIdleTimeout " +
417 karafTimeout )
Jon Hall3c0114c2020-08-11 15:07:42 -0700418 self.handle.expect( self.Prompt() )
suibin zhang116647a2016-05-06 16:30:09 -0700419 self.handle.sendline( "/opt/onos/bin/onos" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800420 self.handle.expect( self.karafPrompt )
suibin zhang116647a2016-05-06 16:30:09 -0700421 return main.TRUE
422 else:
423 main.log.error( "Connection to CLI " +
424 self.name + " timeout" )
425 return main.FALSE
426
427 except TypeError:
428 main.log.exception( self.name + ": Object not as expected" )
429 return None
430 except pexpect.EOF:
431 main.log.error( self.name + ": EOF exception found" )
432 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700433 main.cleanAndExit()
suibin zhang116647a2016-05-06 16:30:09 -0700434 except Exception:
435 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700436 main.cleanAndExit()
suibin zhang116647a2016-05-06 16:30:09 -0700437
Pratik Parab3b2ab5a2017-02-14 13:15:14 -0800438 def log( self, cmdStr, level="", noExit=False ):
kelvin-onlab9f541032015-02-04 16:19:53 -0800439 """
You Wang22e807e2021-03-29 10:53:38 -0700440 log the commands in the onos CLI.
kelvin-onlab338f5512015-02-06 10:53:16 -0800441 returns main.TRUE on success
Jon Hallefbd9792015-03-05 16:11:36 -0800442 returns main.FALSE if Error occurred
YPZhangebf9eb52016-05-12 15:20:24 -0700443 if noExit is True, TestON will not exit, but clean up
kelvin-onlab338f5512015-02-06 10:53:16 -0800444 Available level: DEBUG, TRACE, INFO, WARN, ERROR
445 Level defaults to INFO
Pratik Parab3b2ab5a2017-02-14 13:15:14 -0800446 if cmdStr has spaces then put quotes in the passed string
kelvin-onlab9f541032015-02-04 16:19:53 -0800447 """
448 try:
kelvin-onlab338f5512015-02-06 10:53:16 -0800449 lvlStr = ""
450 if level:
451 lvlStr = "--level=" + level
You Wang22e807e2021-03-29 10:53:38 -0700452 handle = self.sendline( "log:log " + lvlStr + " " + cmdStr, noExit=noExit )
453 assert handle is not None, "Error in sendline"
454 assert "Command not found:" not in handle, handle
455 if re.search( "Error", handle ):
456 main.log.error( self.name + ": Error in logging message" )
457 main.log.error( handle )
kelvin-onlab9f541032015-02-04 16:19:53 -0800458 return main.FALSE
YPZhangebf9eb52016-05-12 15:20:24 -0700459 else:
You Wang22e807e2021-03-29 10:53:38 -0700460 return main.TRUE
461 except AssertionError:
462 main.log.exception( "" )
463 return None
464 except TypeError:
465 main.log.exception( self.name + ": Object not as expected" )
466 return None
kelvin-onlab9f541032015-02-04 16:19:53 -0800467 except pexpect.EOF:
468 main.log.error( self.name + ": EOF exception found" )
469 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700470 if noExit:
471 main.cleanup()
472 return None
473 else:
Devin Lim44075962017-08-11 10:56:37 -0700474 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800475 except Exception:
kelvin-onlabfb521662015-02-27 09:52:40 -0800476 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700477 if noExit:
478 main.cleanup()
479 return None
480 else:
Devin Lim44075962017-08-11 10:56:37 -0700481 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -0400482
Jon Hall0e240372018-05-02 11:21:57 -0700483 def clearBuffer( self, debug=False, timeout=10, noExit=False ):
kelvin8ec71442015-01-15 16:57:00 -0800484 """
Jon Hall0e240372018-05-02 11:21:57 -0700485 Test cli connection and clear any left over output in the buffer
486 Optional Arguments:
487 debug - Defaults to False. If True, will enable debug logging.
488 timeout - Defaults to 10. Amount of time in seconds for a command to return
489 before a timeout.
490 noExit - Defaults to False. If True, will not exit TestON in the event of a
kelvin8ec71442015-01-15 16:57:00 -0800491 """
andrewonlaba18f6bf2014-10-13 19:31:54 -0400492 try:
Jon Halla495f562016-05-16 18:03:26 -0700493 # Try to reconnect if disconnected from cli
494 self.handle.sendline( "" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700495 i = self.handle.expect( [ self.karafPrompt,
496 self.Prompt(),
497 pexpect.TIMEOUT ] )
Jon Hall0e240372018-05-02 11:21:57 -0700498 response = self.handle.before
Jon Halla16b4db2021-10-20 14:11:59 -0700499 if i == 1: # Not in ONOS CLI
500 # FIXME: This isn't really the correct place for this, but it works for now
501 # Check if port-forward session is still up first
502 if hasattr( main, "Cluster"):
503 ctrl = None
504 for c in main.Cluster.controllers:
505 if c.CLI is self:
506 ctrl = c
507 break
508 if not ctrl:
509 main.log.warn( self.name + ": Could not find this node in Cluster. Can't check port-forward status" )
510 elif ctrl.k8s:
511 ctrl.k8s.checkPortForward( ctrl.k8s.podName,
512 kubeconfig=ctrl.k8s.kubeConfig,
513 namespace=main.params[ 'kubernetes' ][ 'namespace' ] )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700514 main.log.error( self.name + ": onos cli session closed. " )
Jon Halla495f562016-05-16 18:03:26 -0700515 if self.onosIp:
516 main.log.warn( "Trying to reconnect " + self.onosIp )
517 reconnectResult = self.startOnosCli( self.onosIp )
518 if reconnectResult:
519 main.log.info( self.name + ": onos cli session reconnected." )
520 else:
521 main.log.error( self.name + ": reconnection failed." )
YPZhang14a4aa92016-07-15 13:37:15 -0700522 if noExit:
523 return None
524 else:
Devin Lim44075962017-08-11 10:56:37 -0700525 main.cleanAndExit()
Jon Halla495f562016-05-16 18:03:26 -0700526 else:
Devin Lim44075962017-08-11 10:56:37 -0700527 main.cleanAndExit()
Jon Halla495f562016-05-16 18:03:26 -0700528 if i == 2:
Jon Hall7a6ebfd2017-03-13 10:58:58 -0700529 main.log.warn( "Timeout when testing cli responsiveness" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700530 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
Jon Hall7a6ebfd2017-03-13 10:58:58 -0700531 self.handle.send( "\x03" ) # Send ctrl-c to clear previous output
Jon Hall6c9e2da2018-11-06 12:01:23 -0800532 self.handle.expect( self.karafPrompt )
Jon Halla495f562016-05-16 18:03:26 -0700533
Jon Hall0e240372018-05-02 11:21:57 -0700534 response += self.handle.before
Jon Hall14a03b52016-05-11 12:07:30 -0700535 if debug:
Jon Hall0e240372018-05-02 11:21:57 -0700536 main.log.debug( self.name + ": Raw output from sending ''" )
537 main.log.debug( self.name + ": " + repr( response ) )
538 except pexpect.TIMEOUT:
539 main.log.error( self.name + ": ONOS timeout" )
Jon Hall3c0114c2020-08-11 15:07:42 -0700540 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
You Wang141b43b2018-06-26 16:50:18 -0700541 self.handle.send( "\x03" )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800542 self.handle.expect( self.karafPrompt )
Jon Hall0e240372018-05-02 11:21:57 -0700543 return None
544 except pexpect.EOF:
545 main.log.error( self.name + ": EOF exception found" )
546 main.log.error( self.name + ": " + self.handle.before )
547 if noExit:
548 return None
549 else:
550 main.cleanAndExit()
551 except Exception:
552 main.log.exception( self.name + ": Uncaught exception!" )
553 if noExit:
554 return None
555 else:
556 main.cleanAndExit()
557
Jon Hall22e94ce2019-01-15 14:52:17 -0800558 def sendline( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False, relaxedRegex=True, expectJson=False ):
Jon Hall0e240372018-05-02 11:21:57 -0700559 """
560 A wrapper around pexpect's sendline/expect. Will return all the output from a given command
561
562 Required Arguments:
563 cmdStr - String to send to the pexpect session
564
565 Optional Arguments:
566 showResponse - Defaults to False. If True will log the response.
567 debug - Defaults to False. If True, will enable debug logging.
568 timeout - Defaults to 10. Amount of time in seconds for a command to return
569 before a timeout.
570 noExit - Defaults to False. If True, will not exit TestON in the event of a
571 closed channel, but instead return None
Jon Hall6c9e2da2018-11-06 12:01:23 -0800572 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 -0700573
574 Warning: There are no sanity checking to commands sent using this method.
575
576 """
577 try:
578 # Try to reconnect if disconnected from cli
579 self.clearBuffer( debug=debug, timeout=timeout, noExit=noExit )
580 if debug:
581 # NOTE: This adds an average of .4 seconds per call
Jon Hall14a03b52016-05-11 12:07:30 -0700582 logStr = "\"Sending CLI command: '" + cmdStr + "'\""
Jon Halle0f0b342017-04-18 11:43:47 -0700583 self.log( logStr, noExit=noExit )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800584 self.handle.sendline( cmdStr )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800585 self.handle.expect( self.karafPrompt, timeout )
Jon Hall63604932015-02-26 17:09:50 -0800586 response = self.handle.before
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000587 main.log.info( "Command '" + str( cmdStr ) + "' sent to "
Jon Hallc6793552016-01-19 14:18:37 -0800588 + self.name + "." )
Jon Hallc6358dd2015-04-10 12:44:28 -0700589 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700590 main.log.debug( self.name + ": Raw output" )
591 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700592
Jon Hall3c0114c2020-08-11 15:07:42 -0700593 response = self.cleanOutput( response, debug=debug )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800594 # Remove control codes from karaf 4.2.1
Jon Hall3c0114c2020-08-11 15:07:42 -0700595 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 -0800596 response = karafEscape.sub( '', response )
597 if debug:
598 main.log.debug( self.name + ": karafEscape output" )
599 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700600 # Remove ANSI color control strings from output
Jon Hall43060f62020-06-23 13:13:33 -0700601 response = self.cleanOutput( response, debug )
Jon Hallc6358dd2015-04-10 12:44:28 -0700602
Jon Hall6c9e2da2018-11-06 12:01:23 -0800603 # Remove ANSI color control strings from output
Jon Hallcf31d0f2018-12-13 11:18:48 -0800604 # NOTE: karaf is sometimes adding a single character then two
605 # backspaces and sometimes adding 2 characters with 2 backspaces??
Jon Hall3c0114c2020-08-11 15:07:42 -0700606 backspaceEscape = re.compile( r'((.|\s)\x08)' )
607 unchanged = False
608 while not unchanged:
609 old = response
610 response = backspaceEscape.sub( '', response, count=1 )
611 if debug:
612 main.log.debug( self.name + ": backspaceEscape output" )
613 main.log.debug( self.name + ": " + repr( response ) )
614 unchanged = old == response
Jon Hall6c9e2da2018-11-06 12:01:23 -0800615
kelvin-onlabfb521662015-02-27 09:52:40 -0800616 # Remove extra return chars that get added
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000617 response = re.sub( r"\s\r", "", response )
Jon Hallc6358dd2015-04-10 12:44:28 -0700618 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700619 main.log.debug( self.name + ": Removed extra returns " +
620 "from output" )
621 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700622
623 # Strip excess whitespace
Jon Hall63604932015-02-26 17:09:50 -0800624 response = response.strip()
Jon Hallc6358dd2015-04-10 12:44:28 -0700625 if debug:
Jon Hall390696c2015-05-05 17:13:41 -0700626 main.log.debug( self.name + ": parsed and stripped output" )
627 main.log.debug( self.name + ": " + repr( response ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700628
Jon Hall63604932015-02-26 17:09:50 -0800629 # parse for just the output, remove the cmd from response
Jon Hallce0d70b2018-12-11 11:01:32 -0800630 cmdPattern = cmdStr.strip()
631 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
632 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800633 if relaxedRegex:
Jon Hallce0d70b2018-12-11 11:01:32 -0800634 cmdPattern = cmdPattern.split( '|' )[ -1 ].strip()
635 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
636 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800637 # This was added because karaf 4.2 is stripping some characters from the command echo
Jon Hallce0d70b2018-12-11 11:01:32 -0800638 output = response.split( cmdPattern, 1 )
Jon Hall22e94ce2019-01-15 14:52:17 -0800639 if expectJson:
640 main.log.warn( "Relaxed Regex: Searching for a json string amongst the output" )
641 jsonPattern = r'\{.*\}'
642 match = re.search( jsonPattern, output[ 0 ] )
643 if match:
644 output = [ '' , match.group( 0 ) ] # We expect a list with the second element to be the output
Jon Hall39e3ffe2018-12-05 11:40:29 -0800645 if len( output ) < 2:
646 main.log.warn( "Relaxing regex match to last 5 characters of the sent command" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800647 cmdPattern = cmdPattern[ -5: ]
648 main.log.debug( "REGEX PATTERN SET TO: " + repr( cmdPattern ) +
649 "\nSENT COMMAND STRING WAS: " + repr( cmdStr ) )
650 output = response.split( cmdPattern, 1 )
Jon Hall6c9e2da2018-11-06 12:01:23 -0800651 else:
Jon Hallce0d70b2018-12-11 11:01:32 -0800652 output = response.split( cmdPattern, 1 )
653 if len( output ) < 2: # TODO: Should we do this without the relaxedRegex flag?
Jon Hall8c9dd1c2018-11-14 15:40:39 -0800654 main.log.warn( "Relaxing regex match to last 5 characters of the sent command" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800655 output = response.split( cmdPattern[ -5: ], 1 )
Jon Hall0e240372018-05-02 11:21:57 -0700656 if output:
657 if debug:
658 main.log.debug( self.name + ": split output" )
659 for r in output:
660 main.log.debug( self.name + ": " + repr( r ) )
Jon Hallce0d70b2018-12-11 11:01:32 -0800661 if len( output ) == 1:
662 main.log.error( "Could not remove sent command echo from output" )
663 return output
Jon Hall0e240372018-05-02 11:21:57 -0700664 output = output[ 1 ].strip()
GlennRC85870432015-11-23 11:45:51 -0800665 if showResponse:
GlennRCed771242016-01-13 17:02:47 -0800666 main.log.info( "Response from ONOS: {}".format( output ) )
Jon Hall0e240372018-05-02 11:21:57 -0700667 self.clearBuffer( debug=debug, timeout=timeout, noExit=noExit )
GlennRC85870432015-11-23 11:45:51 -0800668 return output
GlennRCed771242016-01-13 17:02:47 -0800669 except pexpect.TIMEOUT:
Jon Hall0e240372018-05-02 11:21:57 -0700670 main.log.error( self.name + ": ONOS timeout" )
GlennRCed771242016-01-13 17:02:47 -0800671 if debug:
Jon Hall3c0114c2020-08-11 15:07:42 -0700672 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
You Wang6b5e5ba2019-01-31 15:32:40 -0800673 self.exitFromCmd( self.karafPrompt, 100 )
GlennRCed771242016-01-13 17:02:47 -0800674 return None
Jon Hallc6358dd2015-04-10 12:44:28 -0700675 except IndexError:
676 main.log.exception( self.name + ": Object not as expected" )
Jon Halla495f562016-05-16 18:03:26 -0700677 main.log.debug( "response: {}".format( repr( response ) ) )
Jon Hallc6358dd2015-04-10 12:44:28 -0700678 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800679 except TypeError:
680 main.log.exception( self.name + ": Object not as expected" )
681 return None
andrewonlaba18f6bf2014-10-13 19:31:54 -0400682 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800683 main.log.error( self.name + ": EOF exception found" )
684 main.log.error( self.name + ": " + self.handle.before )
YPZhangebf9eb52016-05-12 15:20:24 -0700685 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700686 return None
687 else:
Devin Lim44075962017-08-11 10:56:37 -0700688 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800689 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800690 main.log.exception( self.name + ": Uncaught exception!" )
YPZhangebf9eb52016-05-12 15:20:24 -0700691 if noExit:
YPZhangebf9eb52016-05-12 15:20:24 -0700692 return None
693 else:
Devin Lim44075962017-08-11 10:56:37 -0700694 main.cleanAndExit()
andrewonlaba18f6bf2014-10-13 19:31:54 -0400695
Jon Halld5a94fb2018-11-13 14:32:23 -0800696 def lineCount( self, cmdStr, showResponse=False, debug=False, timeout=10, noExit=False, relaxedRegex=True ):
697 """
698 A wrapper around sendline(). Will return the number of lines returned or None on error
699
700 Required Arguments:
701 cmdStr - String to send to the pexpect session
702
703 Optional Arguments:
704 showResponse - Defaults to False. If True will log the response.
705 debug - Defaults to False. If True, will enable debug logging.
706 timeout - Defaults to 10. Amount of time in seconds for a command to return
707 before a timeout.
708 noExit - Defaults to False. If True, will not exit TestON in the event of a
709 closed channel, but instead return None
710 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.
711
712 Warning: There are no sanity checking to commands sent using this method.
713
714 """
715 try:
716 numLines = self.sendline( cmdStr, showResponse, debug, timeout, noExit, relaxedRegex )
You Wang0ce8e0c2019-02-22 12:22:26 -0800717 parsed = re.search( "(\d+)", numLines )
Jon Hall8c9dd1c2018-11-14 15:40:39 -0800718 if not parsed:
719 main.log.error( "Warning, output of karaf's wc may have changed" )
720 return None
721 return parsed.group( 1 )
Jon Halld5a94fb2018-11-13 14:32:23 -0800722 except IndexError:
723 main.log.exception( self.name + ": Object not as expected" )
Jon Hallce0d70b2018-12-11 11:01:32 -0800724 main.log.debug( "response: {}".format( repr( numLines ) ) )
Jon Halld5a94fb2018-11-13 14:32:23 -0800725 return None
726 except TypeError:
727 main.log.exception( self.name + ": Object not as expected" )
728 return None
729 except Exception:
730 main.log.exception( self.name + ": Uncaught exception!" )
731 if noExit:
732 return None
733 else:
734 main.cleanAndExit()
735
kelvin8ec71442015-01-15 16:57:00 -0800736 # IMPORTANT NOTE:
737 # For all cli commands, naming convention should match
kelvin-onlabd3b64892015-01-20 13:26:24 -0800738 # the cli command changing 'a:b' with 'aB'.
739 # Ex ) onos:topology > onosTopology
740 # onos:links > onosLinks
741 # feature:list > featureList
Jon Halle3f39ff2015-01-13 11:50:53 -0800742
kelvin-onlabd3b64892015-01-20 13:26:24 -0800743 def addNode( self, nodeId, ONOSIp, tcpPort="" ):
kelvin8ec71442015-01-15 16:57:00 -0800744 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400745 Adds a new cluster node by ID and address information.
746 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800747 * nodeId
748 * ONOSIp
andrewonlabc2d05aa2014-10-13 16:51:10 -0400749 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800750 * tcpPort
kelvin8ec71442015-01-15 16:57:00 -0800751 """
andrewonlabc2d05aa2014-10-13 16:51:10 -0400752 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800753 cmdStr = "add-node " + str( nodeId ) + " " +\
754 str( ONOSIp ) + " " + str( tcpPort )
755 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700756 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800757 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -0800758 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700759 main.log.error( self.name + ": Error in adding node" )
kelvin8ec71442015-01-15 16:57:00 -0800760 main.log.error( handle )
Jon Halle3f39ff2015-01-13 11:50:53 -0800761 return main.FALSE
andrewonlabc2d05aa2014-10-13 16:51:10 -0400762 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800763 main.log.info( "Node " + str( ONOSIp ) + " added" )
andrewonlabc2d05aa2014-10-13 16:51:10 -0400764 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800765 except AssertionError:
766 main.log.exception( "" )
767 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800768 except TypeError:
769 main.log.exception( self.name + ": Object not as expected" )
770 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400771 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800772 main.log.error( self.name + ": EOF exception found" )
773 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700774 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800775 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800776 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700777 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400778
kelvin-onlabd3b64892015-01-20 13:26:24 -0800779 def removeNode( self, nodeId ):
kelvin8ec71442015-01-15 16:57:00 -0800780 """
andrewonlab86dc3082014-10-13 18:18:38 -0400781 Removes a cluster by ID
782 Issues command: 'remove-node [<node-id>]'
783 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800784 * nodeId
kelvin8ec71442015-01-15 16:57:00 -0800785 """
andrewonlab86dc3082014-10-13 18:18:38 -0400786 try:
andrewonlab86dc3082014-10-13 18:18:38 -0400787
kelvin-onlabd3b64892015-01-20 13:26:24 -0800788 cmdStr = "remove-node " + str( nodeId )
Jon Hall08f61bc2015-04-13 16:00:30 -0700789 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700790 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800791 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700792 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700793 main.log.error( self.name + ": Error in removing node" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700794 main.log.error( handle )
795 return main.FALSE
796 else:
797 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800798 except AssertionError:
799 main.log.exception( "" )
800 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800801 except TypeError:
802 main.log.exception( self.name + ": Object not as expected" )
803 return None
andrewonlab86dc3082014-10-13 18:18:38 -0400804 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800805 main.log.error( self.name + ": EOF exception found" )
806 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700807 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800808 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800809 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700810 main.cleanAndExit()
andrewonlabc2d05aa2014-10-13 16:51:10 -0400811
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700812 def nodes( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -0800813 """
andrewonlab7c211572014-10-15 16:45:20 -0400814 List the nodes currently visible
815 Issues command: 'nodes'
Jon Hall61282e32015-03-19 11:34:11 -0700816 Optional argument:
817 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800818 """
andrewonlab7c211572014-10-15 16:45:20 -0400819 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700820 cmdStr = "nodes"
Jon Hall61282e32015-03-19 11:34:11 -0700821 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700822 cmdStr += " -j"
823 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700824 assert output is not None, "Error in sendline"
Jon Halle37bd1f2020-09-10 12:16:41 -0700825 # "Command not found" or "Service org.onosproject.security.AuditService not found"
826 assert "not found" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -0700827 return output
Jon Hallc6793552016-01-19 14:18:37 -0800828 except AssertionError:
829 main.log.exception( "" )
830 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800831 except TypeError:
832 main.log.exception( self.name + ": Object not as expected" )
833 return None
andrewonlab7c211572014-10-15 16:45:20 -0400834 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800835 main.log.error( self.name + ": EOF exception found" )
836 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700837 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800838 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800839 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700840 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400841
kelvin8ec71442015-01-15 16:57:00 -0800842 def topology( self ):
843 """
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700844 Definition:
Jon Hall390696c2015-05-05 17:13:41 -0700845 Returns the output of topology command.
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700846 Return:
847 topology = current ONOS topology
kelvin8ec71442015-01-15 16:57:00 -0800848 """
andrewonlab95ce8322014-10-13 14:12:04 -0400849 try:
Hari Krishnaef1bd4e2015-03-12 16:55:30 -0700850 cmdStr = "topology -j"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800851 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800852 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800853 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700854 main.log.info( cmdStr + " returned: " + str( handle ) )
andrewonlab95ce8322014-10-13 14:12:04 -0400855 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800856 except AssertionError:
857 main.log.exception( "" )
Jon Halld4d4b372015-01-28 16:02:41 -0800858 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800859 except TypeError:
860 main.log.exception( self.name + ": Object not as expected" )
861 return None
andrewonlabc2d05aa2014-10-13 16:51:10 -0400862 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800863 main.log.error( self.name + ": EOF exception found" )
864 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700865 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800866 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800867 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700868 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -0800869
jenkins7ead5a82015-03-13 10:28:21 -0700870 def deviceRemove( self, deviceId ):
871 """
872 Removes particular device from storage
873
874 TODO: refactor this function
875 """
876 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700877 cmdStr = "device-remove " + str( deviceId )
878 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800879 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800880 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700881 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700882 main.log.error( self.name + ": Error in removing device" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700883 main.log.error( handle )
884 return main.FALSE
885 else:
886 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800887 except AssertionError:
888 main.log.exception( "" )
889 return None
jenkins7ead5a82015-03-13 10:28:21 -0700890 except TypeError:
891 main.log.exception( self.name + ": Object not as expected" )
892 return None
893 except pexpect.EOF:
894 main.log.error( self.name + ": EOF exception found" )
895 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700896 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700897 except Exception:
898 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700899 main.cleanAndExit()
jenkins7ead5a82015-03-13 10:28:21 -0700900
You Wang3b9689a2018-08-30 12:24:00 -0700901 def devices( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -0800902 """
Jon Hall7b02d952014-10-17 20:14:54 -0400903 Lists all infrastructure devices or switches
andrewonlab86dc3082014-10-13 18:18:38 -0400904 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800905 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -0800906 """
andrewonlab86dc3082014-10-13 18:18:38 -0400907 try:
Jon Hallc6358dd2015-04-10 12:44:28 -0700908 cmdStr = "devices"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800909 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -0700910 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -0700911 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -0800912 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800913 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700914 return handle
Jon Hallc6793552016-01-19 14:18:37 -0800915 except AssertionError:
916 main.log.exception( "" )
917 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800918 except TypeError:
919 main.log.exception( self.name + ": Object not as expected" )
920 return None
andrewonlab7c211572014-10-15 16:45:20 -0400921 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800922 main.log.error( self.name + ": EOF exception found" )
923 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700924 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800925 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800926 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700927 main.cleanAndExit()
andrewonlab7c211572014-10-15 16:45:20 -0400928
kelvin-onlabd3b64892015-01-20 13:26:24 -0800929 def balanceMasters( self ):
kelvin8ec71442015-01-15 16:57:00 -0800930 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800931 This balances the devices across all controllers
932 by issuing command: 'onos> onos:balance-masters'
933 If required this could be extended to return devices balanced output.
kelvin8ec71442015-01-15 16:57:00 -0800934 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800935 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800936 cmdStr = "onos:balance-masters"
Jon Hallc6358dd2015-04-10 12:44:28 -0700937 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -0800938 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800939 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -0700940 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -0700941 main.log.error( self.name + ": Error in balancing masters" )
Jon Hallc6358dd2015-04-10 12:44:28 -0700942 main.log.error( handle )
943 return main.FALSE
944 else:
945 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -0800946 except AssertionError:
947 main.log.exception( "" )
948 return None
Jon Halld4d4b372015-01-28 16:02:41 -0800949 except TypeError:
950 main.log.exception( self.name + ": Object not as expected" )
951 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800952 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800953 main.log.error( self.name + ": EOF exception found" )
954 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700955 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800956 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -0800957 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700958 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -0800959
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000960 def checkMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700961 """
962 Returns the output of the masters command.
963 Optional argument:
964 * jsonFormat - boolean indicating if you want output in json
965 """
966 try:
967 cmdStr = "onos:masters"
968 if jsonFormat:
969 cmdStr += " -j"
970 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -0700971 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -0800972 assert "Command not found:" not in output, output
acsmars24950022015-07-30 18:00:43 -0700973 return output
Jon Hallc6793552016-01-19 14:18:37 -0800974 except AssertionError:
975 main.log.exception( "" )
976 return None
acsmars24950022015-07-30 18:00:43 -0700977 except TypeError:
978 main.log.exception( self.name + ": Object not as expected" )
979 return None
980 except pexpect.EOF:
981 main.log.error( self.name + ": EOF exception found" )
982 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700983 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700984 except Exception:
985 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700986 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -0700987
Jon Hallc6793552016-01-19 14:18:37 -0800988 def checkBalanceMasters( self, jsonFormat=True ):
acsmars24950022015-07-30 18:00:43 -0700989 """
990 Uses the master command to check that the devices' leadership
991 is evenly divided
992
993 Dependencies: checkMasters() and summary()
994
Jon Hall6509dbf2016-06-21 17:01:17 -0700995 Returns main.TRUE if the devices are balanced
996 Returns main.FALSE if the devices are unbalanced
acsmars24950022015-07-30 18:00:43 -0700997 Exits on Exception
998 Returns None on TypeError
999 """
1000 try:
Jon Hallc6793552016-01-19 14:18:37 -08001001 summaryOutput = self.summary()
1002 totalDevices = json.loads( summaryOutput )[ "devices" ]
1003 except ( TypeError, ValueError ):
1004 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summaryOutput ) )
1005 return None
1006 try:
acsmars24950022015-07-30 18:00:43 -07001007 totalOwnedDevices = 0
Jon Hallc6793552016-01-19 14:18:37 -08001008 mastersOutput = self.checkMasters()
1009 masters = json.loads( mastersOutput )
acsmars24950022015-07-30 18:00:43 -07001010 first = masters[ 0 ][ "size" ]
1011 for master in masters:
1012 totalOwnedDevices += master[ "size" ]
1013 if master[ "size" ] > first + 1 or master[ "size" ] < first - 1:
1014 main.log.error( "Mastership not balanced" )
1015 main.log.info( "\n" + self.checkMasters( False ) )
1016 return main.FALSE
Jon Halle0f0b342017-04-18 11:43:47 -07001017 main.log.info( "Mastership balanced between " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001018 str( len( masters ) ) + " masters" )
acsmars24950022015-07-30 18:00:43 -07001019 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08001020 except ( TypeError, ValueError ):
1021 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, mastersOutput ) )
acsmars24950022015-07-30 18:00:43 -07001022 return None
1023 except pexpect.EOF:
1024 main.log.error( self.name + ": EOF exception found" )
1025 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001026 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -07001027 except Exception:
1028 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001029 main.cleanAndExit()
acsmars24950022015-07-30 18:00:43 -07001030
YPZhangfebf7302016-05-24 16:45:56 -07001031 def links( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -08001032 """
Jon Halle8217482014-10-17 13:49:14 -04001033 Lists all core links
1034 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001035 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001036 """
Jon Halle8217482014-10-17 13:49:14 -04001037 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001038 cmdStr = "links"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001039 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001040 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07001041 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001042 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001043 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001044 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001045 except AssertionError:
1046 main.log.exception( "" )
1047 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001048 except TypeError:
1049 main.log.exception( self.name + ": Object not as expected" )
1050 return None
Jon Halle8217482014-10-17 13:49:14 -04001051 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001052 main.log.error( self.name + ": EOF exception found" )
1053 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001054 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001055 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001056 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001057 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001058
You Wang3b9689a2018-08-30 12:24:00 -07001059 def ports( self, jsonFormat=True, timeout=30 ):
kelvin8ec71442015-01-15 16:57:00 -08001060 """
Jon Halle8217482014-10-17 13:49:14 -04001061 Lists all ports
1062 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001063 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001064 """
Jon Halle8217482014-10-17 13:49:14 -04001065 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001066 cmdStr = "ports"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001067 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001068 cmdStr += " -j"
You Wang3b9689a2018-08-30 12:24:00 -07001069 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08001070 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001071 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001072 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001073 except AssertionError:
1074 main.log.exception( "" )
1075 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001076 except TypeError:
1077 main.log.exception( self.name + ": Object not as expected" )
1078 return None
Jon Halle8217482014-10-17 13:49:14 -04001079 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001080 main.log.error( self.name + ": EOF exception found" )
1081 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001082 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001083 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001084 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001085 main.cleanAndExit()
Jon Halle8217482014-10-17 13:49:14 -04001086
kelvin-onlabd3b64892015-01-20 13:26:24 -08001087 def roles( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001088 """
Jon Hall983a1702014-10-28 18:44:22 -04001089 Lists all devices and the controllers with roles assigned to them
1090 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001091 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001092 """
andrewonlab7c211572014-10-15 16:45:20 -04001093 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001094 cmdStr = "roles"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001095 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001096 cmdStr += " -j"
1097 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001098 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001099 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001100 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001101 except AssertionError:
1102 main.log.exception( "" )
1103 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001104 except TypeError:
1105 main.log.exception( self.name + ": Object not as expected" )
1106 return None
Jon Hall983a1702014-10-28 18:44:22 -04001107 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001108 main.log.error( self.name + ": EOF exception found" )
1109 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001110 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001111 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001112 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001113 main.cleanAndExit()
Jon Hall983a1702014-10-28 18:44:22 -04001114
kelvin-onlabd3b64892015-01-20 13:26:24 -08001115 def getRole( self, deviceId ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08001116 """
Jon Halle3f39ff2015-01-13 11:50:53 -08001117 Given the a string containing the json representation of the "roles"
1118 cli command and a partial or whole device id, returns a json object
1119 containing the roles output for the first device whose id contains
1120 "device_id"
Jon Hall983a1702014-10-28 18:44:22 -04001121
1122 Returns:
Jon Halle3f39ff2015-01-13 11:50:53 -08001123 A dict of the role assignments for the given device or
1124 None if no match
kelvin8ec71442015-01-15 16:57:00 -08001125 """
Jon Hall983a1702014-10-28 18:44:22 -04001126 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001127 if deviceId is None:
Jon Hall983a1702014-10-28 18:44:22 -04001128 return None
1129 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001130 rawRoles = self.roles()
1131 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001132 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001133 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001134 # print device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001135 if str( deviceId ) in device[ 'id' ]:
Jon Hall983a1702014-10-28 18:44:22 -04001136 return device
1137 return None
Jon Hallc6793552016-01-19 14:18:37 -08001138 except ( TypeError, ValueError ):
1139 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001140 return None
andrewonlab86dc3082014-10-13 18:18:38 -04001141 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001142 main.log.error( self.name + ": EOF exception found" )
1143 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001144 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001145 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001146 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001147 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001148
kelvin-onlabd3b64892015-01-20 13:26:24 -08001149 def rolesNotNull( self ):
kelvin8ec71442015-01-15 16:57:00 -08001150 """
Jon Hall94fd0472014-12-08 11:52:42 -08001151 Iterates through each device and checks if there is a master assigned
1152 Returns: main.TRUE if each device has a master
1153 main.FALSE any device has no master
kelvin8ec71442015-01-15 16:57:00 -08001154 """
Jon Hall94fd0472014-12-08 11:52:42 -08001155 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001156 rawRoles = self.roles()
1157 rolesJson = json.loads( rawRoles )
kelvin8ec71442015-01-15 16:57:00 -08001158 # search json for the device with id then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001159 for device in rolesJson:
kelvin8ec71442015-01-15 16:57:00 -08001160 # print device
1161 if device[ 'master' ] == "none":
1162 main.log.warn( "Device has no master: " + str( device ) )
Jon Hall94fd0472014-12-08 11:52:42 -08001163 return main.FALSE
1164 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08001165 except ( TypeError, ValueError ):
1166 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawRoles ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001167 return None
Jon Hall94fd0472014-12-08 11:52:42 -08001168 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001169 main.log.error( self.name + ": EOF exception found" )
1170 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001171 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001172 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001173 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001174 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001175
kelvin-onlabd3b64892015-01-20 13:26:24 -08001176 def paths( self, srcId, dstId ):
kelvin8ec71442015-01-15 16:57:00 -08001177 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001178 Returns string of paths, and the cost.
1179 Issues command: onos:paths <src> <dst>
kelvin8ec71442015-01-15 16:57:00 -08001180 """
andrewonlab3e15ead2014-10-15 14:21:34 -04001181 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001182 cmdStr = "onos:paths " + str( srcId ) + " " + str( dstId )
1183 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001184 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001185 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08001186 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001187 main.log.error( self.name + ": Error in getting paths" )
kelvin8ec71442015-01-15 16:57:00 -08001188 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001189 else:
kelvin8ec71442015-01-15 16:57:00 -08001190 path = handle.split( ";" )[ 0 ]
1191 cost = handle.split( ";" )[ 1 ]
1192 return ( path, cost )
Jon Hallc6793552016-01-19 14:18:37 -08001193 except AssertionError:
1194 main.log.exception( "" )
1195 return ( handle, "Error" )
Jon Halld4d4b372015-01-28 16:02:41 -08001196 except TypeError:
1197 main.log.exception( self.name + ": Object not as expected" )
1198 return ( handle, "Error" )
andrewonlab3e15ead2014-10-15 14:21:34 -04001199 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001200 main.log.error( self.name + ": EOF exception found" )
1201 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001202 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001203 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001204 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001205 main.cleanAndExit()
Jon Hallffb386d2014-11-21 13:43:38 -08001206
kelvin-onlabd3b64892015-01-20 13:26:24 -08001207 def hosts( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08001208 """
Jon Hallffb386d2014-11-21 13:43:38 -08001209 Lists all discovered hosts
Jon Hall42db6dc2014-10-24 19:03:48 -04001210 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001211 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08001212 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001213 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07001214 cmdStr = "hosts"
kelvin-onlabd3b64892015-01-20 13:26:24 -08001215 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07001216 cmdStr += " -j"
1217 handle = self.sendline( cmdStr )
Jeremyd9e4eb12016-04-13 12:09:06 -07001218 if handle:
1219 assert "Command not found:" not in handle, handle
Jon Hallbaf53162015-12-17 17:04:34 -08001220 # TODO: Maybe make this less hardcoded
1221 # ConsistentMap Exceptions
1222 assert "org.onosproject.store.service" not in handle
1223 # Node not leader
1224 assert "java.lang.IllegalStateException" not in handle
Jon Hallc6358dd2015-04-10 12:44:28 -07001225 return handle
Jon Hallc6793552016-01-19 14:18:37 -08001226 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07001227 main.log.exception( self.name + ": Error in processing '" + cmdStr + "' " +
Jeremy Songster6949cea2016-04-19 18:13:18 -07001228 "command: " + str( handle ) )
Jon Hallc6793552016-01-19 14:18:37 -08001229 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001230 except TypeError:
1231 main.log.exception( self.name + ": Object not as expected" )
1232 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001233 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001234 main.log.error( self.name + ": EOF exception found" )
1235 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001236 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001237 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001238 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001239 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001240
kelvin-onlabd3b64892015-01-20 13:26:24 -08001241 def getHost( self, mac ):
kelvin8ec71442015-01-15 16:57:00 -08001242 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001243 Return the first host from the hosts api whose 'id' contains 'mac'
Jon Halle3f39ff2015-01-13 11:50:53 -08001244
Jon Hallefbd9792015-03-05 16:11:36 -08001245 Note: mac must be a colon separated mac address, but could be a
Jon Halle3f39ff2015-01-13 11:50:53 -08001246 partial mac address
1247
Jon Hall42db6dc2014-10-24 19:03:48 -04001248 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08001249 """
Jon Hall42db6dc2014-10-24 19:03:48 -04001250 try:
kelvin8ec71442015-01-15 16:57:00 -08001251 if mac is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04001252 return None
1253 else:
1254 mac = mac
kelvin-onlabd3b64892015-01-20 13:26:24 -08001255 rawHosts = self.hosts()
1256 hostsJson = json.loads( rawHosts )
kelvin8ec71442015-01-15 16:57:00 -08001257 # search json for the host with mac then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08001258 for host in hostsJson:
kelvin8ec71442015-01-15 16:57:00 -08001259 # print "%s in %s?" % ( mac, host[ 'id' ] )
Jon Halld4d4b372015-01-28 16:02:41 -08001260 if not host:
1261 pass
1262 elif mac in host[ 'id' ]:
Jon Hall42db6dc2014-10-24 19:03:48 -04001263 return host
1264 return None
Jon Hallc6793552016-01-19 14:18:37 -08001265 except ( TypeError, ValueError ):
1266 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawHosts ) )
Jon Halld4d4b372015-01-28 16:02:41 -08001267 return None
Jon Hall42db6dc2014-10-24 19:03:48 -04001268 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001269 main.log.error( self.name + ": EOF exception found" )
1270 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001271 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001272 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001273 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001274 main.cleanAndExit()
Jon Hall42db6dc2014-10-24 19:03:48 -04001275
kelvin-onlabd3b64892015-01-20 13:26:24 -08001276 def getHostsId( self, hostList ):
kelvin8ec71442015-01-15 16:57:00 -08001277 """
1278 Obtain list of hosts
andrewonlab3f0a4af2014-10-17 12:25:14 -04001279 Issues command: 'onos> hosts'
kelvin8ec71442015-01-15 16:57:00 -08001280
andrewonlab3f0a4af2014-10-17 12:25:14 -04001281 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001282 * hostList: List of hosts obtained by Mininet
andrewonlab3f0a4af2014-10-17 12:25:14 -04001283 IMPORTANT:
1284 This function assumes that you started your
kelvin8ec71442015-01-15 16:57:00 -08001285 topology with the option '--mac'.
andrewonlab3f0a4af2014-10-17 12:25:14 -04001286 Furthermore, it assumes that value of VLAN is '-1'
1287 Description:
kelvin8ec71442015-01-15 16:57:00 -08001288 Converts mininet hosts ( h1, h2, h3... ) into
1289 ONOS format ( 00:00:00:00:00:01/-1 , ... )
1290 """
andrewonlab3f0a4af2014-10-17 12:25:14 -04001291 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001292 onosHostList = []
andrewonlab3f0a4af2014-10-17 12:25:14 -04001293
kelvin-onlabd3b64892015-01-20 13:26:24 -08001294 for host in hostList:
kelvin8ec71442015-01-15 16:57:00 -08001295 host = host.replace( "h", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001296 hostHex = hex( int( host ) ).zfill( 12 )
1297 hostHex = str( hostHex ).replace( 'x', '0' )
1298 i = iter( str( hostHex ) )
1299 hostHex = ":".join( a + b for a, b in zip( i, i ) )
1300 hostHex = hostHex + "/-1"
1301 onosHostList.append( hostHex )
andrewonlab3f0a4af2014-10-17 12:25:14 -04001302
kelvin-onlabd3b64892015-01-20 13:26:24 -08001303 return onosHostList
andrewonlab3f0a4af2014-10-17 12:25:14 -04001304
Jon Halld4d4b372015-01-28 16:02:41 -08001305 except TypeError:
1306 main.log.exception( self.name + ": Object not as expected" )
1307 return None
andrewonlab3f0a4af2014-10-17 12:25:14 -04001308 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001309 main.log.error( self.name + ": EOF exception found" )
1310 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001311 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001312 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001313 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001314 main.cleanAndExit()
andrewonlab3e15ead2014-10-15 14:21:34 -04001315
You Wangbc898b82018-05-03 16:22:34 -07001316 def verifyHostLocation( self, hostIp, location ):
1317 """
1318 Description:
1319 Verify the host given is discovered in all locations expected
1320 Required:
1321 hostIp: IP address of the host
1322 location: expected location(s) of the given host. ex. "of:0000000000000005/8"
1323 Could be a string or list
1324 Returns:
1325 main.TRUE if host is discovered on all locations provided
1326 main.FALSE otherwise
1327 """
You Wangbc898b82018-05-03 16:22:34 -07001328 locations = [ location ] if isinstance( location, str ) else location
1329 assert isinstance( locations, list ), "Wrong type of location: {}".format( type( location ) )
1330 try:
1331 hosts = self.hosts()
1332 hosts = json.loads( hosts )
1333 targetHost = None
1334 for host in hosts:
1335 if hostIp in host[ "ipAddresses" ]:
1336 targetHost = host
You Wangfd80ab42018-05-10 17:21:53 -07001337 assert targetHost, "Not able to find host with IP {}".format( hostIp )
You Wangbc898b82018-05-03 16:22:34 -07001338 result = main.TRUE
1339 locationsDiscovered = [ loc[ "elementId" ] + "/" + loc[ "port" ] for loc in targetHost[ "locations" ] ]
1340 for loc in locations:
1341 discovered = False
1342 for locDiscovered in locationsDiscovered:
You Wang547893e2018-05-08 13:34:59 -07001343 locToMatch = locDiscovered if "/" in loc else locDiscovered.split( "/" )[0]
1344 if loc == locToMatch:
You Wangbc898b82018-05-03 16:22:34 -07001345 main.log.debug( "Host {} discovered with location {}".format( hostIp, loc ) )
You Wang547893e2018-05-08 13:34:59 -07001346 discovered = True
You Wangbc898b82018-05-03 16:22:34 -07001347 break
1348 if discovered:
1349 locationsDiscovered.remove( locDiscovered )
1350 else:
1351 main.log.warn( "Host {} not discovered with location {}".format( hostIp, loc ) )
1352 result = main.FALSE
1353 if locationsDiscovered:
1354 main.log.warn( "Host {} is also discovered with location {}".format( hostIp, locationsDiscovered ) )
1355 result = main.FALSE
1356 return result
1357 except KeyError:
1358 main.log.exception( self.name + ": host data not as expected: " + hosts )
1359 return None
1360 except pexpect.EOF:
1361 main.log.error( self.name + ": EOF exception found" )
1362 main.log.error( self.name + ": " + self.handle.before )
1363 main.cleanAndExit()
1364 except Exception:
1365 main.log.exception( self.name + ": Uncaught exception" )
1366 return None
1367
Siddesh715a9192021-11-03 19:51:20 +00001368 def verifyHostIp( self, hostList=[], prefix="", prefixLength=24 ):
You Wang53dba1e2018-02-02 17:45:44 -08001369 """
1370 Description:
1371 Verify that all hosts have IP address assigned to them
1372 Optional:
1373 hostList: If specified, verifications only happen to the hosts
1374 in hostList
1375 prefix: at least one of the ip address assigned to the host
1376 needs to have the specified prefix
1377 Returns:
1378 main.TRUE if all hosts have specific IP address assigned;
1379 main.FALSE otherwise
1380 """
You Wang53dba1e2018-02-02 17:45:44 -08001381 try:
1382 hosts = self.hosts()
Siddesh715a9192021-11-03 19:51:20 +00001383 hosts = json.loads( hosts, "utf-8" )
You Wang53dba1e2018-02-02 17:45:44 -08001384 if not hostList:
1385 hostList = [ host[ "id" ] for host in hosts ]
Siddesh715a9192021-11-03 19:51:20 +00001386 hostList = [ str( h.lower() ) for h in hostList ]
You Wang53dba1e2018-02-02 17:45:44 -08001387 for host in hosts:
1388 hostId = host[ "id" ]
Siddesh715a9192021-11-03 19:51:20 +00001389 hostId = str( hostId.lower() )
1390 match = False
1391 for onosHostId in hostList:
1392 if onosHostId == hostId:
1393 match = True
1394 if not match:
You Wang53dba1e2018-02-02 17:45:44 -08001395 continue
1396 ipList = host[ "ipAddresses" ]
1397 main.log.debug( self.name + ": IP list on host " + str( hostId ) + ": " + str( ipList ) )
1398 if not ipList:
1399 main.log.warn( self.name + ": Failed to discover any IP addresses on host " + str( hostId ) )
1400 else:
Siddesh715a9192021-11-03 19:51:20 +00001401 # if no hostIp in subnet: Get warning otherwise remove hostId from hostList
1402 subnetString = u"%s/%s" % (prefix, prefixLength)
1403 subnet = ipaddress.ip_network( subnetString, strict=False )
1404 if not any( ipaddress.ip_address( ip ) in subnet for ip in ipList ):
You Wang53dba1e2018-02-02 17:45:44 -08001405 main.log.warn( self.name + ": None of the IPs on host " + str( hostId ) + " has prefix " + str( prefix ) )
1406 else:
1407 main.log.debug( self.name + ": Found matching IP on host " + str( hostId ) )
1408 hostList.remove( hostId )
1409 if hostList:
1410 main.log.warn( self.name + ": failed to verify IP on following hosts: " + str( hostList) )
Jon Hall43060f62020-06-23 13:13:33 -07001411 # Print info for debugging
1412 main.log.debug( self.name + ": hosts output: " + str( hosts ) )
You Wang53dba1e2018-02-02 17:45:44 -08001413 return main.FALSE
1414 else:
1415 return main.TRUE
1416 except KeyError:
1417 main.log.exception( self.name + ": host data not as expected: " + hosts )
1418 return None
1419 except pexpect.EOF:
1420 main.log.error( self.name + ": EOF exception found" )
1421 main.log.error( self.name + ": " + self.handle.before )
1422 main.cleanAndExit()
1423 except Exception:
1424 main.log.exception( self.name + ": Uncaught exception" )
1425 return None
1426
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001427 def addHostIntent( self, hostIdOne, hostIdTwo, vlanId="", setVlan="", encap="", bandwidth="" ):
kelvin8ec71442015-01-15 16:57:00 -08001428 """
andrewonlabe6745342014-10-17 14:29:13 -04001429 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001430 * hostIdOne: ONOS host id for host1
1431 * hostIdTwo: ONOS host id for host2
Jeremy Songster832f9e92016-05-05 14:30:49 -07001432 Optional:
1433 * vlanId: specify a VLAN id for the intent
Jeremy Songsterff553672016-05-12 17:06:23 -07001434 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001435 * encap: specify an encapsulation type
andrewonlabe6745342014-10-17 14:29:13 -04001436 Description:
Jon Hallefbd9792015-03-05 16:11:36 -08001437 Adds a host-to-host intent ( bidirectional ) by
Jon Hallb1290e82014-11-18 16:17:48 -05001438 specifying the two hosts.
kelvin-onlabfb521662015-02-27 09:52:40 -08001439 Returns:
1440 A string of the intent id or None on Error
kelvin8ec71442015-01-15 16:57:00 -08001441 """
andrewonlabe6745342014-10-17 14:29:13 -04001442 try:
Jeremy Songster832f9e92016-05-05 14:30:49 -07001443 cmdStr = "add-host-intent "
1444 if vlanId:
1445 cmdStr += "-v " + str( vlanId ) + " "
Jeremy Songsterff553672016-05-12 17:06:23 -07001446 if setVlan:
1447 cmdStr += "--setVlan " + str( vlanId ) + " "
Jeremy Songsterc032f162016-08-04 17:14:49 -07001448 if encap:
1449 cmdStr += "--encapsulation " + str( encap ) + " "
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07001450 if bandwidth:
1451 cmdStr += "-b " + str( bandwidth ) + " "
Jeremy Songster832f9e92016-05-05 14:30:49 -07001452 cmdStr += str( hostIdOne ) + " " + str( hostIdTwo )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001453 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001454 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001455 assert "Command not found:" not in handle, handle
Hari Krishnaac4e1782015-01-26 12:09:12 -08001456 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001457 main.log.error( self.name + ": Error in adding Host intent" )
Jon Hall61282e32015-03-19 11:34:11 -07001458 main.log.debug( "Response from ONOS was: " + repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001459 return None
Hari Krishnaac4e1782015-01-26 12:09:12 -08001460 else:
1461 main.log.info( "Host intent installed between " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001462 str( hostIdOne ) + " and " + str( hostIdTwo ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001463 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001464 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001465 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001466 else:
1467 main.log.error( "Error, intent ID not found" )
Jon Hall61282e32015-03-19 11:34:11 -07001468 main.log.debug( "Response from ONOS was: " +
1469 repr( handle ) )
kelvin-onlabfb521662015-02-27 09:52:40 -08001470 return None
Jon Hallc6793552016-01-19 14:18:37 -08001471 except AssertionError:
1472 main.log.exception( "" )
1473 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001474 except TypeError:
1475 main.log.exception( self.name + ": Object not as expected" )
1476 return None
andrewonlabe6745342014-10-17 14:29:13 -04001477 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001478 main.log.error( self.name + ": EOF exception found" )
1479 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001480 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001481 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001482 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001483 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04001484
kelvin-onlabd3b64892015-01-20 13:26:24 -08001485 def addOpticalIntent( self, ingressDevice, egressDevice ):
kelvin8ec71442015-01-15 16:57:00 -08001486 """
andrewonlab7b31d232014-10-24 13:31:47 -04001487 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001488 * ingressDevice: device id of ingress device
1489 * egressDevice: device id of egress device
andrewonlab7b31d232014-10-24 13:31:47 -04001490 Optional:
1491 TODO: Still needs to be implemented via dev side
kelvin-onlabfb521662015-02-27 09:52:40 -08001492 Description:
1493 Adds an optical intent by specifying an ingress and egress device
1494 Returns:
1495 A string of the intent id or None on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08001496 """
andrewonlab7b31d232014-10-24 13:31:47 -04001497 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001498 cmdStr = "add-optical-intent " + str( ingressDevice ) +\
1499 " " + str( egressDevice )
1500 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08001501 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001502 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08001503 # If error, return error message
Jon Halle3f39ff2015-01-13 11:50:53 -08001504 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001505 main.log.error( self.name + ": Error in adding Optical intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001506 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001507 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001508 main.log.info( "Optical intent installed between " +
1509 str( ingressDevice ) + " and " +
1510 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001511 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001512 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001513 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001514 else:
1515 main.log.error( "Error, intent ID not found" )
1516 return None
Jon Hallc6793552016-01-19 14:18:37 -08001517 except AssertionError:
1518 main.log.exception( "" )
1519 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001520 except TypeError:
1521 main.log.exception( self.name + ": Object not as expected" )
1522 return None
andrewonlab7b31d232014-10-24 13:31:47 -04001523 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001524 main.log.error( self.name + ": EOF exception found" )
1525 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001526 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001527 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001528 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001529 main.cleanAndExit()
andrewonlab7b31d232014-10-24 13:31:47 -04001530
kelvin-onlabd3b64892015-01-20 13:26:24 -08001531 def addPointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001532 self,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001533 ingressDevice,
1534 egressDevice,
1535 portIngress="",
1536 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001537 ethType="",
1538 ethSrc="",
1539 ethDst="",
1540 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001541 lambdaAlloc=False,
alisonda157272016-12-22 01:13:21 -08001542 protected=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001543 ipProto="",
1544 ipSrc="",
1545 ipDst="",
1546 tcpSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001547 tcpDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001548 vlanId="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001549 setVlan="",
1550 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001551 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001552 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001553 * ingressDevice: device id of ingress device
1554 * egressDevice: device id of egress device
andrewonlab289e4b72014-10-21 21:24:18 -04001555 Optional:
1556 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001557 * ethSrc: specify ethSrc ( i.e. src mac addr )
1558 * ethDst: specify ethDst ( i.e. dst mac addr )
andrewonlab0dbb6ec2014-11-06 13:46:55 -05001559 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001560 * lambdaAlloc: if True, intent will allocate lambda
andrewonlab40ccd8b2014-11-06 16:23:34 -05001561 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001562 * ipProto: specify ip protocol
andrewonlabf77e0cb2014-11-11 17:17:59 -05001563 * ipSrc: specify ip source address
1564 * ipDst: specify ip destination address
1565 * tcpSrc: specify tcp source port
1566 * tcpDst: specify tcp destination port
Jeremy Songster832f9e92016-05-05 14:30:49 -07001567 * vlanId: specify vlan ID
Jeremy Songsterff553672016-05-12 17:06:23 -07001568 * setVlan: specify a VLAN id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001569 * encap: specify an Encapsulation type to use
andrewonlab4dbb4d82014-10-17 18:22:31 -04001570 Description:
kelvin8ec71442015-01-15 16:57:00 -08001571 Adds a point-to-point intent ( uni-directional ) by
andrewonlab289e4b72014-10-21 21:24:18 -04001572 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001573 Returns:
1574 A string of the intent id or None on error
andrewonlab289e4b72014-10-21 21:24:18 -04001575
Jon Halle3f39ff2015-01-13 11:50:53 -08001576 NOTE: This function may change depending on the
andrewonlab4dbb4d82014-10-17 18:22:31 -04001577 options developers provide for point-to-point
1578 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001579 """
andrewonlab4dbb4d82014-10-17 18:22:31 -04001580 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001581 cmd = "add-point-intent"
andrewonlab36af3822014-11-18 17:48:18 -05001582
Jeremy Songsterff553672016-05-12 17:06:23 -07001583 if ethType:
1584 cmd += " --ethType " + str( ethType )
1585 if ethSrc:
1586 cmd += " --ethSrc " + str( ethSrc )
1587 if ethDst:
1588 cmd += " --ethDst " + str( ethDst )
1589 if bandwidth:
1590 cmd += " --bandwidth " + str( bandwidth )
1591 if lambdaAlloc:
1592 cmd += " --lambda "
1593 if ipProto:
1594 cmd += " --ipProto " + str( ipProto )
1595 if ipSrc:
1596 cmd += " --ipSrc " + str( ipSrc )
1597 if ipDst:
1598 cmd += " --ipDst " + str( ipDst )
1599 if tcpSrc:
1600 cmd += " --tcpSrc " + str( tcpSrc )
1601 if tcpDst:
1602 cmd += " --tcpDst " + str( tcpDst )
1603 if vlanId:
1604 cmd += " -v " + str( vlanId )
1605 if setVlan:
1606 cmd += " --setVlan " + str( setVlan )
Jeremy Songsterc032f162016-08-04 17:14:49 -07001607 if encap:
1608 cmd += " --encapsulation " + str( encap )
alisonda157272016-12-22 01:13:21 -08001609 if protected:
1610 cmd += " --protect "
andrewonlab289e4b72014-10-21 21:24:18 -04001611
kelvin8ec71442015-01-15 16:57:00 -08001612 # Check whether the user appended the port
1613 # or provided it as an input
kelvin-onlabd3b64892015-01-20 13:26:24 -08001614 if "/" in ingressDevice:
1615 cmd += " " + str( ingressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001616 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001617 if not portIngress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001618 main.log.error( "You must specify the ingress port" )
kelvin8ec71442015-01-15 16:57:00 -08001619 # TODO: perhaps more meaningful return
kelvin-onlabfb521662015-02-27 09:52:40 -08001620 # Would it make sense to throw an exception and exit
1621 # the test?
1622 return None
andrewonlab36af3822014-11-18 17:48:18 -05001623
kelvin8ec71442015-01-15 16:57:00 -08001624 cmd += " " + \
kelvin-onlabd3b64892015-01-20 13:26:24 -08001625 str( ingressDevice ) + "/" +\
1626 str( portIngress ) + " "
andrewonlab36af3822014-11-18 17:48:18 -05001627
kelvin-onlabd3b64892015-01-20 13:26:24 -08001628 if "/" in egressDevice:
1629 cmd += " " + str( egressDevice )
andrewonlab36af3822014-11-18 17:48:18 -05001630 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001631 if not portEgress:
kelvin-onlabfb521662015-02-27 09:52:40 -08001632 main.log.error( "You must specify the egress port" )
1633 return None
Jon Halle3f39ff2015-01-13 11:50:53 -08001634
kelvin8ec71442015-01-15 16:57:00 -08001635 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001636 str( egressDevice ) + "/" +\
1637 str( portEgress )
kelvin8ec71442015-01-15 16:57:00 -08001638
kelvin-onlab898a6c62015-01-16 14:13:53 -08001639 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001640 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001641 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001642 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001643 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001644 main.log.error( self.name + ": Error in adding point-to-point intent" )
kelvin-onlabfb521662015-02-27 09:52:40 -08001645 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001646 else:
kelvin-onlabfb521662015-02-27 09:52:40 -08001647 # TODO: print out all the options in this message?
1648 main.log.info( "Point-to-point intent installed between " +
1649 str( ingressDevice ) + " and " +
1650 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001651 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabfb521662015-02-27 09:52:40 -08001652 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001653 return match.group()[ 3:-1 ]
kelvin-onlabfb521662015-02-27 09:52:40 -08001654 else:
1655 main.log.error( "Error, intent ID not found" )
1656 return None
Jon Hallc6793552016-01-19 14:18:37 -08001657 except AssertionError:
1658 main.log.exception( "" )
1659 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001660 except TypeError:
1661 main.log.exception( self.name + ": Object not as expected" )
1662 return None
andrewonlab4dbb4d82014-10-17 18:22:31 -04001663 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001664 main.log.error( self.name + ": EOF exception found" )
1665 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001666 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001667 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001668 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001669 main.cleanAndExit()
andrewonlab4dbb4d82014-10-17 18:22:31 -04001670
kelvin-onlabd3b64892015-01-20 13:26:24 -08001671 def addMultipointToSinglepointIntent(
kelvin-onlab898a6c62015-01-16 14:13:53 -08001672 self,
shahshreyac2f97072015-03-19 17:04:29 -07001673 ingressDeviceList,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001674 egressDevice,
shahshreyac2f97072015-03-19 17:04:29 -07001675 portIngressList=None,
kelvin-onlabd3b64892015-01-20 13:26:24 -08001676 portEgress="",
kelvin-onlab898a6c62015-01-16 14:13:53 -08001677 ethType="",
1678 ethSrc="",
1679 ethDst="",
1680 bandwidth="",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001681 lambdaAlloc=False,
kelvin-onlab898a6c62015-01-16 14:13:53 -08001682 ipProto="",
1683 ipSrc="",
1684 ipDst="",
1685 tcpSrc="",
1686 tcpDst="",
1687 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001688 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001689 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001690 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001691 partial=False,
1692 encap="" ):
kelvin8ec71442015-01-15 16:57:00 -08001693 """
shahshreyad0c80432014-12-04 16:56:05 -08001694 Note:
shahshreya70622b12015-03-19 17:19:00 -07001695 This function assumes the format of all ingress devices
Jon Hallbe379602015-03-24 13:39:32 -07001696 is same. That is, all ingress devices include port numbers
1697 with a "/" or all ingress devices could specify device
1698 ids and port numbers seperately.
shahshreyad0c80432014-12-04 16:56:05 -08001699 Required:
Jon Hallbe379602015-03-24 13:39:32 -07001700 * ingressDeviceList: List of device ids of ingress device
shahshreyac2f97072015-03-19 17:04:29 -07001701 ( Atleast 2 ingress devices required in the list )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001702 * egressDevice: device id of egress device
shahshreyad0c80432014-12-04 16:56:05 -08001703 Optional:
1704 * ethType: specify ethType
kelvin8ec71442015-01-15 16:57:00 -08001705 * ethSrc: specify ethSrc ( i.e. src mac addr )
1706 * ethDst: specify ethDst ( i.e. dst mac addr )
shahshreyad0c80432014-12-04 16:56:05 -08001707 * bandwidth: specify bandwidth capacity of link
kelvin-onlabd3b64892015-01-20 13:26:24 -08001708 * lambdaAlloc: if True, intent will allocate lambda
shahshreyad0c80432014-12-04 16:56:05 -08001709 for the specified intent
Jon Halle3f39ff2015-01-13 11:50:53 -08001710 * ipProto: specify ip protocol
shahshreyad0c80432014-12-04 16:56:05 -08001711 * ipSrc: specify ip source address
1712 * ipDst: specify ip destination address
1713 * tcpSrc: specify tcp source port
1714 * tcpDst: specify tcp destination port
1715 * setEthSrc: action to Rewrite Source MAC Address
1716 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001717 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001718 * setVlan: specify VLAN Id treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001719 * encap: specify a type of encapsulation
shahshreyad0c80432014-12-04 16:56:05 -08001720 Description:
kelvin8ec71442015-01-15 16:57:00 -08001721 Adds a multipoint-to-singlepoint intent ( uni-directional ) by
shahshreyad0c80432014-12-04 16:56:05 -08001722 specifying device id's and optional fields
kelvin-onlabfb521662015-02-27 09:52:40 -08001723 Returns:
1724 A string of the intent id or None on error
shahshreyad0c80432014-12-04 16:56:05 -08001725
Jon Halle3f39ff2015-01-13 11:50:53 -08001726 NOTE: This function may change depending on the
Jon Hallefbd9792015-03-05 16:11:36 -08001727 options developers provide for multipoint-to-singlepoint
shahshreyad0c80432014-12-04 16:56:05 -08001728 intent via cli
kelvin8ec71442015-01-15 16:57:00 -08001729 """
shahshreyad0c80432014-12-04 16:56:05 -08001730 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001731 cmd = "add-multi-to-single-intent"
shahshreyad0c80432014-12-04 16:56:05 -08001732
Jeremy Songsterff553672016-05-12 17:06:23 -07001733 if ethType:
1734 cmd += " --ethType " + str( ethType )
1735 if ethSrc:
1736 cmd += " --ethSrc " + str( ethSrc )
1737 if ethDst:
1738 cmd += " --ethDst " + str( ethDst )
1739 if bandwidth:
1740 cmd += " --bandwidth " + str( bandwidth )
1741 if lambdaAlloc:
1742 cmd += " --lambda "
1743 if ipProto:
1744 cmd += " --ipProto " + str( ipProto )
1745 if ipSrc:
1746 cmd += " --ipSrc " + str( ipSrc )
1747 if ipDst:
1748 cmd += " --ipDst " + str( ipDst )
1749 if tcpSrc:
1750 cmd += " --tcpSrc " + str( tcpSrc )
1751 if tcpDst:
1752 cmd += " --tcpDst " + str( tcpDst )
1753 if setEthSrc:
1754 cmd += " --setEthSrc " + str( setEthSrc )
1755 if setEthDst:
1756 cmd += " --setEthDst " + str( setEthDst )
1757 if vlanId:
1758 cmd += " -v " + str( vlanId )
1759 if setVlan:
1760 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001761 if partial:
1762 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001763 if encap:
1764 cmd += " --encapsulation " + str( encap )
shahshreyad0c80432014-12-04 16:56:05 -08001765
kelvin8ec71442015-01-15 16:57:00 -08001766 # Check whether the user appended the port
1767 # or provided it as an input
shahshreyac2f97072015-03-19 17:04:29 -07001768
1769 if portIngressList is None:
1770 for ingressDevice in ingressDeviceList:
1771 if "/" in ingressDevice:
1772 cmd += " " + str( ingressDevice )
1773 else:
1774 main.log.error( "You must specify " +
Jon Hallbe379602015-03-24 13:39:32 -07001775 "the ingress port" )
shahshreyac2f97072015-03-19 17:04:29 -07001776 # TODO: perhaps more meaningful return
1777 return main.FALSE
shahshreyad0c80432014-12-04 16:56:05 -08001778 else:
Jon Hall71ce4e72015-03-23 14:05:58 -07001779 if len( ingressDeviceList ) == len( portIngressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001780 for ingressDevice, portIngress in zip( ingressDeviceList,
1781 portIngressList ):
shahshreya70622b12015-03-19 17:19:00 -07001782 cmd += " " + \
1783 str( ingressDevice ) + "/" +\
1784 str( portIngress ) + " "
kelvin-onlab38143812015-04-01 15:03:01 -07001785 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001786 main.log.error( "Device list and port list does not " +
1787 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001788 return main.FALSE
kelvin-onlabd3b64892015-01-20 13:26:24 -08001789 if "/" in egressDevice:
1790 cmd += " " + str( egressDevice )
shahshreyad0c80432014-12-04 16:56:05 -08001791 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001792 if not portEgress:
kelvin8ec71442015-01-15 16:57:00 -08001793 main.log.error( "You must specify " +
1794 "the egress port" )
shahshreyad0c80432014-12-04 16:56:05 -08001795 return main.FALSE
Jon Halle3f39ff2015-01-13 11:50:53 -08001796
kelvin8ec71442015-01-15 16:57:00 -08001797 cmd += " " +\
kelvin-onlabd3b64892015-01-20 13:26:24 -08001798 str( egressDevice ) + "/" +\
1799 str( portEgress )
kelvin-onlab898a6c62015-01-16 14:13:53 -08001800 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001801 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001802 assert "Command not found:" not in handle, handle
kelvin-onlabfb521662015-02-27 09:52:40 -08001803 # If error, return error message
kelvin-onlab898a6c62015-01-16 14:13:53 -08001804 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001805 main.log.error( self.name + ": Error in adding multipoint-to-singlepoint " +
kelvin-onlabfb521662015-02-27 09:52:40 -08001806 "intent" )
1807 return None
shahshreyad0c80432014-12-04 16:56:05 -08001808 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001809 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001810 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001811 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001812 else:
1813 main.log.error( "Error, intent ID not found" )
1814 return None
Jon Hallc6793552016-01-19 14:18:37 -08001815 except AssertionError:
1816 main.log.exception( "" )
1817 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001818 except TypeError:
1819 main.log.exception( self.name + ": Object not as expected" )
1820 return None
1821 except pexpect.EOF:
1822 main.log.error( self.name + ": EOF exception found" )
1823 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001824 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001825 except Exception:
1826 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001827 main.cleanAndExit()
kelvin-onlabb9408212015-04-01 13:34:04 -07001828
1829 def addSinglepointToMultipointIntent(
1830 self,
1831 ingressDevice,
1832 egressDeviceList,
1833 portIngress="",
1834 portEgressList=None,
1835 ethType="",
1836 ethSrc="",
1837 ethDst="",
1838 bandwidth="",
1839 lambdaAlloc=False,
1840 ipProto="",
1841 ipSrc="",
1842 ipDst="",
1843 tcpSrc="",
1844 tcpDst="",
1845 setEthSrc="",
Jeremy Songster832f9e92016-05-05 14:30:49 -07001846 setEthDst="",
Jeremy Songsterff553672016-05-12 17:06:23 -07001847 vlanId="",
Jeremy Songster9385d412016-06-02 17:57:36 -07001848 setVlan="",
Jeremy Songsterc032f162016-08-04 17:14:49 -07001849 partial=False,
1850 encap="" ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001851 """
1852 Note:
1853 This function assumes the format of all egress devices
1854 is same. That is, all egress devices include port numbers
1855 with a "/" or all egress devices could specify device
1856 ids and port numbers seperately.
1857 Required:
1858 * EgressDeviceList: List of device ids of egress device
1859 ( Atleast 2 eress devices required in the list )
1860 * ingressDevice: device id of ingress device
1861 Optional:
1862 * ethType: specify ethType
1863 * ethSrc: specify ethSrc ( i.e. src mac addr )
1864 * ethDst: specify ethDst ( i.e. dst mac addr )
1865 * bandwidth: specify bandwidth capacity of link
1866 * lambdaAlloc: if True, intent will allocate lambda
1867 for the specified intent
1868 * ipProto: specify ip protocol
1869 * ipSrc: specify ip source address
1870 * ipDst: specify ip destination address
1871 * tcpSrc: specify tcp source port
1872 * tcpDst: specify tcp destination port
1873 * setEthSrc: action to Rewrite Source MAC Address
1874 * setEthDst: action to Rewrite Destination MAC Address
Jeremy Songster832f9e92016-05-05 14:30:49 -07001875 * vlanId: specify vlan Id
Jeremy Songsterff553672016-05-12 17:06:23 -07001876 * setVlan: specify VLAN ID treatment
Jeremy Songsterc032f162016-08-04 17:14:49 -07001877 * encap: specify an encapsulation type
kelvin-onlabb9408212015-04-01 13:34:04 -07001878 Description:
1879 Adds a singlepoint-to-multipoint intent ( uni-directional ) by
1880 specifying device id's and optional fields
1881 Returns:
1882 A string of the intent id or None on error
1883
1884 NOTE: This function may change depending on the
1885 options developers provide for singlepoint-to-multipoint
1886 intent via cli
1887 """
1888 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07001889 cmd = "add-single-to-multi-intent"
kelvin-onlabb9408212015-04-01 13:34:04 -07001890
Jeremy Songsterff553672016-05-12 17:06:23 -07001891 if ethType:
1892 cmd += " --ethType " + str( ethType )
1893 if ethSrc:
1894 cmd += " --ethSrc " + str( ethSrc )
1895 if ethDst:
1896 cmd += " --ethDst " + str( ethDst )
1897 if bandwidth:
1898 cmd += " --bandwidth " + str( bandwidth )
1899 if lambdaAlloc:
1900 cmd += " --lambda "
1901 if ipProto:
1902 cmd += " --ipProto " + str( ipProto )
1903 if ipSrc:
1904 cmd += " --ipSrc " + str( ipSrc )
1905 if ipDst:
1906 cmd += " --ipDst " + str( ipDst )
1907 if tcpSrc:
1908 cmd += " --tcpSrc " + str( tcpSrc )
1909 if tcpDst:
1910 cmd += " --tcpDst " + str( tcpDst )
1911 if setEthSrc:
1912 cmd += " --setEthSrc " + str( setEthSrc )
1913 if setEthDst:
1914 cmd += " --setEthDst " + str( setEthDst )
1915 if vlanId:
1916 cmd += " -v " + str( vlanId )
1917 if setVlan:
1918 cmd += " --setVlan " + str( setVlan )
Jeremy Songster9385d412016-06-02 17:57:36 -07001919 if partial:
1920 cmd += " --partial"
Jeremy Songsterc032f162016-08-04 17:14:49 -07001921 if encap:
1922 cmd += " --encapsulation " + str( encap )
kelvin-onlabb9408212015-04-01 13:34:04 -07001923
1924 # Check whether the user appended the port
1925 # or provided it as an input
Jon Hall08f61bc2015-04-13 16:00:30 -07001926
kelvin-onlabb9408212015-04-01 13:34:04 -07001927 if "/" in ingressDevice:
1928 cmd += " " + str( ingressDevice )
1929 else:
1930 if not portIngress:
1931 main.log.error( "You must specify " +
1932 "the Ingress port" )
1933 return main.FALSE
1934
1935 cmd += " " +\
1936 str( ingressDevice ) + "/" +\
1937 str( portIngress )
1938
1939 if portEgressList is None:
1940 for egressDevice in egressDeviceList:
1941 if "/" in egressDevice:
1942 cmd += " " + str( egressDevice )
1943 else:
1944 main.log.error( "You must specify " +
1945 "the egress port" )
1946 # TODO: perhaps more meaningful return
1947 return main.FALSE
1948 else:
1949 if len( egressDeviceList ) == len( portEgressList ):
Jon Hall08f61bc2015-04-13 16:00:30 -07001950 for egressDevice, portEgress in zip( egressDeviceList,
1951 portEgressList ):
kelvin-onlabb9408212015-04-01 13:34:04 -07001952 cmd += " " + \
1953 str( egressDevice ) + "/" +\
1954 str( portEgress )
kelvin-onlab38143812015-04-01 15:03:01 -07001955 else:
Jon Hall08f61bc2015-04-13 16:00:30 -07001956 main.log.error( "Device list and port list does not " +
1957 "have the same length" )
kelvin-onlab38143812015-04-01 15:03:01 -07001958 return main.FALSE
kelvin-onlabb9408212015-04-01 13:34:04 -07001959 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08001960 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08001961 assert "Command not found:" not in handle, handle
kelvin-onlabb9408212015-04-01 13:34:04 -07001962 # If error, return error message
1963 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07001964 main.log.error( self.name + ": Error in adding singlepoint-to-multipoint " +
kelvin-onlabb9408212015-04-01 13:34:04 -07001965 "intent" )
shahshreyac2f97072015-03-19 17:04:29 -07001966 return None
kelvin-onlabb9408212015-04-01 13:34:04 -07001967 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001968 match = re.search( 'id=0x([\da-f]+),', handle )
kelvin-onlabb9408212015-04-01 13:34:04 -07001969 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001970 return match.group()[ 3:-1 ]
kelvin-onlabb9408212015-04-01 13:34:04 -07001971 else:
1972 main.log.error( "Error, intent ID not found" )
1973 return None
Jon Hallc6793552016-01-19 14:18:37 -08001974 except AssertionError:
1975 main.log.exception( "" )
1976 return None
Jon Halld4d4b372015-01-28 16:02:41 -08001977 except TypeError:
1978 main.log.exception( self.name + ": Object not as expected" )
1979 return None
shahshreyad0c80432014-12-04 16:56:05 -08001980 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001981 main.log.error( self.name + ": EOF exception found" )
1982 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001983 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001984 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08001985 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001986 main.cleanAndExit()
shahshreyad0c80432014-12-04 16:56:05 -08001987
Hari Krishna9e232602015-04-13 17:29:08 -07001988 def addMplsIntent(
1989 self,
1990 ingressDevice,
1991 egressDevice,
Hari Krishna87a17f12015-04-13 17:42:23 -07001992 ingressPort="",
1993 egressPort="",
Hari Krishna9e232602015-04-13 17:29:08 -07001994 ethType="",
1995 ethSrc="",
1996 ethDst="",
1997 bandwidth="",
1998 lambdaAlloc=False,
1999 ipProto="",
2000 ipSrc="",
2001 ipDst="",
2002 tcpSrc="",
2003 tcpDst="",
Hari Krishna87a17f12015-04-13 17:42:23 -07002004 ingressLabel="",
Hari Krishnadfff6672015-04-13 17:53:27 -07002005 egressLabel="",
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002006 priority="" ):
Hari Krishna9e232602015-04-13 17:29:08 -07002007 """
2008 Required:
2009 * ingressDevice: device id of ingress device
2010 * egressDevice: device id of egress device
2011 Optional:
2012 * ethType: specify ethType
2013 * ethSrc: specify ethSrc ( i.e. src mac addr )
2014 * ethDst: specify ethDst ( i.e. dst mac addr )
2015 * bandwidth: specify bandwidth capacity of link
2016 * lambdaAlloc: if True, intent will allocate lambda
2017 for the specified intent
2018 * ipProto: specify ip protocol
2019 * ipSrc: specify ip source address
2020 * ipDst: specify ip destination address
2021 * tcpSrc: specify tcp source port
2022 * tcpDst: specify tcp destination port
2023 * ingressLabel: Ingress MPLS label
2024 * egressLabel: Egress MPLS label
2025 Description:
2026 Adds MPLS intent by
2027 specifying device id's and optional fields
2028 Returns:
2029 A string of the intent id or None on error
2030
2031 NOTE: This function may change depending on the
2032 options developers provide for MPLS
2033 intent via cli
2034 """
2035 try:
Jeremy Songsterff553672016-05-12 17:06:23 -07002036 cmd = "add-mpls-intent"
Hari Krishna9e232602015-04-13 17:29:08 -07002037
Jeremy Songsterff553672016-05-12 17:06:23 -07002038 if ethType:
2039 cmd += " --ethType " + str( ethType )
2040 if ethSrc:
2041 cmd += " --ethSrc " + str( ethSrc )
2042 if ethDst:
2043 cmd += " --ethDst " + str( ethDst )
2044 if bandwidth:
2045 cmd += " --bandwidth " + str( bandwidth )
2046 if lambdaAlloc:
2047 cmd += " --lambda "
2048 if ipProto:
2049 cmd += " --ipProto " + str( ipProto )
2050 if ipSrc:
2051 cmd += " --ipSrc " + str( ipSrc )
2052 if ipDst:
2053 cmd += " --ipDst " + str( ipDst )
2054 if tcpSrc:
2055 cmd += " --tcpSrc " + str( tcpSrc )
2056 if tcpDst:
2057 cmd += " --tcpDst " + str( tcpDst )
2058 if ingressLabel:
2059 cmd += " --ingressLabel " + str( ingressLabel )
2060 if egressLabel:
2061 cmd += " --egressLabel " + str( egressLabel )
2062 if priority:
2063 cmd += " --priority " + str( priority )
Hari Krishna9e232602015-04-13 17:29:08 -07002064
2065 # Check whether the user appended the port
2066 # or provided it as an input
2067 if "/" in ingressDevice:
2068 cmd += " " + str( ingressDevice )
2069 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002070 if not ingressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002071 main.log.error( "You must specify the ingress port" )
2072 return None
2073
2074 cmd += " " + \
2075 str( ingressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002076 str( ingressPort ) + " "
Hari Krishna9e232602015-04-13 17:29:08 -07002077
2078 if "/" in egressDevice:
2079 cmd += " " + str( egressDevice )
2080 else:
Hari Krishna87a17f12015-04-13 17:42:23 -07002081 if not egressPort:
Hari Krishna9e232602015-04-13 17:29:08 -07002082 main.log.error( "You must specify the egress port" )
2083 return None
2084
2085 cmd += " " +\
2086 str( egressDevice ) + "/" +\
Hari Krishna87a17f12015-04-13 17:42:23 -07002087 str( egressPort )
Hari Krishna9e232602015-04-13 17:29:08 -07002088
2089 handle = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08002090 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002091 assert "Command not found:" not in handle, handle
Hari Krishna9e232602015-04-13 17:29:08 -07002092 # If error, return error message
2093 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002094 main.log.error( self.name + ": Error in adding mpls intent" )
Hari Krishna9e232602015-04-13 17:29:08 -07002095 return None
2096 else:
2097 # TODO: print out all the options in this message?
2098 main.log.info( "MPLS intent installed between " +
2099 str( ingressDevice ) + " and " +
2100 str( egressDevice ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002101 match = re.search( 'id=0x([\da-f]+),', handle )
Hari Krishna9e232602015-04-13 17:29:08 -07002102 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002103 return match.group()[ 3:-1 ]
Hari Krishna9e232602015-04-13 17:29:08 -07002104 else:
2105 main.log.error( "Error, intent ID not found" )
2106 return None
Jon Hallc6793552016-01-19 14:18:37 -08002107 except AssertionError:
2108 main.log.exception( "" )
2109 return None
Hari Krishna9e232602015-04-13 17:29:08 -07002110 except TypeError:
2111 main.log.exception( self.name + ": Object not as expected" )
2112 return None
2113 except pexpect.EOF:
2114 main.log.error( self.name + ": EOF exception found" )
2115 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002116 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002117 except Exception:
2118 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002119 main.cleanAndExit()
Hari Krishna9e232602015-04-13 17:29:08 -07002120
Jon Hallefbd9792015-03-05 16:11:36 -08002121 def removeIntent( self, intentId, app='org.onosproject.cli',
2122 purge=False, sync=False ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08002123 """
shahshreya1c818fc2015-02-26 13:44:08 -08002124 Remove intent for specified application id and intent id
Jon Hall61282e32015-03-19 11:34:11 -07002125 Optional args:-
shahshreya1c818fc2015-02-26 13:44:08 -08002126 -s or --sync: Waits for the removal before returning
Jon Hall61282e32015-03-19 11:34:11 -07002127 -p or --purge: Purge the intent from the store after removal
2128
Jon Halle3f39ff2015-01-13 11:50:53 -08002129 Returns:
Jon Hall6509dbf2016-06-21 17:01:17 -07002130 main.FALSE on error and
Jon Halle3f39ff2015-01-13 11:50:53 -08002131 cli output otherwise
kelvin-onlab898a6c62015-01-16 14:13:53 -08002132 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002133 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002134 cmdStr = "remove-intent"
shahshreya1c818fc2015-02-26 13:44:08 -08002135 if purge:
2136 cmdStr += " -p"
2137 if sync:
2138 cmdStr += " -s"
2139
2140 cmdStr += " " + app + " " + str( intentId )
kelvin-onlabd3b64892015-01-20 13:26:24 -08002141 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002142 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002143 assert "Command not found:" not in handle, handle
Jon Halle3f39ff2015-01-13 11:50:53 -08002144 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002145 main.log.error( self.name + ": Error in removing intent" )
Jon Halle3f39ff2015-01-13 11:50:53 -08002146 return main.FALSE
andrewonlab9a50dfe2014-10-17 17:22:31 -04002147 else:
Jon Halle3f39ff2015-01-13 11:50:53 -08002148 # TODO: Should this be main.TRUE
2149 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002150 except AssertionError:
2151 main.log.exception( "" )
2152 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002153 except TypeError:
2154 main.log.exception( self.name + ": Object not as expected" )
2155 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04002156 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002157 main.log.error( self.name + ": EOF exception found" )
2158 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002159 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002160 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002161 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002162 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04002163
YPZhangfebf7302016-05-24 16:45:56 -07002164 def removeAllIntents( self, purge=False, sync=False, app='org.onosproject.cli', timeout=30 ):
Jeremy42df2e72016-02-23 16:37:46 -08002165 """
2166 Description:
2167 Remove all the intents
2168 Optional args:-
2169 -s or --sync: Waits for the removal before returning
2170 -p or --purge: Purge the intent from the store after removal
2171 Returns:
2172 Returns main.TRUE if all intents are removed, otherwise returns
2173 main.FALSE; Returns None for exception
2174 """
2175 try:
2176 cmdStr = "remove-intent"
2177 if purge:
2178 cmdStr += " -p"
2179 if sync:
2180 cmdStr += " -s"
2181
2182 cmdStr += " " + app
YPZhangfebf7302016-05-24 16:45:56 -07002183 handle = self.sendline( cmdStr, timeout=timeout )
You Wangb5a55f72017-03-03 12:51:05 -08002184 assert handle is not None, "Error in sendline"
Jeremy42df2e72016-02-23 16:37:46 -08002185 assert "Command not found:" not in handle, handle
2186 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002187 main.log.error( self.name + ": Error in removing intent" )
Jeremy42df2e72016-02-23 16:37:46 -08002188 return main.FALSE
2189 else:
2190 return main.TRUE
2191 except AssertionError:
2192 main.log.exception( "" )
2193 return None
2194 except TypeError:
2195 main.log.exception( self.name + ": Object not as expected" )
2196 return None
2197 except pexpect.EOF:
2198 main.log.error( self.name + ": EOF exception found" )
2199 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002200 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002201 except Exception:
2202 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002203 main.cleanAndExit()
Jeremy42df2e72016-02-23 16:37:46 -08002204
Hari Krishnaacabd5a2015-07-01 17:10:19 -07002205 def purgeWithdrawnIntents( self ):
Hari Krishna0ce0e152015-06-23 09:55:29 -07002206 """
2207 Purges all WITHDRAWN Intents
2208 """
2209 try:
2210 cmdStr = "purge-intents"
2211 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002212 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002213 assert "Command not found:" not in handle, handle
Hari Krishna0ce0e152015-06-23 09:55:29 -07002214 if re.search( "Error", handle ):
Jon Hall0e240372018-05-02 11:21:57 -07002215 main.log.error( self.name + ": Error in purging intents" )
Hari Krishna0ce0e152015-06-23 09:55:29 -07002216 return main.FALSE
2217 else:
2218 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002219 except AssertionError:
2220 main.log.exception( "" )
2221 return None
Hari Krishna0ce0e152015-06-23 09:55:29 -07002222 except TypeError:
2223 main.log.exception( self.name + ": Object not as expected" )
2224 return None
2225 except pexpect.EOF:
2226 main.log.error( self.name + ": EOF exception found" )
2227 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002228 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002229 except Exception:
2230 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002231 main.cleanAndExit()
Hari Krishna0ce0e152015-06-23 09:55:29 -07002232
Devin Lime6fe3c42017-10-18 16:28:40 -07002233 def wipeout( self ):
2234 """
2235 Wipe out the flows,intents,links,devices,hosts, and groups from the ONOS.
2236 """
2237 try:
2238 cmdStr = "wipe-out please"
2239 handle = self.sendline( cmdStr, timeout=60 )
2240 assert handle is not None, "Error in sendline"
2241 assert "Command not found:" not in handle, handle
2242 return main.TRUE
2243 except AssertionError:
2244 main.log.exception( "" )
2245 return None
2246 except TypeError:
2247 main.log.exception( self.name + ": Object not as expected" )
2248 return None
2249 except pexpect.EOF:
2250 main.log.error( self.name + ": EOF exception found" )
2251 main.log.error( self.name + ": " + self.handle.before )
2252 main.cleanAndExit()
2253 except Exception:
2254 main.log.exception( self.name + ": Uncaught exception!" )
2255 main.cleanAndExit()
2256
kelvin-onlabd3b64892015-01-20 13:26:24 -08002257 def routes( self, jsonFormat=False ):
kelvin8ec71442015-01-15 16:57:00 -08002258 """
kelvin-onlab898a6c62015-01-16 14:13:53 -08002259 NOTE: This method should be used after installing application:
2260 onos-app-sdnip
pingping-lin8b306ac2014-11-17 18:13:51 -08002261 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002262 * jsonFormat: enable output formatting in json
pingping-lin8b306ac2014-11-17 18:13:51 -08002263 Description:
2264 Obtain all routes in the system
kelvin8ec71442015-01-15 16:57:00 -08002265 """
pingping-lin8b306ac2014-11-17 18:13:51 -08002266 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002267 cmdStr = "routes"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002268 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002269 cmdStr += " -j"
2270 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002271 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002272 assert "Command not found:" not in handle, handle
pingping-lin8b306ac2014-11-17 18:13:51 -08002273 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002274 except AssertionError:
2275 main.log.exception( "" )
2276 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002277 except TypeError:
2278 main.log.exception( self.name + ": Object not as expected" )
2279 return None
pingping-lin8b306ac2014-11-17 18:13:51 -08002280 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002281 main.log.error( self.name + ": EOF exception found" )
2282 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002283 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002284 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002285 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002286 main.cleanAndExit()
pingping-lin8b306ac2014-11-17 18:13:51 -08002287
pingping-lin54b03372015-08-13 14:43:10 -07002288 def ipv4RouteNumber( self ):
2289 """
2290 NOTE: This method should be used after installing application:
2291 onos-app-sdnip
2292 Description:
2293 Obtain the total IPv4 routes number in the system
2294 """
2295 try:
Pratik Parab57963572017-05-09 11:37:54 -07002296 cmdStr = "routes -j"
pingping-lin54b03372015-08-13 14:43:10 -07002297 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002298 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002299 assert "Command not found:" not in handle, handle
pingping-lin54b03372015-08-13 14:43:10 -07002300 jsonResult = json.loads( handle )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002301 return len( jsonResult[ 'routes4' ] )
Jon Hallc6793552016-01-19 14:18:37 -08002302 except AssertionError:
2303 main.log.exception( "" )
2304 return None
2305 except ( TypeError, ValueError ):
2306 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002307 return None
2308 except pexpect.EOF:
2309 main.log.error( self.name + ": EOF exception found" )
2310 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002311 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002312 except Exception:
2313 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002314 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002315
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002316 # =============Function to check Bandwidth allocation========
Jon Hall0e240372018-05-02 11:21:57 -07002317 def allocations( self, jsonFormat = True ):
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002318 """
2319 Description:
2320 Obtain Bandwidth Allocation Information from ONOS cli.
2321 """
2322 try:
2323 cmdStr = "allocations"
2324 if jsonFormat:
2325 cmdStr += " -j"
Jon Hall0e240372018-05-02 11:21:57 -07002326 handle = self.sendline( cmdStr, timeout=300 )
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002327 assert handle is not None, "Error in sendline"
2328 assert "Command not found:" not in handle, handle
2329 return handle
2330 except AssertionError:
2331 main.log.exception( "" )
2332 return None
2333 except ( TypeError, ValueError ):
2334 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
2335 return None
2336 except pexpect.EOF:
2337 main.log.error( self.name + ": EOF exception found" )
2338 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002339 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002340 except Exception:
2341 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002342 main.cleanAndExit()
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002343
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002344 def intents( self, jsonFormat = True, summary = False, **intentargs ):
kelvin8ec71442015-01-15 16:57:00 -08002345 """
andrewonlabe6745342014-10-17 14:29:13 -04002346 Description:
Jon Hallff566d52016-01-15 14:45:36 -08002347 Obtain intents from the ONOS cli.
2348 Optional:
2349 * jsonFormat: Enable output formatting in json, default to True
2350 * summary: Whether only output the intent summary, defaults to False
2351 * type: Only output a certain type of intent. This options is valid
2352 only when jsonFormat is True and summary is True.
kelvin-onlab898a6c62015-01-16 14:13:53 -08002353 """
andrewonlabe6745342014-10-17 14:29:13 -04002354 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002355 cmdStr = "intents"
pingping-lin8244a3b2015-09-16 13:36:56 -07002356 if summary:
2357 cmdStr += " -s"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002358 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002359 cmdStr += " -j"
Shreya Chowdhary6fbb96c2017-05-02 16:20:19 -07002360 handle = self.sendline( cmdStr, timeout=300 )
You Wangb5a55f72017-03-03 12:51:05 -08002361 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002362 assert "Command not found:" not in handle, handle
pingping-lin8244a3b2015-09-16 13:36:56 -07002363 args = utilities.parse_args( [ "TYPE" ], **intentargs )
acsmars5b5fbaf2015-09-18 10:38:20 -07002364 if "TYPE" in args.keys():
Jon Hallff566d52016-01-15 14:45:36 -08002365 intentType = args[ "TYPE" ]
acsmars5b5fbaf2015-09-18 10:38:20 -07002366 else:
Jon Hallff566d52016-01-15 14:45:36 -08002367 intentType = ""
2368 # IF we want the summary of a specific intent type
2369 if jsonFormat and summary and ( intentType != "" ):
pingping-lin8244a3b2015-09-16 13:36:56 -07002370 jsonResult = json.loads( handle )
Jon Hallff566d52016-01-15 14:45:36 -08002371 if intentType in jsonResult.keys():
2372 return jsonResult[ intentType ]
pingping-lin8244a3b2015-09-16 13:36:56 -07002373 else:
Jon Hallff566d52016-01-15 14:45:36 -08002374 main.log.error( "unknown TYPE, returning all types of intents" )
pingping-lin8244a3b2015-09-16 13:36:56 -07002375 return handle
2376 else:
2377 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002378 except AssertionError:
2379 main.log.exception( "" )
2380 return None
2381 except ( TypeError, ValueError ):
2382 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, handle ) )
pingping-lin54b03372015-08-13 14:43:10 -07002383 return None
2384 except pexpect.EOF:
2385 main.log.error( self.name + ": EOF exception found" )
2386 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002387 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002388 except Exception:
2389 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002390 main.cleanAndExit()
pingping-lin54b03372015-08-13 14:43:10 -07002391
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002392 def getIntentState( self, intentsId, intentsJson=None ):
kelvin-onlab54400a92015-02-26 18:05:51 -08002393 """
You Wangfdcbfc42016-05-16 12:16:53 -07002394 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002395 Gets intent state. Accepts a single intent ID (string type) or a
You Wangfdcbfc42016-05-16 12:16:53 -07002396 list of intent IDs.
2397 Parameters:
2398 intentsId: intent ID, both string type and list type are acceptable
kelvin-onlab54400a92015-02-26 18:05:51 -08002399 intentsJson: parsed json object from the onos:intents api
You Wangfdcbfc42016-05-16 12:16:53 -07002400 Returns:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002401 Returns the state (string type) of the ID if a single intent ID is
You Wangfdcbfc42016-05-16 12:16:53 -07002402 accepted.
2403 Returns a list of dictionaries if a list of intent IDs is accepted,
2404 and each dictionary maps 'id' to the Intent ID and 'state' to
2405 corresponding intent state.
kelvin-onlab54400a92015-02-26 18:05:51 -08002406 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002407
kelvin-onlab54400a92015-02-26 18:05:51 -08002408 try:
2409 state = "State is Undefined"
2410 if not intentsJson:
Jon Hallc6793552016-01-19 14:18:37 -08002411 rawJson = self.intents()
kelvin-onlab54400a92015-02-26 18:05:51 -08002412 else:
Jon Hallc6793552016-01-19 14:18:37 -08002413 rawJson = intentsJson
2414 parsedIntentsJson = json.loads( rawJson )
Jon Hallefbd9792015-03-05 16:11:36 -08002415 if isinstance( intentsId, types.StringType ):
Jon Hallc6793552016-01-19 14:18:37 -08002416 for intent in parsedIntentsJson:
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002417 if intentsId == intent[ 'id' ]:
2418 state = intent[ 'state' ]
kelvin-onlab54400a92015-02-26 18:05:51 -08002419 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002420 main.log.info( "Cannot find intent ID" + str( intentsId ) +
Jon Hall53158082017-05-18 11:17:00 -07002421 " in the list" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002422 return state
Jon Hallefbd9792015-03-05 16:11:36 -08002423 elif isinstance( intentsId, types.ListType ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002424 dictList = []
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002425 for i in xrange( len( intentsId ) ):
kelvin-onlab07dbd012015-03-04 16:29:39 -08002426 stateDict = {}
Jon Hall53158082017-05-18 11:17:00 -07002427 for intent in parsedIntentsJson:
2428 if intentsId[ i ] == intent[ 'id' ]:
2429 stateDict[ 'state' ] = intent[ 'state' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002430 stateDict[ 'id' ] = intentsId[ i ]
Jon Hallefbd9792015-03-05 16:11:36 -08002431 dictList.append( stateDict )
kelvin-onlab54400a92015-02-26 18:05:51 -08002432 break
Jon Hallefbd9792015-03-05 16:11:36 -08002433 if len( intentsId ) != len( dictList ):
Jon Hall53158082017-05-18 11:17:00 -07002434 main.log.warn( "Could not find all intents in ONOS output" )
2435 main.log.debug( "expected ids: {} \n ONOS intents: {}".format( intentsId, parsedIntentsJson ) )
kelvin-onlab07dbd012015-03-04 16:29:39 -08002436 return dictList
kelvin-onlab54400a92015-02-26 18:05:51 -08002437 else:
Jon Hall53158082017-05-18 11:17:00 -07002438 main.log.info( "Invalid type for intentsId argument" )
kelvin-onlab54400a92015-02-26 18:05:51 -08002439 return None
Jon Hallc6793552016-01-19 14:18:37 -08002440 except ( TypeError, ValueError ):
2441 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
kelvin-onlab54400a92015-02-26 18:05:51 -08002442 return None
2443 except pexpect.EOF:
2444 main.log.error( self.name + ": EOF exception found" )
2445 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002446 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002447 except Exception:
kelvin-onlab54400a92015-02-26 18:05:51 -08002448 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002449 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07002450
Jon Hallf539eb92017-05-22 17:18:42 -07002451 def checkIntentState( self, intentsId, expectedState='INSTALLED' ):
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002452 """
2453 Description:
2454 Check intents state
2455 Required:
2456 intentsId - List of intents ID to be checked
2457 Optional:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002458 expectedState - Check the expected state(s) of each intents
kelvin-onlabf512e942015-06-08 19:42:59 -07002459 state in the list.
2460 *NOTE: You can pass in a list of expected state,
2461 Eg: expectedState = [ 'INSTALLED' , 'INSTALLING' ]
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002462 Return:
Jon Hall53158082017-05-18 11:17:00 -07002463 Returns main.TRUE only if all intent are the same as expected states,
2464 otherwise returns main.FALSE.
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002465 """
2466 try:
kelvin-onlabf512e942015-06-08 19:42:59 -07002467 returnValue = main.TRUE
Jon Hallf539eb92017-05-22 17:18:42 -07002468 # Generating a dictionary: intent id as a key and state as value
Devin Lim752dd7b2017-06-27 14:40:03 -07002469
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002470 # intentsDict = self.getIntentState( intentsId )
Devin Lim752dd7b2017-06-27 14:40:03 -07002471 intentsDict = []
2472 for intent in json.loads( self.intents() ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002473 if isinstance( intentsId, types.StringType ) \
2474 and intent.get( 'id' ) == intentsId:
2475 intentsDict.append( intent )
2476 elif isinstance( intentsId, types.ListType ) \
Devin Lim752dd7b2017-06-27 14:40:03 -07002477 and any( intent.get( 'id' ) == ids for ids in intentsId ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002478 intentsDict.append( intent )
Devin Lim752dd7b2017-06-27 14:40:03 -07002479
2480 if not intentsDict:
Jon Hallae04e622016-01-27 10:38:05 -08002481 main.log.info( self.name + ": There is something wrong " +
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002482 "getting intents state" )
2483 return main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002484
2485 if isinstance( expectedState, types.StringType ):
2486 for intents in intentsDict:
2487 if intents.get( 'state' ) != expectedState:
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002488 main.log.debug( self.name + " : Intent ID - " +
2489 intents.get( 'id' ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002490 " actual state = " +
2491 intents.get( 'state' )
2492 + " does not equal expected state = "
2493 + expectedState )
kelvin-onlaba297c4d2015-06-01 13:53:55 -07002494 returnValue = main.FALSE
kelvin-onlabf512e942015-06-08 19:42:59 -07002495 elif isinstance( expectedState, types.ListType ):
2496 for intents in intentsDict:
2497 if not any( state == intents.get( 'state' ) for state in
2498 expectedState ):
2499 main.log.debug( self.name + " : Intent ID - " +
2500 intents.get( 'id' ) +
2501 " actual state = " +
2502 intents.get( 'state' ) +
2503 " does not equal expected states = "
2504 + str( expectedState ) )
2505 returnValue = main.FALSE
2506
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002507 if returnValue == main.TRUE:
2508 main.log.info( self.name + ": All " +
2509 str( len( intentsDict ) ) +
kelvin-onlabf512e942015-06-08 19:42:59 -07002510 " intents are in " + str( expectedState ) +
2511 " state" )
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002512 return returnValue
2513 except TypeError:
2514 main.log.exception( self.name + ": Object not as expected" )
2515 return None
2516 except pexpect.EOF:
2517 main.log.error( self.name + ": EOF exception found" )
2518 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002519 main.cleanAndExit()
kelvin-onlabc2dcd3f2015-04-09 16:40:02 -07002520 except Exception:
2521 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002522 main.cleanAndExit()
andrewonlabe6745342014-10-17 14:29:13 -04002523
Jon Hallf539eb92017-05-22 17:18:42 -07002524 def compareBandwidthAllocations( self, expectedAllocations ):
2525 """
2526 Description:
2527 Compare the allocated bandwidth with the given allocations
2528 Required:
2529 expectedAllocations - The expected ONOS output of the allocations command
2530 Return:
2531 Returns main.TRUE only if all intent are the same as expected states,
2532 otherwise returns main.FALSE.
2533 """
2534 # FIXME: Convert these string comparisons to object comparisons
2535 try:
2536 returnValue = main.TRUE
2537 bandwidthFailed = False
2538 rawAlloc = self.allocations()
2539 expectedFormat = StringIO( expectedAllocations )
2540 ONOSOutput = StringIO( rawAlloc )
2541 main.log.debug( "ONOSOutput: {}\nexpected output: {}".format( str( ONOSOutput ),
2542 str( expectedFormat ) ) )
2543
2544 for actual, expected in izip( ONOSOutput, expectedFormat ):
2545 actual = actual.rstrip()
2546 expected = expected.rstrip()
2547 main.log.debug( "Expect: {}\nactual: {}".format( expected, actual ) )
2548 if actual != expected and 'allocated' in actual and 'allocated' in expected:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002549 marker1 = actual.find( 'allocated' )
2550 m1 = actual[ :marker1 ]
2551 marker2 = expected.find( 'allocated' )
2552 m2 = expected[ :marker2 ]
Jon Hallf539eb92017-05-22 17:18:42 -07002553 if m1 != m2:
2554 bandwidthFailed = True
2555 elif actual != expected and 'allocated' not in actual and 'allocated' not in expected:
2556 bandwidthFailed = True
2557 expectedFormat.close()
2558 ONOSOutput.close()
2559
2560 if bandwidthFailed:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002561 main.log.error( "Bandwidth not allocated correctly using Intents!!" )
Jon Hallf539eb92017-05-22 17:18:42 -07002562 returnValue = main.FALSE
2563 return returnValue
2564 except TypeError:
2565 main.log.exception( self.name + ": Object not as expected" )
2566 return None
2567 except pexpect.EOF:
2568 main.log.error( self.name + ": EOF exception found" )
2569 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002570 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002571 except Exception:
2572 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002573 main.cleanAndExit()
Jon Hallf539eb92017-05-22 17:18:42 -07002574
You Wang66518af2016-05-16 15:32:59 -07002575 def compareIntent( self, intentDict ):
2576 """
2577 Description:
2578 Compare the intent ids and states provided in the argument with all intents in ONOS
2579 Return:
2580 Returns main.TRUE if the two sets of intents match exactly, otherwise main.FALSE
2581 Arguments:
2582 intentDict: a dictionary which maps intent ids to intent states
2583 """
2584 try:
2585 intentsRaw = self.intents()
2586 intentsJson = json.loads( intentsRaw )
2587 intentDictONOS = {}
2588 for intent in intentsJson:
2589 intentDictONOS[ intent[ 'id' ] ] = intent[ 'state' ]
You Wang58d04452016-09-21 15:13:05 -07002590 returnValue = main.TRUE
You Wang66518af2016-05-16 15:32:59 -07002591 if len( intentDict ) != len( intentDictONOS ):
You Wang58d04452016-09-21 15:13:05 -07002592 main.log.warn( self.name + ": expected intent count does not match that in ONOS, " +
You Wang66518af2016-05-16 15:32:59 -07002593 str( len( intentDict ) ) + " expected and " +
2594 str( len( intentDictONOS ) ) + " actual" )
You Wang58d04452016-09-21 15:13:05 -07002595 returnValue = main.FALSE
You Wang66518af2016-05-16 15:32:59 -07002596 for intentID in intentDict.keys():
Jon Halle0f0b342017-04-18 11:43:47 -07002597 if intentID not in intentDictONOS.keys():
You Wang66518af2016-05-16 15:32:59 -07002598 main.log.debug( self.name + ": intent ID - " + intentID + " is not in ONOS" )
2599 returnValue = main.FALSE
You Wang58d04452016-09-21 15:13:05 -07002600 else:
2601 if intentDict[ intentID ] != intentDictONOS[ intentID ]:
2602 main.log.debug( self.name + ": intent ID - " + intentID +
2603 " expected state is " + intentDict[ intentID ] +
2604 " but actual state is " + intentDictONOS[ intentID ] )
2605 returnValue = main.FALSE
2606 intentDictONOS.pop( intentID )
2607 if len( intentDictONOS ) > 0:
2608 returnValue = main.FALSE
2609 for intentID in intentDictONOS.keys():
2610 main.log.debug( self.name + ": find extra intent in ONOS: intent ID " + intentID )
You Wang66518af2016-05-16 15:32:59 -07002611 if returnValue == main.TRUE:
2612 main.log.info( self.name + ": all intent IDs and states match that in ONOS" )
2613 return returnValue
You Wang1be9a512016-05-26 16:54:17 -07002614 except KeyError:
2615 main.log.exception( self.name + ": KeyError exception found" )
2616 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002617 except ( TypeError, ValueError ):
2618 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intentsRaw ) )
You Wang85560372016-05-18 10:44:33 -07002619 return main.ERROR
You Wang66518af2016-05-16 15:32:59 -07002620 except pexpect.EOF:
2621 main.log.error( self.name + ": EOF exception found" )
2622 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002623 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002624 except Exception:
2625 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002626 main.cleanAndExit()
You Wang66518af2016-05-16 15:32:59 -07002627
YPZhang14a4aa92016-07-15 13:37:15 -07002628 def checkIntentSummary( self, timeout=60, noExit=True ):
GlennRCed771242016-01-13 17:02:47 -08002629 """
2630 Description:
2631 Check the number of installed intents.
2632 Optional:
2633 timeout - the timeout for pexcept
YPZhang14a4aa92016-07-15 13:37:15 -07002634 noExit - If noExit, TestON will not exit if any except.
GlennRCed771242016-01-13 17:02:47 -08002635 Return:
2636 Returns main.TRUE only if the number of all installed intents are the same as total intents number
2637 , otherwise, returns main.FALSE.
2638 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002639
GlennRCed771242016-01-13 17:02:47 -08002640 try:
2641 cmd = "intents -s -j"
2642
2643 # Check response if something wrong
YPZhang14a4aa92016-07-15 13:37:15 -07002644 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002645 if response is None:
YPZhang0584d432016-06-21 15:20:13 -07002646 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002647 response = json.loads( response )
2648
2649 # get total and installed number, see if they are match
2650 allState = response.get( 'all' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002651 if allState.get( 'total' ) == allState.get( 'installed' ):
Jon Halla478b852017-12-04 15:00:15 -08002652 main.log.info( 'Total Intents: {} Installed Intents: {}'.format(
2653 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002654 return main.TRUE
Jon Halla478b852017-12-04 15:00:15 -08002655 main.log.info( 'Verified Intents failed Expected intents: {} installed intents: {}'.format(
2656 allState.get( 'total' ), allState.get( 'installed' ) ) )
GlennRCed771242016-01-13 17:02:47 -08002657 return main.FALSE
2658
Jon Hallc6793552016-01-19 14:18:37 -08002659 except ( TypeError, ValueError ):
2660 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
GlennRCed771242016-01-13 17:02:47 -08002661 return None
2662 except pexpect.EOF:
2663 main.log.error( self.name + ": EOF exception found" )
2664 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002665 if noExit:
2666 return main.FALSE
2667 else:
Devin Lim44075962017-08-11 10:56:37 -07002668 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07002669 except pexpect.TIMEOUT:
2670 main.log.error( self.name + ": ONOS timeout" )
2671 return None
GlennRCed771242016-01-13 17:02:47 -08002672 except Exception:
2673 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002674 if noExit:
2675 return main.FALSE
2676 else:
Devin Lim44075962017-08-11 10:56:37 -07002677 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002678
pierventre3ee58d32022-02-19 18:30:19 -08002679 def flows( self, state="any", jsonFormat=True, timeout=60, noExit=False, noCore=False, device="" ):
2680 return self.dataPlaneEntities( entity="flows", state=state, jsonFormat=jsonFormat,
2681 timeout=timeout, noExit=noExit, noCore=noCore, device=device )
2682
2683 def groups( self, state="any", jsonFormat=True, timeout=60, noExit=False, noCore=False, device="" ):
2684 return self.dataPlaneEntities( entity="groups", state=state, jsonFormat=jsonFormat,
2685 timeout=timeout, noExit=noExit, noCore=noCore, device=device )
2686
2687 def dataPlaneEntities( self, entity="flows", state="any", jsonFormat=True,
2688 timeout=60, noExit=False, noCore=False, device="" ):
kelvin8ec71442015-01-15 16:57:00 -08002689 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002690 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002691 * jsonFormat: enable output formatting in json
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002692 * noCore: suppress core flows
Shreya Shah0f01c812014-10-26 20:15:28 -04002693 Description:
pierventre3ee58d32022-02-19 18:30:19 -08002694 Obtain dataplaneEntities currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08002695 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002696 try:
pierventre3ee58d32022-02-19 18:30:19 -08002697 cmdStr = entity
kelvin-onlabd3b64892015-01-20 13:26:24 -08002698 if jsonFormat:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002699 cmdStr += " -j"
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002700 if noCore:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002701 cmdStr += " -n"
2702 cmdStr += " " + state
2703 cmdStr += " " + device
YPZhangebf9eb52016-05-12 15:20:24 -07002704 handle = self.sendline( cmdStr, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002705 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002706 assert "Command not found:" not in handle, handle
2707 if re.search( "Error:", handle ):
pierventre3ee58d32022-02-19 18:30:19 -08002708 main.log.error( self.name + ": " + entity + "() response: " +
Jon Hallc6793552016-01-19 14:18:37 -08002709 str( handle ) )
2710 return handle
2711 except AssertionError:
2712 main.log.exception( "" )
GlennRCed771242016-01-13 17:02:47 -08002713 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002714 except TypeError:
2715 main.log.exception( self.name + ": Object not as expected" )
2716 return None
Jon Hallc6793552016-01-19 14:18:37 -08002717 except pexpect.TIMEOUT:
2718 main.log.error( self.name + ": ONOS timeout" )
2719 return None
Shreya Shah0f01c812014-10-26 20:15:28 -04002720 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002721 main.log.error( self.name + ": EOF exception found" )
2722 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002723 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002724 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002725 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002726 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002727
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002728 def checkFlowCount( self, min=0, timeout=60 ):
Flavio Castroa1286fe2016-07-25 14:48:51 -07002729 count = self.getTotalFlowsNum( timeout=timeout )
Jon Halle0f0b342017-04-18 11:43:47 -07002730 count = int( count ) if count else 0
steven30801eccfe212019-01-24 13:00:42 +08002731 main.log.debug( "found {} flows".format( count ) )
Jon Hall39570262020-11-17 12:18:19 -08002732 return count if ( count >= min ) else False
GlennRCed771242016-01-13 17:02:47 -08002733
Jon Halle0f0b342017-04-18 11:43:47 -07002734 def checkFlowsState( self, isPENDING=True, timeout=60, noExit=False ):
kelvin-onlab4df89f22015-04-13 18:10:23 -07002735 """
2736 Description:
GlennRCed771242016-01-13 17:02:47 -08002737 Check the if all the current flows are in ADDED state
Jon Hallc6793552016-01-19 14:18:37 -08002738 We check PENDING_ADD, PENDING_REMOVE, REMOVED, and FAILED flows,
2739 if the count of those states is 0, which means all current flows
2740 are in ADDED state, and return main.TRUE otherwise return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002741 Optional:
GlennRCed771242016-01-13 17:02:47 -08002742 * isPENDING: whether the PENDING_ADD is also a correct status
kelvin-onlab4df89f22015-04-13 18:10:23 -07002743 Return:
2744 returnValue - Returns main.TRUE only if all flows are in
Jon Hallc6793552016-01-19 14:18:37 -08002745 ADDED state or PENDING_ADD if the isPENDING
pingping-linbab7f8a2015-09-21 17:33:36 -07002746 parameter is set true, return main.FALSE otherwise.
kelvin-onlab4df89f22015-04-13 18:10:23 -07002747 """
2748 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002749 states = [ "PENDING_ADD", "PENDING_REMOVE", "REMOVED", "FAILED" ]
GlennRCed771242016-01-13 17:02:47 -08002750 checkedStates = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002751 statesCount = [ 0, 0, 0, 0 ]
GlennRCed771242016-01-13 17:02:47 -08002752 for s in states:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002753 rawFlows = self.flows( state=s, timeout = timeout )
YPZhang240842b2016-05-17 12:00:50 -07002754 if rawFlows:
2755 # if we didn't get flows or flows function return None, we should return
2756 # main.Flase
2757 checkedStates.append( json.loads( rawFlows ) )
2758 else:
2759 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002760 for i in range( len( states ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002761 for c in checkedStates[ i ]:
Jon Hallc6793552016-01-19 14:18:37 -08002762 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002763 statesCount[ i ] += int( c.get( "flowCount" ) )
Jon Hallc6793552016-01-19 14:18:37 -08002764 except TypeError:
2765 main.log.exception( "Json object not as expected" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002766 main.log.info( states[ i ] + " flows: " + str( statesCount[ i ] ) )
kelvin-onlabf2ec6e02015-05-27 14:15:28 -07002767
GlennRCed771242016-01-13 17:02:47 -08002768 # We want to count PENDING_ADD if isPENDING is true
2769 if isPENDING:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002770 if statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002771 return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002772 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002773 if statesCount[ 0 ] + statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002774 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002775 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002776 except ( TypeError, ValueError ):
2777 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawFlows ) )
kelvin-onlab4df89f22015-04-13 18:10:23 -07002778 return None
Jeremy Songster9385d412016-06-02 17:57:36 -07002779
YPZhang240842b2016-05-17 12:00:50 -07002780 except AssertionError:
2781 main.log.exception( "" )
2782 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002783 except pexpect.TIMEOUT:
2784 main.log.error( self.name + ": ONOS timeout" )
2785 return None
kelvin-onlab4df89f22015-04-13 18:10:23 -07002786 except pexpect.EOF:
2787 main.log.error( self.name + ": EOF exception found" )
2788 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002789 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002790 except Exception:
2791 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002792 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002793
pierventre3ee58d32022-02-19 18:30:19 -08002794 def checkGroupCount( self, min=0, timeout=60 ):
2795 count = self.getTotalGroupsNum( timeout=timeout )
2796 count = int( count ) if count else 0
2797 main.log.debug( "found {} groups".format( count ) )
2798 return count if ( count >= min ) else False
2799
2800 def checkGroupsState( self, isPENDING=True, timeout=60, noExit=False ):
2801 """
2802 Description:
2803 Check the if all the current groups are in ADDED state
2804 We check PENDING_ADD, PENDING_REMOVE, REMOVED, and FAILED groups,
2805 if the count of those states is 0, which means all current groups
2806 are in ADDED state, and return main.TRUE otherwise return main.FALSE
2807 Optional:
2808 * isPENDING: whether the PENDING_ADD is also a correct status
2809 Return:
2810 returnValue - Returns main.TRUE only if all groups are in
2811 ADDED state or PENDING_ADD if the isPENDING
2812 parameter is set true, return main.FALSE otherwise.
2813 """
2814 try:
2815 states = [ "PENDING_ADD", "PENDING_ADD_RETRY", "PENDING_DELETE", "PENDING_UPDATE", "WAITING_AUDIT_COMPLETE" ]
2816 checkedStates = []
2817 statesCount = [ 0, 0, 0, 0, 0 ]
2818 for s in states:
2819 rawGroups = self.groups( state=s, timeout = timeout )
2820 if rawGroups:
2821 # if we didn't get groups or groups function return None, we should return
2822 # main.Flase
2823 checkedStates.append( json.loads( rawGroups ) )
2824 else:
2825 return main.FALSE
2826 for i in range( len( states ) ):
2827 statesCount[ i ] += int( len(checkedStates[i]) )
2828 main.log.info( states[ i ] + " groups: " + str( statesCount[ i ] ) )
2829
2830 # We want to count PENDING_ADD if isPENDING is true
2831 if isPENDING:
2832 if statesCount[ 2 ] + statesCount[ 3 ] + statesCount[ 4 ] > 0:
2833 return main.FALSE
2834 else:
2835 if statesCount[ 0 ] + statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] + statesCount[ 4 ] > 0:
2836 return main.FALSE
2837 return main.TRUE
2838 except ( TypeError, ValueError ):
2839 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawGroups ) )
2840 return None
2841
2842 except AssertionError:
2843 main.log.exception( "" )
2844 return None
2845 except pexpect.TIMEOUT:
2846 main.log.error( self.name + ": ONOS timeout" )
2847 return None
2848 except pexpect.EOF:
2849 main.log.error( self.name + ": EOF exception found" )
2850 main.log.error( self.name + ": " + self.handle.before )
2851 main.cleanAndExit()
2852 except Exception:
2853 main.log.exception( self.name + ": Uncaught exception!" )
2854 main.cleanAndExit()
2855
GlennRCed771242016-01-13 17:02:47 -08002856 def pushTestIntents( self, ingress, egress, batchSize, offset="",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002857 options="", timeout=10, background = False, noExit=False, getResponse=False ):
kelvin8ec71442015-01-15 16:57:00 -08002858 """
andrewonlab87852b02014-11-19 18:44:19 -05002859 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002860 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05002861 a specific point-to-point intent definition
2862 Required:
GlennRCed771242016-01-13 17:02:47 -08002863 * ingress: specify source dpid
2864 * egress: specify destination dpid
2865 * batchSize: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05002866 Optional:
GlennRCed771242016-01-13 17:02:47 -08002867 * offset: the keyOffset is where the next batch of intents
2868 will be installed
YPZhangb34b7e12016-06-14 14:28:19 -07002869 * noExit: If set to True, TestON will not exit if any error when issus command
2870 * getResponse: If set to True, function will return ONOS response.
2871
GlennRCed771242016-01-13 17:02:47 -08002872 Returns: If failed to push test intents, it will returen None,
2873 if successful, return true.
2874 Timeout expection will return None,
2875 TypeError will return false
2876 other expections will exit()
kelvin8ec71442015-01-15 16:57:00 -08002877 """
andrewonlab87852b02014-11-19 18:44:19 -05002878 try:
GlennRCed771242016-01-13 17:02:47 -08002879 if background:
2880 back = "&"
andrewonlab87852b02014-11-19 18:44:19 -05002881 else:
GlennRCed771242016-01-13 17:02:47 -08002882 back = ""
2883 cmd = "push-test-intents {} {} {} {} {} {}".format( options,
Jon Hallc6793552016-01-19 14:18:37 -08002884 ingress,
2885 egress,
2886 batchSize,
2887 offset,
2888 back )
YPZhangebf9eb52016-05-12 15:20:24 -07002889 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002890 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002891 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08002892 main.log.info( response )
YPZhangb34b7e12016-06-14 14:28:19 -07002893 if getResponse:
2894 return response
2895
GlennRCed771242016-01-13 17:02:47 -08002896 # TODO: We should handle if there is failure in installation
2897 return main.TRUE
2898
Jon Hallc6793552016-01-19 14:18:37 -08002899 except AssertionError:
2900 main.log.exception( "" )
2901 return None
GlennRCed771242016-01-13 17:02:47 -08002902 except pexpect.TIMEOUT:
2903 main.log.error( self.name + ": ONOS timeout" )
Jon Halld4d4b372015-01-28 16:02:41 -08002904 return None
andrewonlab87852b02014-11-19 18:44:19 -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()
GlennRCed771242016-01-13 17:02:47 -08002909 except TypeError:
2910 main.log.exception( self.name + ": Object not as expected" )
Jon Hallc6793552016-01-19 14:18:37 -08002911 return None
Jon Hallfebb1c72015-03-05 13:30:09 -08002912 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002913 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002914 main.cleanAndExit()
andrewonlab87852b02014-11-19 18:44:19 -05002915
YPZhangebf9eb52016-05-12 15:20:24 -07002916 def getTotalFlowsNum( self, timeout=60, noExit=False ):
pierventre3ee58d32022-02-19 18:30:19 -08002917 return self.getTotalEntitiesNum( entity="flows", timeout=60, noExit=False )
2918
2919 def getTotalGroupsNum( self, timeout=60, noExit=False ):
2920 return self.getTotalEntitiesNum( entity="groups", timeout=60, noExit=False )
2921
2922 def getTotalEntitiesNum( self, entity="flows", timeout=60, noExit=False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002923 """
2924 Description:
pierventre3ee58d32022-02-19 18:30:19 -08002925 Get the number of ADDED entities.
YPZhangb5d3f832016-01-23 22:54:26 -08002926 Return:
pierventre3ee58d32022-02-19 18:30:19 -08002927 The number of ADDED entities
YPZhang14a4aa92016-07-15 13:37:15 -07002928 Or return None if any exceptions
YPZhangb5d3f832016-01-23 22:54:26 -08002929 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002930
YPZhangb5d3f832016-01-23 22:54:26 -08002931 try:
pierventre3ee58d32022-02-19 18:30:19 -08002932 # get total added entities number
2933 cmd = entity + " -c added"
2934 rawEntities = self.sendline( cmd, timeout=timeout, noExit=noExit )
2935 if rawEntities:
2936 rawEntities = rawEntities.split( "\n" )
2937 totalEntities = 0
2938 for l in rawEntities:
2939 totalEntities += int( l.split( "Count=" )[ 1 ] )
YPZhang14a4aa92016-07-15 13:37:15 -07002940 else:
You Wang68568b12019-03-04 11:49:57 -08002941 main.log.warn( "Response not as expected!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002942 return None
pierventre3ee58d32022-02-19 18:30:19 -08002943 return totalEntities
YPZhange3109a72016-02-02 11:25:37 -08002944
You Wangd3097f72018-12-12 11:56:03 -08002945 except IndexError:
2946 main.log.exception( "{}: Object not as expected!".format( self.name ) )
pierventre3ee58d32022-02-19 18:30:19 -08002947 main.log.debug( "rawEntities: {}".format( rawEntities ) )
You Wangd3097f72018-12-12 11:56:03 -08002948 return None
You Wangd3cb2ce2016-05-16 14:01:24 -07002949 except ( TypeError, ValueError ):
YPZhang14a4aa92016-07-15 13:37:15 -07002950 main.log.exception( "{}: Object not as expected!".format( self.name ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002951 return None
2952 except pexpect.EOF:
2953 main.log.error( self.name + ": EOF exception found" )
2954 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002955 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002956 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002957 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002958 except pexpect.TIMEOUT:
2959 main.log.error( self.name + ": ONOS timeout" )
2960 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002961 except Exception:
2962 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002963 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002964 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002965 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002966
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002967 def getTotalIntentsNum( self, timeout=60, noExit = False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002968 """
2969 Description:
2970 Get the total number of intents, include every states.
YPZhang14a4aa92016-07-15 13:37:15 -07002971 Optional:
2972 noExit - If noExit, TestON will not exit if any except.
YPZhangb5d3f832016-01-23 22:54:26 -08002973 Return:
2974 The number of intents
2975 """
2976 try:
2977 cmd = "summary -j"
YPZhang14a4aa92016-07-15 13:37:15 -07002978 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002979 if response is None:
2980 return -1
YPZhangb5d3f832016-01-23 22:54:26 -08002981 response = json.loads( response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002982 return int( response.get( "intents" ) )
You Wangd3cb2ce2016-05-16 14:01:24 -07002983 except ( TypeError, ValueError ):
2984 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002985 return None
2986 except pexpect.EOF:
2987 main.log.error( self.name + ": EOF exception found" )
2988 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002989 if noExit:
2990 return -1
2991 else:
Devin Lim44075962017-08-11 10:56:37 -07002992 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002993 except Exception:
2994 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002995 if noExit:
2996 return -1
2997 else:
Devin Lim44075962017-08-11 10:56:37 -07002998 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002999
kelvin-onlabd3b64892015-01-20 13:26:24 -08003000 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08003001 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003002 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05003003 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003004 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08003005 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05003006 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003007 cmdStr = "intents-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003008 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003009 cmdStr += " -j"
3010 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003011 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003012 assert "Command not found:" not in handle, handle
andrewonlab0dbb6ec2014-11-06 13:46:55 -05003013 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003014 except AssertionError:
3015 main.log.exception( "" )
3016 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003017 except TypeError:
3018 main.log.exception( self.name + ": Object not as expected" )
3019 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05003020 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003021 main.log.error( self.name + ": EOF exception found" )
3022 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003023 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003024 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003025 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003026 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04003027
kelvin-onlabd3b64892015-01-20 13:26:24 -08003028 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08003029 """
3030 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04003031 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003032 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08003033 """
andrewonlab867212a2014-10-22 20:13:38 -04003034 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003035 cmdStr = "topology-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003036 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003037 cmdStr += " -j"
3038 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003039 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003040 assert "Command not found:" not in handle, handle
jenkins7ead5a82015-03-13 10:28:21 -07003041 if handle:
3042 return handle
Jon Hallc6358dd2015-04-10 12:44:28 -07003043 elif jsonFormat:
Jon Hallbe379602015-03-24 13:39:32 -07003044 # Return empty json
jenkins7ead5a82015-03-13 10:28:21 -07003045 return '{}'
Jon Hallc6358dd2015-04-10 12:44:28 -07003046 else:
3047 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003048 except AssertionError:
3049 main.log.exception( "" )
3050 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003051 except TypeError:
3052 main.log.exception( self.name + ": Object not as expected" )
3053 return None
andrewonlab867212a2014-10-22 20:13:38 -04003054 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003055 main.log.error( self.name + ": EOF exception found" )
3056 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003057 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003058 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003059 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003060 main.cleanAndExit()
andrewonlab867212a2014-10-22 20:13:38 -04003061
kelvin8ec71442015-01-15 16:57:00 -08003062 # Wrapper functions ****************
3063 # Wrapper functions use existing driver
3064 # functions and extends their use case.
3065 # For example, we may use the output of
3066 # a normal driver function, and parse it
3067 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04003068
kelvin-onlabd3b64892015-01-20 13:26:24 -08003069 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003070 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04003071 Description:
3072 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08003073 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04003074 try:
kelvin8ec71442015-01-15 16:57:00 -08003075 # Obtain output of intents function
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003076 intentsStr = self.intents( jsonFormat=True )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003077 if intentsStr is None:
3078 raise TypeError
Jon Hall6021e062017-01-30 11:10:06 -08003079 # Convert to a dictionary
3080 intents = json.loads( intentsStr )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003081 intentIdList = []
Jon Hall6021e062017-01-30 11:10:06 -08003082 for intent in intents:
3083 intentIdList.append( intent[ 'id' ] )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003084 return intentIdList
Jon Halld4d4b372015-01-28 16:02:41 -08003085 except TypeError:
3086 main.log.exception( self.name + ": Object not as expected" )
3087 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04003088 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003089 main.log.error( self.name + ": EOF exception found" )
3090 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003091 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003092 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003093 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003094 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04003095
You Wang3c276252016-09-21 15:21:36 -07003096 def flowAddedCount( self, deviceId, core=False ):
Jon Hall30b82fa2015-03-04 17:15:43 -08003097 """
3098 Determine the number of flow rules for the given device id that are
3099 in the added state
You Wang3c276252016-09-21 15:21:36 -07003100 Params:
3101 core: if True, only return the number of core flows added
Jon Hall30b82fa2015-03-04 17:15:43 -08003102 """
3103 try:
You Wang3c276252016-09-21 15:21:36 -07003104 if core:
3105 cmdStr = "flows any " + str( deviceId ) + " | " +\
3106 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
3107 else:
3108 cmdStr = "flows any " + str( deviceId ) + " | " +\
3109 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003110 handle = self.lineCount( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003111 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003112 assert "Command not found:" not in handle, handle
Jon Hall30b82fa2015-03-04 17:15:43 -08003113 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003114 except AssertionError:
3115 main.log.exception( "" )
3116 return None
Jon Hall30b82fa2015-03-04 17:15:43 -08003117 except pexpect.EOF:
3118 main.log.error( self.name + ": EOF exception found" )
3119 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003120 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003121 except Exception:
Jon Hall30b82fa2015-03-04 17:15:43 -08003122 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003123 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -04003124
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003125 def groupAddedCount( self, deviceId, core=False ):
3126 """
3127 Determine the number of group rules for the given device id that are
3128 in the added state
3129 Params:
3130 core: if True, only return the number of core groups added
3131 """
3132 try:
3133 if core:
3134 cmdStr = "groups any " + str( deviceId ) + " | " +\
3135 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
3136 else:
3137 cmdStr = "groups any " + str( deviceId ) + " | " +\
3138 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003139 handle = self.lineCount( cmdStr )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003140 assert handle is not None, "Error in sendline"
3141 assert "Command not found:" not in handle, handle
3142 return handle
3143 except AssertionError:
3144 main.log.exception( "" )
3145 return None
3146 except pexpect.EOF:
3147 main.log.error( self.name + ": EOF exception found" )
3148 main.log.error( self.name + ": " + self.handle.before )
3149 main.cleanAndExit()
3150 except Exception:
3151 main.log.exception( self.name + ": Uncaught exception!" )
3152 main.cleanAndExit()
3153
Siddesh713c4c52022-01-14 22:08:05 +00003154 def sendOnosCliCommand( self, cmd, params=[] ):
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003155 """
Siddesh713c4c52022-01-14 22:08:05 +00003156 Handles sending an arbitrary command to the ONOS cli and parsing standard errors
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003157 Params:
Siddesh713c4c52022-01-14 22:08:05 +00003158 cmd: The command to be sent in the onos cli
3159 params: Sending the parameters within the command we send in the cli
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003160 """
3161 try:
Siddesh713c4c52022-01-14 22:08:05 +00003162 if not isinstance(params, list):
3163 params=[params]
3164 cmdStr = cmd + " " + ' '.join(params)
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003165 handle = self.sendline( cmdStr )
3166 assert handle is not None, "Error in sendline"
3167 assert "Command not found:" not in handle, handle
Siddesh713c4c52022-01-14 22:08:05 +00003168 # Check for error in cli response
3169 assert "Error executing command" not in handle, handle
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003170 return handle
3171 except AssertionError:
3172 main.log.exception( "" )
Siddesh713c4c52022-01-14 22:08:05 +00003173 return main.FALSE
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003174 except pexpect.EOF:
3175 main.log.error( self.name + ": EOF exception found" )
3176 main.log.error( self.name + ": " + self.handle.before )
3177 main.cleanAndExit()
3178 except Exception:
3179 main.log.exception( self.name + ": Uncaught exception!" )
3180 main.cleanAndExit()
3181
Siddesh713c4c52022-01-14 22:08:05 +00003182 def blackholeStaticRoute( self, subnet, addBlackhole=True ):
3183 """
3184 Manage black hole routes in onos.
3185 Params:
3186 subnet: The subnet to be blocked through this route
3187 addBlackhole: Boolean set to declare if we are adding or removing the blackhole route
3188 """
3189 if addBlackhole:
3190 addedBlackholeIP = self.sendOnosCliCommand('sr-blackhole add', subnet)
3191 else:
3192 removedBlackholeIP = self.sendOnosCliCommand('sr-blackhole remove', subnet)
3193 blackHoleList = self.sendOnosCliCommand('sr-blackhole list')
3194 if subnet in blackHoleList:
3195 exists = True
3196 else:
3197 exists = False
3198 if (addBlackhole and exists) or (not addBlackhole and not exists):
3199 return main.TRUE
3200 else:
3201 return main.FALSE
3202
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003203 def checkGroupAddedCount( self, deviceId, expectedGroupCount=0, core=False, comparison=0):
3204 """
3205 Description:
3206 Check whether the number of groups for the given device id that
3207 are in ADDED state is bigger than minGroupCount.
3208 Required:
3209 * deviceId: device id to check the number of added group rules
3210 Optional:
3211 * minGroupCount: the number of groups to compare
3212 * core: if True, only check the number of core groups added
3213 * comparison: if 0, compare with greater than minFlowCount
3214 * if 1, compare with equal to minFlowCount
3215 Return:
3216 Returns the number of groups if it is bigger than minGroupCount,
3217 returns main.FALSE otherwise.
3218 """
3219 count = self.groupAddedCount( deviceId, core )
3220 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003221 main.log.debug( "found {} groups".format( count ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003222 return count if ((count > expectedGroupCount) if (comparison == 0) else (count == expectedGroupCount)) else main.FALSE
3223
You Wangc02f3be2018-05-18 12:14:23 -07003224 def getGroups( self, deviceId, groupType="any" ):
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003225 """
3226 Retrieve groups from a specific device.
You Wangc02f3be2018-05-18 12:14:23 -07003227 deviceId: Id of the device from which we retrieve groups
3228 groupType: Type of group
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003229 """
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003230 try:
You Wangc02f3be2018-05-18 12:14:23 -07003231 groupCmd = "groups -t {0} any {1}".format( groupType, deviceId )
3232 handle = self.sendline( groupCmd )
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003233 assert handle is not None, "Error in sendline"
3234 assert "Command not found:" not in handle, handle
3235 return handle
3236 except AssertionError:
3237 main.log.exception( "" )
3238 return None
3239 except TypeError:
3240 main.log.exception( self.name + ": Object not as expected" )
3241 return None
3242 except pexpect.EOF:
3243 main.log.error( self.name + ": EOF exception found" )
3244 main.log.error( self.name + ": " + self.handle.before )
3245 main.cleanAndExit()
3246 except Exception:
3247 main.log.exception( self.name + ": Uncaught exception!" )
3248 main.cleanAndExit()
3249
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003250 def checkFlowAddedCount( self, deviceId, expectedFlowCount=0, core=False, comparison=0):
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003251 """
3252 Description:
3253 Check whether the number of flow rules for the given device id that
3254 are in ADDED state is bigger than minFlowCount.
3255 Required:
3256 * deviceId: device id to check the number of added flow rules
3257 Optional:
3258 * minFlowCount: the number of flow rules to compare
3259 * core: if True, only check the number of core flows added
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003260 * comparison: if 0, compare with greater than minFlowCount
3261 * if 1, compare with equal to minFlowCount
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003262 Return:
3263 Returns the number of flow rules if it is bigger than minFlowCount,
3264 returns main.FALSE otherwise.
3265 """
3266 count = self.flowAddedCount( deviceId, core )
3267 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003268 main.log.debug( "found {} flows".format( count ) )
Jon Hall39570262020-11-17 12:18:19 -08003269 return count if ((count >= expectedFlowCount) if (comparison == 0) else (count == expectedFlowCount)) else main.FALSE
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003270
kelvin-onlabd3b64892015-01-20 13:26:24 -08003271 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003272 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003273 Use 'devices' function to obtain list of all devices
3274 and parse the result to obtain a list of all device
3275 id's. Returns this list. Returns empty list if no
3276 devices exist
kelvin8ec71442015-01-15 16:57:00 -08003277 List is ordered sequentially
3278
andrewonlab3e15ead2014-10-15 14:21:34 -04003279 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08003280 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04003281 the ids. By obtaining the list of device ids on the fly,
3282 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08003283 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003284 try:
kelvin8ec71442015-01-15 16:57:00 -08003285 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08003286 devicesStr = self.devices( jsonFormat=False )
3287 idList = []
kelvin8ec71442015-01-15 16:57:00 -08003288
kelvin-onlabd3b64892015-01-20 13:26:24 -08003289 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08003290 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003291 return idList
kelvin8ec71442015-01-15 16:57:00 -08003292
3293 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08003294 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08003295 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08003296 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08003297 # Split list further into arguments before and after string
3298 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08003299 # append to idList
3300 for arg in tempList:
3301 idList.append( arg.split( "id=" )[ 1 ] )
3302 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04003303
Jon Halld4d4b372015-01-28 16:02:41 -08003304 except TypeError:
3305 main.log.exception( self.name + ": Object not as expected" )
3306 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04003307 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003308 main.log.error( self.name + ": EOF exception found" )
3309 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003310 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003311 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003312 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003313 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003314
kelvin-onlabd3b64892015-01-20 13:26:24 -08003315 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003316 """
andrewonlab7c211572014-10-15 16:45:20 -04003317 Uses 'nodes' function to obtain list of all nodes
3318 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08003319 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04003320 Returns:
3321 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08003322 """
andrewonlab7c211572014-10-15 16:45:20 -04003323 try:
Jon Hall5aa168b2015-03-23 14:23:09 -07003324 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003325 idList = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003326 # Sample nodesStr output
Jon Hallbd182782016-03-28 16:42:22 -07003327 # id=local, address=127.0.0.1:9876, state=READY *
kelvin-onlabd3b64892015-01-20 13:26:24 -08003328 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08003329 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003330 return idList
Jon Hall5aa168b2015-03-23 14:23:09 -07003331 nodesJson = json.loads( nodesStr )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003332 idList = [ node.get( 'id' ) for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08003333 return idList
Jon Hallc6793552016-01-19 14:18:37 -08003334 except ( TypeError, ValueError ):
3335 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, nodesStr ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003336 return None
andrewonlab7c211572014-10-15 16:45:20 -04003337 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003338 main.log.error( self.name + ": EOF exception found" )
3339 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003340 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003341 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003342 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003343 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003344
kelvin-onlabd3b64892015-01-20 13:26:24 -08003345 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08003346 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003347 Return the first device from the devices api whose 'id' contains 'dpid'
3348 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08003349 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003350 try:
kelvin8ec71442015-01-15 16:57:00 -08003351 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04003352 return None
3353 else:
kelvin8ec71442015-01-15 16:57:00 -08003354 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003355 rawDevices = self.devices()
3356 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08003357 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08003358 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08003359 # print "%s in %s?" % ( dpid, device[ 'id' ] )
3360 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04003361 return device
3362 return None
Jon Hallc6793552016-01-19 14:18:37 -08003363 except ( TypeError, ValueError ):
3364 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawDevices ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003365 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04003366 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003367 main.log.error( self.name + ": EOF exception found" )
3368 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003369 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003370 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003371 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003372 main.cleanAndExit()
Jon Halla91c4dc2014-10-22 12:57:04 -04003373
You Wang24139872016-05-03 11:48:47 -07003374 def getTopology( self, topologyOutput ):
3375 """
3376 Definition:
3377 Loads a json topology output
3378 Return:
3379 topology = current ONOS topology
3380 """
You Wang24139872016-05-03 11:48:47 -07003381 try:
3382 # either onos:topology or 'topology' will work in CLI
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003383 topology = json.loads( topologyOutput )
Jeremy Songsterbc2d8ac2016-05-04 11:25:42 -07003384 main.log.debug( topology )
You Wang24139872016-05-03 11:48:47 -07003385 return topology
You Wangd3cb2ce2016-05-16 14:01:24 -07003386 except ( TypeError, ValueError ):
3387 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, topologyOutput ) )
3388 return None
You Wang24139872016-05-03 11:48:47 -07003389 except pexpect.EOF:
3390 main.log.error( self.name + ": EOF exception found" )
3391 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003392 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003393 except Exception:
3394 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003395 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003396
Jon Hall39570262020-11-17 12:18:19 -08003397 def checkStatus( self, numoswitch, numolink = -1, numoctrl = -1, numoSCCs=1, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08003398 """
Jon Hallefbd9792015-03-05 16:11:36 -08003399 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08003400 supplied values. By default this will report to main.log, but the
You Wang24139872016-05-03 11:48:47 -07003401 log level can be specific.
kelvin8ec71442015-01-15 16:57:00 -08003402
Flavio Castro82ee2f62016-06-07 15:04:12 -07003403 Params: numoswitch = expected number of switches
Jon Hallefbd9792015-03-05 16:11:36 -08003404 numolink = expected number of links
Flavio Castro82ee2f62016-06-07 15:04:12 -07003405 numoctrl = expected number of controllers
Jon Hall39570262020-11-17 12:18:19 -08003406 numoSCCs = Number of expected SCCs
You Wang24139872016-05-03 11:48:47 -07003407 logLevel = level to log to.
3408 Currently accepts 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04003409
Jon Hallefbd9792015-03-05 16:11:36 -08003410 Returns: main.TRUE if the number of switches and links are correct,
3411 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04003412 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08003413 """
Jon Hall42db6dc2014-10-24 19:03:48 -04003414 try:
You Wang13310252016-07-31 10:56:14 -07003415 summary = self.summary()
3416 summary = json.loads( summary )
Flavio Castrof5b3f872016-06-23 17:52:31 -07003417 except ( TypeError, ValueError ):
3418 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summary ) )
3419 return main.ERROR
3420 try:
3421 topology = self.getTopology( self.topology() )
Jon Halle0f0b342017-04-18 11:43:47 -07003422 if topology == {} or topology is None or summary == {} or summary is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04003423 return main.ERROR
3424 output = ""
kelvin8ec71442015-01-15 16:57:00 -08003425 # Is the number of switches is what we expected
3426 devices = topology.get( 'devices', False )
3427 links = topology.get( 'links', False )
Flavio Castro82ee2f62016-06-07 15:04:12 -07003428 nodes = summary.get( 'nodes', False )
Jon Hall39570262020-11-17 12:18:19 -08003429 SCCs = summary.get( 'SCC(s)', False )
3430 if devices is False or links is False or nodes is False or SCCs is False:
3431 main.log.warn( "Issues parsing topology and summary output" )
3432 main.log.debug( topology )
3433 main.log.debug( summary )
Jon Hall42db6dc2014-10-24 19:03:48 -04003434 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08003435 switchCheck = ( int( devices ) == int( numoswitch ) )
Jon Hall39570262020-11-17 12:18:19 -08003436 if not switchCheck:
3437 main.log.debug( "switch Check Failed" )
Pier6a0c4de2018-03-18 16:01:30 -07003438 linkCheck = ( int( links ) == int( numolink ) ) or int( numolink ) == -1
Jon Hall39570262020-11-17 12:18:19 -08003439 if not linkCheck:
3440 main.log.debug( "link Check Failed" )
Flavio Castro82ee2f62016-06-07 15:04:12 -07003441 nodeCheck = ( int( nodes ) == int( numoctrl ) ) or int( numoctrl ) == -1
Jon Hall39570262020-11-17 12:18:19 -08003442 if not nodeCheck:
3443 main.log.debug( "node Check Failed" )
3444 SCCsCheck = ( int( SCCs ) == int( numoSCCs ) ) or int( numoSCCs ) == -1
3445 if not SCCsCheck:
3446 main.log.debug( "SCCs Check Failed" )
3447 if switchCheck and linkCheck and nodeCheck and SCCsCheck:
kelvin8ec71442015-01-15 16:57:00 -08003448 # We expected the correct numbers
Jon Hall39570262020-11-17 12:18:19 -08003449 output = output + "The number of links, switches, nodes, and SCCs match "\
You Wang24139872016-05-03 11:48:47 -07003450 + "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003451 result = main.TRUE
3452 else:
You Wang24139872016-05-03 11:48:47 -07003453 output = output + \
Jon Hall627b1572020-12-01 12:01:15 -08003454 "The number of links, switches, nodes, and SCCs does not match " + \
You Wang24139872016-05-03 11:48:47 -07003455 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003456 result = main.FALSE
Jon Hall39570262020-11-17 12:18:19 -08003457 output = output + "\n ONOS sees %i devices " % int( devices )
3458 output = output + "(%i expected) " % int( numoswitch )
3459 if int( numolink ) >= 0:
Pier6a0c4de2018-03-18 16:01:30 -07003460 output = output + "and %i links " % int( links )
Jon Hall39570262020-11-17 12:18:19 -08003461 output = output + "(%i expected) " % int( numolink )
3462 if int( numoctrl ) >= 0:
Flavio Castro82ee2f62016-06-07 15:04:12 -07003463 output = output + "and %i controllers " % int( nodes )
Jon Hall39570262020-11-17 12:18:19 -08003464 output = output + "(%i expected) " % int( numoctrl )
3465 if int( numoSCCs ) >= 0:
3466 output = output + "and %i SCCs " % int( SCCs )
3467 output = output + "(%i expected)" % int( numoSCCs )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003468 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08003469 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003470 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08003471 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04003472 else:
You Wang24139872016-05-03 11:48:47 -07003473 main.log.info( output )
Jon Hall39570262020-11-17 12:18:19 -08003474 main.TOPOOUTPUT = output
kelvin8ec71442015-01-15 16:57:00 -08003475 return result
Jon Hall42db6dc2014-10-24 19:03:48 -04003476 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003477 main.log.error( self.name + ": EOF exception found" )
3478 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003479 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003480 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003481 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003482 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003483
kelvin-onlabd3b64892015-01-20 13:26:24 -08003484 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08003485 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003486 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08003487 deviceId must be the id of a device as seen in the onos devices command
3488 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04003489 role must be either master, standby, or none
3490
Jon Halle3f39ff2015-01-13 11:50:53 -08003491 Returns:
3492 main.TRUE or main.FALSE based on argument verification and
3493 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003494 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003495 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003496 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04003497 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08003498 cmdStr = "device-role " +\
3499 str( deviceId ) + " " +\
3500 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003501 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003502 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003503 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003504 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08003505 if re.search( "Error", handle ):
3506 # end color output to escape any colours
3507 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08003508 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003509 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08003510 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08003511 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04003512 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003513 main.log.error( "Invalid 'role' given to device_role(). " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003514 "Value was '" + str( role ) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04003515 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003516 except AssertionError:
3517 main.log.exception( "" )
3518 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003519 except TypeError:
3520 main.log.exception( self.name + ": Object not as expected" )
3521 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04003522 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003523 main.log.error( self.name + ": EOF exception found" )
3524 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003525 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003526 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003527 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003528 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003529
kelvin-onlabd3b64892015-01-20 13:26:24 -08003530 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08003531 """
Jon Hall0dd09952018-04-19 09:59:11 -07003532 Lists all topology clusters
Jon Hallffb386d2014-11-21 13:43:38 -08003533 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003534 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08003535 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08003536 try:
Jon Hall0dd09952018-04-19 09:59:11 -07003537 cmdStr = "topo-clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003538 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003539 cmdStr += " -j"
3540 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003541 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003542 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07003543 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003544 except AssertionError:
3545 main.log.exception( "" )
3546 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003547 except TypeError:
3548 main.log.exception( self.name + ": Object not as expected" )
3549 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08003550 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003551 main.log.error( self.name + ": EOF exception found" )
3552 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003553 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003554 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003555 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003556 main.cleanAndExit()
Jon Hall73cf9cc2014-11-20 22:28:38 -08003557
kelvin-onlabd3b64892015-01-20 13:26:24 -08003558 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003559 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003560 CLI command to get the current leader for the Election test application
3561 NOTE: Requires installation of the onos-app-election feature
3562 Returns: Node IP of the leader if one exists
3563 None if none exists
3564 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003565 """
Jon Hall94fd0472014-12-08 11:52:42 -08003566 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003567 cmdStr = "election-test-leader"
3568 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003569 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003570 assert "Command not found:" not in response, response
Jon Halle3f39ff2015-01-13 11:50:53 -08003571 # Leader
3572 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003573 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08003574 nodeSearch = re.search( leaderPattern, response )
3575 if nodeSearch:
3576 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08003577 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003578 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08003579 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08003580 # no leader
3581 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003582 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003583 nullSearch = re.search( nullPattern, response )
3584 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08003585 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003586 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08003587 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08003588 # error
Jon Hall0e240372018-05-02 11:21:57 -07003589 main.log.error( self.name + ": Error in electionTestLeader on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003590 ": " + "unexpected response" )
3591 main.log.error( repr( response ) )
3592 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003593 except AssertionError:
3594 main.log.exception( "" )
3595 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003596 except TypeError:
3597 main.log.exception( self.name + ": Object not as expected" )
3598 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003599 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003600 main.log.error( self.name + ": EOF exception found" )
3601 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003602 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003603 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003604 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003605 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003606
kelvin-onlabd3b64892015-01-20 13:26:24 -08003607 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003608 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003609 CLI command to run for leadership of the Election test application.
3610 NOTE: Requires installation of the onos-app-election feature
3611 Returns: Main.TRUE on success
3612 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003613 """
Jon Hall94fd0472014-12-08 11:52:42 -08003614 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003615 cmdStr = "election-test-run"
3616 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003617 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003618 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003619 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003620 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003621 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003622 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08003623 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08003624 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003625 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003626 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003627 # error
Jon Hall0e240372018-05-02 11:21:57 -07003628 main.log.error( self.name + ": Error in electionTestRun on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003629 ": " + "unexpected response" )
3630 main.log.error( repr( response ) )
3631 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003632 except AssertionError:
3633 main.log.exception( "" )
3634 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003635 except TypeError:
3636 main.log.exception( self.name + ": Object not as expected" )
3637 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003638 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003639 main.log.error( self.name + ": EOF exception found" )
3640 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003641 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003642 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003643 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003644 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003645
kelvin-onlabd3b64892015-01-20 13:26:24 -08003646 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08003647 """
Jon Hall94fd0472014-12-08 11:52:42 -08003648 * CLI command to withdraw the local node from leadership election for
3649 * the Election test application.
3650 #NOTE: Requires installation of the onos-app-election feature
3651 Returns: Main.TRUE on success
3652 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08003653 """
Jon Hall94fd0472014-12-08 11:52:42 -08003654 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003655 cmdStr = "election-test-withdraw"
3656 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003657 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003658 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003659 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003660 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003661 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003662 if re.search( successPattern, response ):
3663 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003664 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003665 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003666 # error
Jon Hall0e240372018-05-02 11:21:57 -07003667 main.log.error( self.name + ": Error in electionTestWithdraw on " +
Jon Hall97cf84a2016-06-20 13:35:58 -07003668 self.name + ": " + "unexpected response" )
3669 main.log.error( repr( response ) )
3670 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003671 except AssertionError:
3672 main.log.exception( "" )
3673 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003674 except TypeError:
3675 main.log.exception( self.name + ": Object not as expected" )
3676 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003677 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003678 main.log.error( self.name + ": EOF exception found" )
3679 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003680 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003681 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003682 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003683 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003684
kelvin8ec71442015-01-15 16:57:00 -08003685 def getDevicePortsEnabledCount( self, dpid ):
3686 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003687 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003688 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003689 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003690 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003691 cmdStr = "onos:ports -e " + dpid + " | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003692 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003693 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003694 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003695 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003696 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003697 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003698 return output
Jon Hallc6793552016-01-19 14:18:37 -08003699 except AssertionError:
3700 main.log.exception( "" )
3701 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003702 except TypeError:
3703 main.log.exception( self.name + ": Object not as expected" )
3704 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003705 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003706 main.log.error( self.name + ": EOF exception found" )
3707 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003708 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003709 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003710 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003711 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003712
kelvin8ec71442015-01-15 16:57:00 -08003713 def getDeviceLinksActiveCount( self, dpid ):
3714 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003715 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003716 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003717 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003718 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003719 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003720 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003721 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003722 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003723 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003724 main.log.error( self.name + ": Error in getting ports " )
kelvin-onlab898a6c62015-01-16 14:13:53 -08003725 return ( output, "Error " )
Jon Halla495f562016-05-16 18:03:26 -07003726 return output
Jon Hallc6793552016-01-19 14:18:37 -08003727 except AssertionError:
3728 main.log.exception( "" )
3729 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003730 except TypeError:
3731 main.log.exception( self.name + ": Object not as expected" )
3732 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003733 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003734 main.log.error( self.name + ": EOF exception found" )
3735 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003736 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003737 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003738 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003739 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003740
kelvin8ec71442015-01-15 16:57:00 -08003741 def getAllIntentIds( self ):
3742 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003743 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08003744 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003745 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003746 cmdStr = "onos:intents | grep id="
3747 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003748 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003749 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003750 if re.search( "Error", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003751 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003752 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003753 return output
Jon Hallc6793552016-01-19 14:18:37 -08003754 except AssertionError:
3755 main.log.exception( "" )
3756 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003757 except TypeError:
3758 main.log.exception( self.name + ": Object not as expected" )
3759 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003760 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003761 main.log.error( self.name + ": EOF exception found" )
3762 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003763 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003764 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003765 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003766 main.cleanAndExit()
Jon Halld4d4b372015-01-28 16:02:41 -08003767
Jon Hall73509952015-02-24 16:42:56 -08003768 def intentSummary( self ):
3769 """
Jon Hallefbd9792015-03-05 16:11:36 -08003770 Returns a dictionary containing the current intent states and the count
Jon Hall73509952015-02-24 16:42:56 -08003771 """
3772 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003773 intents = self.intents( )
Jon Hall08f61bc2015-04-13 16:00:30 -07003774 states = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003775 for intent in json.loads( intents ):
Jon Hall08f61bc2015-04-13 16:00:30 -07003776 states.append( intent.get( 'state', None ) )
3777 out = [ ( i, states.count( i ) ) for i in set( states ) ]
Jon Hall63604932015-02-26 17:09:50 -08003778 main.log.info( dict( out ) )
Jon Hall73509952015-02-24 16:42:56 -08003779 return dict( out )
Jon Hallc6793552016-01-19 14:18:37 -08003780 except ( TypeError, ValueError ):
3781 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intents ) )
Jon Hall73509952015-02-24 16:42:56 -08003782 return None
3783 except pexpect.EOF:
3784 main.log.error( self.name + ": EOF exception found" )
3785 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003786 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003787 except Exception:
Jon Hall73509952015-02-24 16:42:56 -08003788 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003789 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003790
Jon Hall61282e32015-03-19 11:34:11 -07003791 def leaders( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003792 """
3793 Returns the output of the leaders command.
Jon Hall61282e32015-03-19 11:34:11 -07003794 Optional argument:
3795 * jsonFormat - boolean indicating if you want output in json
Jon Hall63604932015-02-26 17:09:50 -08003796 """
Jon Hall63604932015-02-26 17:09:50 -08003797 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003798 cmdStr = "onos:leaders"
Jon Hall61282e32015-03-19 11:34:11 -07003799 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003800 cmdStr += " -j"
3801 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003802 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003803 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003804 return output
Jon Hallc6793552016-01-19 14:18:37 -08003805 except AssertionError:
3806 main.log.exception( "" )
3807 return None
Jon Hall63604932015-02-26 17:09:50 -08003808 except TypeError:
3809 main.log.exception( self.name + ": Object not as expected" )
3810 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003811 except pexpect.EOF:
3812 main.log.error( self.name + ": EOF exception found" )
3813 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003814 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003815 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003816 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003817 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003818
acsmarsa4a4d1e2015-07-10 16:01:24 -07003819 def leaderCandidates( self, jsonFormat=True ):
3820 """
3821 Returns the output of the leaders -c command.
3822 Optional argument:
3823 * jsonFormat - boolean indicating if you want output in json
3824 """
3825 try:
3826 cmdStr = "onos:leaders -c"
3827 if jsonFormat:
3828 cmdStr += " -j"
3829 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003830 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003831 assert "Command not found:" not in output, output
acsmarsa4a4d1e2015-07-10 16:01:24 -07003832 return output
Jon Hallc6793552016-01-19 14:18:37 -08003833 except AssertionError:
3834 main.log.exception( "" )
3835 return None
acsmarsa4a4d1e2015-07-10 16:01:24 -07003836 except TypeError:
3837 main.log.exception( self.name + ": Object not as expected" )
3838 return None
3839 except pexpect.EOF:
3840 main.log.error( self.name + ": EOF exception found" )
3841 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003842 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003843 except Exception:
3844 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003845 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003846
Jon Hallc6793552016-01-19 14:18:37 -08003847 def specificLeaderCandidate( self, topic ):
acsmarsa4a4d1e2015-07-10 16:01:24 -07003848 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003849 Returns a list in format [leader,candidate1,candidate2,...] for a given
acsmarsa4a4d1e2015-07-10 16:01:24 -07003850 topic parameter and an empty list if the topic doesn't exist
3851 If no leader is elected leader in the returned list will be "none"
3852 Returns None if there is a type error processing the json object
3853 """
3854 try:
Jon Hall6e709752016-02-01 13:38:46 -08003855 cmdStr = "onos:leaders -j"
Jon Hallc6793552016-01-19 14:18:37 -08003856 rawOutput = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003857 assert rawOutput is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003858 assert "Command not found:" not in rawOutput, rawOutput
3859 output = json.loads( rawOutput )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003860 results = []
3861 for dict in output:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003862 if dict[ "topic" ] == topic:
3863 leader = dict[ "leader" ]
3864 candidates = re.split( ", ", dict[ "candidates" ][ 1:-1 ] )
Jon Hallc6793552016-01-19 14:18:37 -08003865 results.append( leader )
3866 results.extend( candidates )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003867 return results
Jon Hallc6793552016-01-19 14:18:37 -08003868 except AssertionError:
3869 main.log.exception( "" )
3870 return None
3871 except ( TypeError, ValueError ):
3872 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawOutput ) )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003873 return None
3874 except pexpect.EOF:
3875 main.log.error( self.name + ": EOF exception found" )
3876 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003877 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003878 except Exception:
3879 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003880 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003881
Jon Hall61282e32015-03-19 11:34:11 -07003882 def pendingMap( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003883 """
3884 Returns the output of the intent Pending map.
3885 """
Jon Hall63604932015-02-26 17:09:50 -08003886 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003887 cmdStr = "onos:intents -p"
Jon Hall61282e32015-03-19 11:34:11 -07003888 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003889 cmdStr += " -j"
3890 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003891 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003892 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003893 return output
Jon Hallc6793552016-01-19 14:18:37 -08003894 except AssertionError:
3895 main.log.exception( "" )
3896 return None
Jon Hall63604932015-02-26 17:09:50 -08003897 except TypeError:
3898 main.log.exception( self.name + ": Object not as expected" )
3899 return None
3900 except pexpect.EOF:
3901 main.log.error( self.name + ": EOF exception found" )
3902 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003903 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003904 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003905 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003906 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003907
Jon Hall2c8959e2016-12-16 12:17:34 -08003908 def partitions( self, candidates=False, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003909 """
3910 Returns the output of the raft partitions command for ONOS.
3911 """
Jon Hall61282e32015-03-19 11:34:11 -07003912 # Sample JSON
3913 # {
3914 # "leader": "tcp://10.128.30.11:7238",
3915 # "members": [
3916 # "tcp://10.128.30.11:7238",
3917 # "tcp://10.128.30.17:7238",
3918 # "tcp://10.128.30.13:7238",
3919 # ],
3920 # "name": "p1",
3921 # "term": 3
3922 # },
Jon Hall63604932015-02-26 17:09:50 -08003923 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003924 cmdStr = "onos:partitions"
Jon Hall2c8959e2016-12-16 12:17:34 -08003925 if candidates:
3926 cmdStr += " -c"
Jon Hall61282e32015-03-19 11:34:11 -07003927 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003928 cmdStr += " -j"
3929 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003930 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003931 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003932 return output
Jon Hallc6793552016-01-19 14:18:37 -08003933 except AssertionError:
3934 main.log.exception( "" )
3935 return None
Jon Hall63604932015-02-26 17:09:50 -08003936 except TypeError:
3937 main.log.exception( self.name + ": Object not as expected" )
3938 return None
3939 except pexpect.EOF:
3940 main.log.error( self.name + ": EOF exception found" )
3941 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003942 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003943 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003944 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003945 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003946
Jon Halle9f909e2016-09-23 10:43:12 -07003947 def apps( self, summary=False, active=False, jsonFormat=True ):
Jon Hallbe379602015-03-24 13:39:32 -07003948 """
3949 Returns the output of the apps command for ONOS. This command lists
3950 information about installed ONOS applications
3951 """
3952 # Sample JSON object
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003953 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
Jon Hallbe379602015-03-24 13:39:32 -07003954 # "description":"ONOS OpenFlow protocol southbound providers",
3955 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003956 # "features":"[onos-openflow]","state":"ACTIVE"}]
Jon Hallbe379602015-03-24 13:39:32 -07003957 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003958 cmdStr = "onos:apps"
Jon Hallf03ae762019-01-22 13:25:27 -08003959 expectJson = False
Jon Halle9f909e2016-09-23 10:43:12 -07003960 if summary:
3961 cmdStr += " -s"
3962 if active:
3963 cmdStr += " -a"
Jon Hallbe379602015-03-24 13:39:32 -07003964 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003965 cmdStr += " -j"
Jon Hallf03ae762019-01-22 13:25:27 -08003966 expectJson = True
3967 output = self.sendline( cmdStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07003968 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003969 assert "Command not found:" not in output, output
3970 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003971 return output
Jon Hallbe379602015-03-24 13:39:32 -07003972 # FIXME: look at specific exceptions/Errors
3973 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07003974 main.log.exception( self.name + ": Error in processing onos:app command." )
Jon Hallbe379602015-03-24 13:39:32 -07003975 return None
3976 except TypeError:
3977 main.log.exception( self.name + ": Object not as expected" )
3978 return None
3979 except pexpect.EOF:
3980 main.log.error( self.name + ": EOF exception found" )
3981 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003982 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003983 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003984 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003985 main.cleanAndExit()
Jon Hallbe379602015-03-24 13:39:32 -07003986
You Wangcdc51fe2018-08-12 17:14:56 -07003987 def appStatus( self, appName ):
Jon Hall146f1522015-03-24 15:33:24 -07003988 """
3989 Uses the onos:apps cli command to return the status of an application.
3990 Returns:
3991 "ACTIVE" - If app is installed and activated
3992 "INSTALLED" - If app is installed and deactivated
3993 "UNINSTALLED" - If app is not installed
3994 None - on error
3995 """
Jon Hall146f1522015-03-24 15:33:24 -07003996 try:
3997 if not isinstance( appName, types.StringType ):
3998 main.log.error( self.name + ".appStatus(): appName must be" +
3999 " a string" )
4000 return None
4001 output = self.apps( jsonFormat=True )
4002 appsJson = json.loads( output )
4003 state = None
4004 for app in appsJson:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004005 if appName == app.get( 'name' ):
4006 state = app.get( 'state' )
Jon Hall146f1522015-03-24 15:33:24 -07004007 break
4008 if state == "ACTIVE" or state == "INSTALLED":
4009 return state
4010 elif state is None:
You Wang0d9f2c02018-08-10 14:56:32 -07004011 main.log.warn( "{} app not found".format( appName ) )
Jon Hall146f1522015-03-24 15:33:24 -07004012 return "UNINSTALLED"
4013 elif state:
4014 main.log.error( "Unexpected state from 'onos:apps': " +
4015 str( state ) )
4016 return state
Jon Hallc6793552016-01-19 14:18:37 -08004017 except ( TypeError, ValueError ):
4018 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, output ) )
Jon Hall146f1522015-03-24 15:33:24 -07004019 return None
4020 except pexpect.EOF:
4021 main.log.error( self.name + ": EOF exception found" )
4022 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004023 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004024 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004025 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004026 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004027
Jon Hallbe379602015-03-24 13:39:32 -07004028 def app( self, appName, option ):
4029 """
4030 Interacts with the app command for ONOS. This command manages
4031 application inventory.
4032 """
Jon Hallbe379602015-03-24 13:39:32 -07004033 try:
Jon Hallbd16b922015-03-26 17:53:15 -07004034 # Validate argument types
4035 valid = True
4036 if not isinstance( appName, types.StringType ):
4037 main.log.error( self.name + ".app(): appName must be a " +
4038 "string" )
4039 valid = False
4040 if not isinstance( option, types.StringType ):
4041 main.log.error( self.name + ".app(): option must be a string" )
4042 valid = False
4043 if not valid:
4044 return main.FALSE
4045 # Validate Option
4046 option = option.lower()
4047 # NOTE: Install may become a valid option
4048 if option == "activate":
4049 pass
4050 elif option == "deactivate":
4051 pass
4052 elif option == "uninstall":
4053 pass
4054 else:
4055 # Invalid option
4056 main.log.error( "The ONOS app command argument only takes " +
4057 "the values: (activate|deactivate|uninstall)" +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004058 "; was given '" + option + "'" )
Jon Hallbd16b922015-03-26 17:53:15 -07004059 return main.FALSE
Jon Hall146f1522015-03-24 15:33:24 -07004060 cmdStr = "onos:app " + option + " " + appName
Jon Hallbe379602015-03-24 13:39:32 -07004061 output = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08004062 assert output is not None, "Error in sendline"
4063 assert "Command not found:" not in output, output
Jon Hallbe379602015-03-24 13:39:32 -07004064 if "Error executing command" in output:
Jon Hall0e240372018-05-02 11:21:57 -07004065 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hallbe379602015-03-24 13:39:32 -07004066 str( output ) )
Jon Hall146f1522015-03-24 15:33:24 -07004067 return main.FALSE
Jon Hallbe379602015-03-24 13:39:32 -07004068 elif "No such application" in output:
4069 main.log.error( "The application '" + appName +
4070 "' is not installed in ONOS" )
Jon Hall146f1522015-03-24 15:33:24 -07004071 return main.FALSE
4072 elif "Command not found:" in output:
Jon Hall0e240372018-05-02 11:21:57 -07004073 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hall146f1522015-03-24 15:33:24 -07004074 str( output ) )
4075 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07004076 elif "Unsupported command:" in output:
4077 main.log.error( "Incorrect command given to 'app': " +
4078 str( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07004079 # NOTE: we may need to add more checks here
Jon Hallbd16b922015-03-26 17:53:15 -07004080 # else: Command was successful
Jon Hall08f61bc2015-04-13 16:00:30 -07004081 # main.log.debug( "app response: " + repr( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07004082 return main.TRUE
You Wangb5a55f72017-03-03 12:51:05 -08004083 except AssertionError:
4084 main.log.exception( self.name + ": AssertionError exception found" )
4085 return main.ERROR
Jon Hallbe379602015-03-24 13:39:32 -07004086 except TypeError:
4087 main.log.exception( self.name + ": Object not as expected" )
4088 return main.ERROR
4089 except pexpect.EOF:
4090 main.log.error( self.name + ": EOF exception found" )
4091 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004092 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004093 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07004094 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004095 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004096
Jon Hallbd16b922015-03-26 17:53:15 -07004097 def activateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004098 """
4099 Activate an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004100 appName is the hierarchical app name, not the feature name
4101 If check is True, method will check the status of the app after the
4102 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004103 Returns main.TRUE if the command was successfully sent
4104 main.FALSE if the cli responded with an error or given
4105 incorrect input
4106 """
4107 try:
4108 if not isinstance( appName, types.StringType ):
4109 main.log.error( self.name + ".activateApp(): appName must be" +
4110 " a string" )
4111 return main.FALSE
4112 status = self.appStatus( appName )
4113 if status == "INSTALLED":
4114 response = self.app( appName, "activate" )
Jon Hallbd16b922015-03-26 17:53:15 -07004115 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004116 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004117 status = self.appStatus( appName )
4118 if status == "ACTIVE":
4119 return main.TRUE
4120 else:
Jon Hall050e1bd2015-03-30 13:33:02 -07004121 main.log.debug( "The state of application " +
4122 appName + " is " + status )
Jon Hallbd16b922015-03-26 17:53:15 -07004123 time.sleep( 1 )
4124 return main.FALSE
4125 else: # not 'check' or command didn't succeed
4126 return response
Jon Hall146f1522015-03-24 15:33:24 -07004127 elif status == "ACTIVE":
4128 return main.TRUE
4129 elif status == "UNINSTALLED":
4130 main.log.error( self.name + ": Tried to activate the " +
4131 "application '" + appName + "' which is not " +
4132 "installed." )
4133 else:
4134 main.log.error( "Unexpected return value from appStatus: " +
4135 str( status ) )
4136 return main.ERROR
4137 except TypeError:
4138 main.log.exception( self.name + ": Object not as expected" )
4139 return main.ERROR
4140 except pexpect.EOF:
4141 main.log.error( self.name + ": EOF exception found" )
4142 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004143 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004144 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004145 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004146 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004147
Jon Hallbd16b922015-03-26 17:53:15 -07004148 def deactivateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004149 """
4150 Deactivate an app that is already activated in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004151 appName is the hierarchical app name, not the feature name
4152 If check is True, method will check the status of the app after the
4153 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004154 Returns main.TRUE if the command was successfully sent
4155 main.FALSE if the cli responded with an error or given
4156 incorrect input
4157 """
4158 try:
4159 if not isinstance( appName, types.StringType ):
4160 main.log.error( self.name + ".deactivateApp(): appName must " +
4161 "be a string" )
4162 return main.FALSE
4163 status = self.appStatus( appName )
4164 if status == "INSTALLED":
4165 return main.TRUE
4166 elif status == "ACTIVE":
4167 response = self.app( appName, "deactivate" )
Jon Hallbd16b922015-03-26 17:53:15 -07004168 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004169 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004170 status = self.appStatus( appName )
4171 if status == "INSTALLED":
4172 return main.TRUE
4173 else:
4174 time.sleep( 1 )
4175 return main.FALSE
4176 else: # not check or command didn't succeed
4177 return response
Jon Hall146f1522015-03-24 15:33:24 -07004178 elif status == "UNINSTALLED":
4179 main.log.warn( self.name + ": Tried to deactivate the " +
4180 "application '" + appName + "' which is not " +
4181 "installed." )
4182 return main.TRUE
4183 else:
4184 main.log.error( "Unexpected return value from appStatus: " +
4185 str( status ) )
4186 return main.ERROR
4187 except TypeError:
4188 main.log.exception( self.name + ": Object not as expected" )
4189 return main.ERROR
4190 except pexpect.EOF:
4191 main.log.error( self.name + ": EOF exception found" )
4192 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004193 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004194 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004195 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004196 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004197
Jon Hallbd16b922015-03-26 17:53:15 -07004198 def uninstallApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004199 """
4200 Uninstall an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004201 appName is the hierarchical app name, not the feature name
4202 If check is True, method will check the status of the app after the
4203 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004204 Returns main.TRUE if the command was successfully sent
4205 main.FALSE if the cli responded with an error or given
4206 incorrect input
4207 """
4208 # TODO: check with Thomas about the state machine for apps
4209 try:
4210 if not isinstance( appName, types.StringType ):
4211 main.log.error( self.name + ".uninstallApp(): appName must " +
4212 "be a string" )
4213 return main.FALSE
4214 status = self.appStatus( appName )
4215 if status == "INSTALLED":
4216 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004217 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004218 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004219 status = self.appStatus( appName )
4220 if status == "UNINSTALLED":
4221 return main.TRUE
4222 else:
4223 time.sleep( 1 )
4224 return main.FALSE
4225 else: # not check or command didn't succeed
4226 return response
Jon Hall146f1522015-03-24 15:33:24 -07004227 elif status == "ACTIVE":
4228 main.log.warn( self.name + ": Tried to uninstall the " +
4229 "application '" + appName + "' which is " +
4230 "currently active." )
4231 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004232 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004233 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004234 status = self.appStatus( appName )
4235 if status == "UNINSTALLED":
4236 return main.TRUE
4237 else:
4238 time.sleep( 1 )
4239 return main.FALSE
4240 else: # not check or command didn't succeed
4241 return response
Jon Hall146f1522015-03-24 15:33:24 -07004242 elif status == "UNINSTALLED":
4243 return main.TRUE
4244 else:
4245 main.log.error( "Unexpected return value from appStatus: " +
4246 str( status ) )
4247 return main.ERROR
4248 except TypeError:
4249 main.log.exception( self.name + ": Object not as expected" )
4250 return main.ERROR
4251 except pexpect.EOF:
4252 main.log.error( self.name + ": EOF exception found" )
4253 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004254 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004255 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004256 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004257 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004258
4259 def appIDs( self, jsonFormat=True ):
4260 """
4261 Show the mappings between app id and app names given by the 'app-ids'
4262 cli command
4263 """
4264 try:
4265 cmdStr = "app-ids"
4266 if jsonFormat:
4267 cmdStr += " -j"
Jon Hallc6358dd2015-04-10 12:44:28 -07004268 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004269 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004270 assert "Command not found:" not in output, output
4271 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07004272 return output
Jon Hallbd16b922015-03-26 17:53:15 -07004273 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004274 main.log.exception( self.name + ": Error in processing onos:app-ids command." )
Jon Hallbd16b922015-03-26 17:53:15 -07004275 return None
4276 except TypeError:
4277 main.log.exception( self.name + ": Object not as expected" )
4278 return None
4279 except pexpect.EOF:
4280 main.log.error( self.name + ": EOF exception found" )
4281 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004282 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004283 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004284 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004285 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004286
4287 def appToIDCheck( self ):
4288 """
4289 This method will check that each application's ID listed in 'apps' is
4290 the same as the ID listed in 'app-ids'. The check will also check that
4291 there are no duplicate IDs issued. Note that an app ID should be
4292 a globaly unique numerical identifier for app/app-like features. Once
4293 an ID is registered, the ID is never freed up so that if an app is
4294 reinstalled it will have the same ID.
4295
4296 Returns: main.TRUE if the check passes and
4297 main.FALSE if the check fails or
4298 main.ERROR if there is some error in processing the test
4299 """
4300 try:
Jon Hall0e240372018-05-02 11:21:57 -07004301 # Grab IDs
Jon Hallc6793552016-01-19 14:18:37 -08004302 rawJson = self.appIDs( jsonFormat=True )
4303 if rawJson:
4304 ids = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004305 else:
Jon Hall0e240372018-05-02 11:21:57 -07004306 main.log.error( "app-ids returned nothing: " + repr( rawJson ) )
4307 return main.FALSE
4308
4309 # Grab Apps
Jon Hallc6793552016-01-19 14:18:37 -08004310 rawJson = self.apps( jsonFormat=True )
4311 if rawJson:
4312 apps = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004313 else:
Jon Hallc6793552016-01-19 14:18:37 -08004314 main.log.error( "apps returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07004315 return main.FALSE
Jon Hall0e240372018-05-02 11:21:57 -07004316
Jon Hallbd16b922015-03-26 17:53:15 -07004317 result = main.TRUE
4318 for app in apps:
4319 appID = app.get( 'id' )
4320 if appID is None:
4321 main.log.error( "Error parsing app: " + str( app ) )
4322 result = main.FALSE
4323 appName = app.get( 'name' )
4324 if appName is None:
4325 main.log.error( "Error parsing app: " + str( app ) )
4326 result = main.FALSE
4327 # get the entry in ids that has the same appID
Jon Hall390696c2015-05-05 17:13:41 -07004328 current = filter( lambda item: item[ 'id' ] == appID, ids )
Jon Hallbd16b922015-03-26 17:53:15 -07004329 if not current: # if ids doesn't have this id
4330 result = main.FALSE
4331 main.log.error( "'app-ids' does not have the ID for " +
4332 str( appName ) + " that apps does." )
Jon Hallb9d381e2018-02-05 12:02:10 -08004333 main.log.debug( "apps command returned: " + str( app ) +
4334 "; app-ids has: " + str( ids ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004335 elif len( current ) > 1:
4336 # there is more than one app with this ID
4337 result = main.FALSE
4338 # We will log this later in the method
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004339 elif not current[ 0 ][ 'name' ] == appName:
4340 currentName = current[ 0 ][ 'name' ]
Jon Hallbd16b922015-03-26 17:53:15 -07004341 result = main.FALSE
4342 main.log.error( "'app-ids' has " + str( currentName ) +
4343 " registered under id:" + str( appID ) +
4344 " but 'apps' has " + str( appName ) )
4345 else:
4346 pass # id and name match!
Jon Hall0e240372018-05-02 11:21:57 -07004347
Jon Hallbd16b922015-03-26 17:53:15 -07004348 # now make sure that app-ids has no duplicates
4349 idsList = []
4350 namesList = []
4351 for item in ids:
4352 idsList.append( item[ 'id' ] )
4353 namesList.append( item[ 'name' ] )
4354 if len( idsList ) != len( set( idsList ) ) or\
4355 len( namesList ) != len( set( namesList ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004356 main.log.error( "'app-ids' has some duplicate entries: \n"
4357 + json.dumps( ids,
4358 sort_keys=True,
4359 indent=4,
4360 separators=( ',', ': ' ) ) )
4361 result = main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07004362 return result
Jon Hallc6793552016-01-19 14:18:37 -08004363 except ( TypeError, ValueError ):
4364 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004365 return main.ERROR
4366 except pexpect.EOF:
4367 main.log.error( self.name + ": EOF exception found" )
4368 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004369 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004370 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004371 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004372 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004373
Jon Hallfb760a02015-04-13 15:35:03 -07004374 def getCfg( self, component=None, propName=None, short=False,
4375 jsonFormat=True ):
4376 """
4377 Get configuration settings from onos cli
4378 Optional arguments:
4379 component - Optionally only list configurations for a specific
4380 component. If None, all components with configurations
4381 are displayed. Case Sensitive string.
4382 propName - If component is specified, propName option will show
4383 only this specific configuration from that component.
4384 Case Sensitive string.
4385 jsonFormat - Returns output as json. Note that this will override
4386 the short option
4387 short - Short, less verbose, version of configurations.
4388 This is overridden by the json option
4389 returns:
4390 Output from cli as a string or None on error
4391 """
4392 try:
4393 baseStr = "cfg"
4394 cmdStr = " get"
4395 componentStr = ""
4396 if component:
4397 componentStr += " " + component
4398 if propName:
4399 componentStr += " " + propName
4400 if jsonFormat:
4401 baseStr += " -j"
Jon Hall22e94ce2019-01-15 14:52:17 -08004402 expectJson = True
Jon Hallfb760a02015-04-13 15:35:03 -07004403 elif short:
4404 baseStr += " -s"
Jon Hall22e94ce2019-01-15 14:52:17 -08004405 expectJson = False
4406 output = self.sendline( baseStr + cmdStr + componentStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07004407 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004408 assert "Command not found:" not in output, output
4409 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004410 return output
4411 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004412 main.log.exception( self.name + ": Error in processing 'cfg get' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004413 return None
4414 except TypeError:
4415 main.log.exception( self.name + ": Object not as expected" )
4416 return None
4417 except pexpect.EOF:
4418 main.log.error( self.name + ": EOF exception found" )
4419 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004420 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004421 except Exception:
4422 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004423 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004424
4425 def setCfg( self, component, propName, value=None, check=True ):
4426 """
4427 Set/Unset configuration settings from ONOS cli
Jon Hall390696c2015-05-05 17:13:41 -07004428 Required arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004429 component - The case sensitive name of the component whose
4430 property is to be set
4431 propName - The case sensitive name of the property to be set/unset
Jon Hall390696c2015-05-05 17:13:41 -07004432 Optional arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004433 value - The value to set the property to. If None, will unset the
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004434 property and revert it to it's default value(if applicable)
Jon Hallfb760a02015-04-13 15:35:03 -07004435 check - Boolean, Check whether the option was successfully set this
4436 only applies when a value is given.
4437 returns:
4438 main.TRUE on success or main.FALSE on failure. If check is False,
4439 will return main.TRUE unless there is an error
4440 """
4441 try:
4442 baseStr = "cfg"
4443 cmdStr = " set " + str( component ) + " " + str( propName )
4444 if value is not None:
4445 cmdStr += " " + str( value )
4446 output = self.sendline( baseStr + cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004447 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004448 assert "Command not found:" not in output, output
4449 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004450 if value and check:
4451 results = self.getCfg( component=str( component ),
4452 propName=str( propName ),
4453 jsonFormat=True )
4454 # Check if current value is what we just set
4455 try:
4456 jsonOutput = json.loads( results )
4457 current = jsonOutput[ 'value' ]
Jon Hallc6793552016-01-19 14:18:37 -08004458 except ( TypeError, ValueError ):
Jon Hallfb760a02015-04-13 15:35:03 -07004459 main.log.exception( "Error parsing cfg output" )
4460 main.log.error( "output:" + repr( results ) )
4461 return main.FALSE
4462 if current == str( value ):
4463 return main.TRUE
4464 return main.FALSE
4465 return main.TRUE
4466 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004467 main.log.exception( self.name + ": Error in processing 'cfg set' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004468 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08004469 except ( TypeError, ValueError ):
4470 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, results ) )
Jon Hallfb760a02015-04-13 15:35:03 -07004471 return main.FALSE
4472 except pexpect.EOF:
4473 main.log.error( self.name + ": EOF exception found" )
4474 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004475 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004476 except Exception:
4477 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004478 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004479
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004480 def distPrimitivesSend( self, cmd ):
4481 """
4482 Function to handle sending cli commands for the distributed primitives test app
4483
4484 This command will catch some exceptions and retry the command on some
4485 specific store exceptions.
4486
4487 Required arguments:
4488 cmd - The command to send to the cli
4489 returns:
4490 string containing the cli output
4491 None on Error
4492 """
4493 try:
4494 output = self.sendline( cmd )
4495 try:
4496 assert output is not None, "Error in sendline"
4497 # TODO: Maybe make this less hardcoded
4498 # ConsistentMap Exceptions
4499 assert "org.onosproject.store.service" not in output
4500 # Node not leader
4501 assert "java.lang.IllegalStateException" not in output
4502 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004503 main.log.error( self.name + ": Error in processing '" + cmd + "' " +
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004504 "command: " + str( output ) )
4505 retryTime = 30 # Conservative time, given by Madan
4506 main.log.info( "Waiting " + str( retryTime ) +
4507 "seconds before retrying." )
4508 time.sleep( retryTime ) # Due to change in mastership
4509 output = self.sendline( cmd )
4510 assert output is not None, "Error in sendline"
4511 assert "Command not found:" not in output, output
4512 assert "Error executing command" not in output, output
4513 main.log.info( self.name + ": " + output )
4514 return output
4515 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004516 main.log.exception( self.name + ": Error in processing '" + cmd + "' command." )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004517 return None
4518 except TypeError:
4519 main.log.exception( self.name + ": Object not as expected" )
4520 return None
4521 except pexpect.EOF:
4522 main.log.error( self.name + ": EOF exception found" )
4523 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004524 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004525 except Exception:
4526 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004527 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004528
Jon Hall390696c2015-05-05 17:13:41 -07004529 def setTestAdd( self, setName, values ):
4530 """
4531 CLI command to add elements to a distributed set.
4532 Arguments:
4533 setName - The name of the set to add to.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004534 values - The value(s) to add to the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004535 Example usages:
4536 setTestAdd( "set1", "a b c" )
4537 setTestAdd( "set2", "1" )
4538 returns:
4539 main.TRUE on success OR
4540 main.FALSE if elements were already in the set OR
4541 main.ERROR on error
4542 """
4543 try:
4544 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004545 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004546 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
4547 negativeMatch = "\[(.*)\] was already in set " + str( setName )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004548 if re.search( positiveMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004549 return main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004550 elif re.search( negativeMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004551 return main.FALSE
4552 else:
4553 main.log.error( self.name + ": setTestAdd did not" +
4554 " match expected output" )
Jon Hall390696c2015-05-05 17:13:41 -07004555 main.log.debug( self.name + " actual: " + repr( output ) )
4556 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004557 except TypeError:
4558 main.log.exception( self.name + ": Object not as expected" )
4559 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004560 except Exception:
4561 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004562 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004563
4564 def setTestRemove( self, setName, values, clear=False, retain=False ):
4565 """
4566 CLI command to remove elements from a distributed set.
4567 Required arguments:
4568 setName - The name of the set to remove from.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004569 values - The value(s) to remove from the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004570 Optional arguments:
4571 clear - Clear all elements from the set
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004572 retain - Retain only the given values. (intersection of the
4573 original set and the given set)
Jon Hall390696c2015-05-05 17:13:41 -07004574 returns:
4575 main.TRUE on success OR
4576 main.FALSE if the set was not changed OR
4577 main.ERROR on error
4578 """
4579 try:
4580 cmdStr = "set-test-remove "
4581 if clear:
4582 cmdStr += "-c " + str( setName )
4583 elif retain:
4584 cmdStr += "-r " + str( setName ) + " " + str( values )
4585 else:
4586 cmdStr += str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004587 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004588 if clear:
4589 pattern = "Set " + str( setName ) + " cleared"
4590 if re.search( pattern, output ):
4591 return main.TRUE
4592 elif retain:
4593 positivePattern = str( setName ) + " was pruned to contain " +\
4594 "only elements of set \[(.*)\]"
4595 negativePattern = str( setName ) + " was not changed by " +\
4596 "retaining only elements of the set " +\
4597 "\[(.*)\]"
4598 if re.search( positivePattern, output ):
4599 return main.TRUE
4600 elif re.search( negativePattern, output ):
4601 return main.FALSE
4602 else:
4603 positivePattern = "\[(.*)\] was removed from the set " +\
4604 str( setName )
4605 if ( len( values.split() ) == 1 ):
4606 negativePattern = "\[(.*)\] was not in set " +\
4607 str( setName )
4608 else:
4609 negativePattern = "No element of \[(.*)\] was in set " +\
4610 str( setName )
4611 if re.search( positivePattern, output ):
4612 return main.TRUE
4613 elif re.search( negativePattern, output ):
4614 return main.FALSE
4615 main.log.error( self.name + ": setTestRemove did not" +
4616 " match expected output" )
4617 main.log.debug( self.name + " expected: " + pattern )
4618 main.log.debug( self.name + " actual: " + repr( output ) )
4619 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004620 except TypeError:
4621 main.log.exception( self.name + ": Object not as expected" )
4622 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004623 except Exception:
4624 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004625 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004626
4627 def setTestGet( self, setName, values="" ):
4628 """
4629 CLI command to get the elements in a distributed set.
4630 Required arguments:
4631 setName - The name of the set to remove from.
4632 Optional arguments:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004633 values - The value(s) to check if in the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004634 returns:
4635 main.ERROR on error OR
4636 A list of elements in the set if no optional arguments are
4637 supplied OR
4638 A tuple containing the list then:
4639 main.FALSE if the given values are not in the set OR
4640 main.TRUE if the given values are in the set OR
4641 """
4642 try:
4643 values = str( values ).strip()
4644 setName = str( setName ).strip()
4645 length = len( values.split() )
4646 containsCheck = None
4647 # Patterns to match
4648 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004649 pattern = "Items in set " + setName + ":\r\n" + setPattern
Jon Hall390696c2015-05-05 17:13:41 -07004650 containsTrue = "Set " + setName + " contains the value " + values
4651 containsFalse = "Set " + setName + " did not contain the value " +\
4652 values
4653 containsAllTrue = "Set " + setName + " contains the the subset " +\
4654 setPattern
4655 containsAllFalse = "Set " + setName + " did not contain the the" +\
4656 " subset " + setPattern
4657
4658 cmdStr = "set-test-get "
4659 cmdStr += setName + " " + values
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004660 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004661 if length == 0:
4662 match = re.search( pattern, output )
4663 else: # if given values
4664 if length == 1: # Contains output
Jon Hall54b994f2016-12-05 10:48:59 -08004665 patternTrue = pattern + "\r\n" + containsTrue
4666 patternFalse = pattern + "\r\n" + containsFalse
Jon Hall390696c2015-05-05 17:13:41 -07004667 else: # ContainsAll output
Jon Hall54b994f2016-12-05 10:48:59 -08004668 patternTrue = pattern + "\r\n" + containsAllTrue
4669 patternFalse = pattern + "\r\n" + containsAllFalse
Jon Hall390696c2015-05-05 17:13:41 -07004670 matchTrue = re.search( patternTrue, output )
4671 matchFalse = re.search( patternFalse, output )
4672 if matchTrue:
4673 containsCheck = main.TRUE
4674 match = matchTrue
4675 elif matchFalse:
4676 containsCheck = main.FALSE
4677 match = matchFalse
4678 else:
Jon Halle0f0b342017-04-18 11:43:47 -07004679 main.log.error( self.name + " setTestGet did not match " +
Jon Hall390696c2015-05-05 17:13:41 -07004680 "expected output" )
4681 main.log.debug( self.name + " expected: " + pattern )
4682 main.log.debug( self.name + " actual: " + repr( output ) )
4683 match = None
4684 if match:
4685 setMatch = match.group( 1 )
4686 if setMatch == '':
4687 setList = []
4688 else:
4689 setList = setMatch.split( ", " )
4690 if length > 0:
4691 return ( setList, containsCheck )
4692 else:
4693 return setList
4694 else: # no match
4695 main.log.error( self.name + ": setTestGet did not" +
4696 " match expected output" )
4697 main.log.debug( self.name + " expected: " + pattern )
4698 main.log.debug( self.name + " actual: " + repr( output ) )
4699 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004700 except TypeError:
4701 main.log.exception( self.name + ": Object not as expected" )
4702 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004703 except Exception:
4704 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004705 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004706
4707 def setTestSize( self, setName ):
4708 """
4709 CLI command to get the elements in a distributed set.
4710 Required arguments:
4711 setName - The name of the set to remove from.
4712 returns:
Jon Hallfeff3082015-05-19 10:23:26 -07004713 The integer value of the size returned or
Jon Hall390696c2015-05-05 17:13:41 -07004714 None on error
4715 """
4716 try:
4717 # TODO: Should this check against the number of elements returned
4718 # and then return true/false based on that?
4719 setName = str( setName ).strip()
4720 # Patterns to match
4721 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004722 pattern = "There are (\d+) items in set " + setName + ":\r\n" +\
Jon Hall390696c2015-05-05 17:13:41 -07004723 setPattern
4724 cmdStr = "set-test-get -s "
4725 cmdStr += setName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004726 output = self.distPrimitivesSend( cmdStr )
Jon Hall0e240372018-05-02 11:21:57 -07004727 if output:
4728 match = re.search( pattern, output )
4729 if match:
4730 setSize = int( match.group( 1 ) )
4731 setMatch = match.group( 2 )
4732 if len( setMatch.split() ) == setSize:
4733 main.log.info( "The size returned by " + self.name +
4734 " matches the number of elements in " +
4735 "the returned set" )
4736 else:
4737 main.log.error( "The size returned by " + self.name +
4738 " does not match the number of " +
4739 "elements in the returned set." )
4740 return setSize
Jon Hall390696c2015-05-05 17:13:41 -07004741 else: # no match
4742 main.log.error( self.name + ": setTestGet did not" +
4743 " match expected output" )
4744 main.log.debug( self.name + " expected: " + pattern )
4745 main.log.debug( self.name + " actual: " + repr( output ) )
4746 return None
Jon Hall390696c2015-05-05 17:13:41 -07004747 except TypeError:
4748 main.log.exception( self.name + ": Object not as expected" )
4749 return None
Jon Hall390696c2015-05-05 17:13:41 -07004750 except Exception:
4751 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004752 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004753
Jon Hall80daded2015-05-27 16:07:00 -07004754 def counters( self, jsonFormat=True ):
Jon Hall390696c2015-05-05 17:13:41 -07004755 """
4756 Command to list the various counters in the system.
4757 returns:
Jon Hall80daded2015-05-27 16:07:00 -07004758 if jsonFormat, a string of the json object returned by the cli
4759 command
4760 if not jsonFormat, the normal string output of the cli command
Jon Hall390696c2015-05-05 17:13:41 -07004761 None on error
4762 """
Jon Hall390696c2015-05-05 17:13:41 -07004763 try:
Jon Hall390696c2015-05-05 17:13:41 -07004764 cmdStr = "counters"
Jon Hall80daded2015-05-27 16:07:00 -07004765 if jsonFormat:
4766 cmdStr += " -j"
Jon Hall390696c2015-05-05 17:13:41 -07004767 output = self.sendline( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004768 main.log.debug( self.name + ": Counters unparsed: " + output )
4769 output = output.split( "\r\n" )[ -1 ]
4770 main.log.debug( self.name + ": Counters parsed: " + output )
Jon Halla495f562016-05-16 18:03:26 -07004771 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004772 assert "Command not found:" not in output, output
4773 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004774 main.log.info( self.name + ": " + output )
Jon Hall80daded2015-05-27 16:07:00 -07004775 return output
Jon Hall390696c2015-05-05 17:13:41 -07004776 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004777 main.log.exception( self.name + ": Error in processing 'counters' command." )
Jon Hall80daded2015-05-27 16:07:00 -07004778 return None
Jon Hall390696c2015-05-05 17:13:41 -07004779 except TypeError:
4780 main.log.exception( self.name + ": Object not as expected" )
Jon Hall80daded2015-05-27 16:07:00 -07004781 return None
Jon Hall390696c2015-05-05 17:13:41 -07004782 except pexpect.EOF:
4783 main.log.error( self.name + ": EOF exception found" )
4784 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004785 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004786 except Exception:
4787 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004788 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004789
Jon Hall935db192016-04-19 00:22:04 -07004790 def counterTestAddAndGet( self, counter, delta=1 ):
Jon Hall390696c2015-05-05 17:13:41 -07004791 """
Jon Halle1a3b752015-07-22 13:02:46 -07004792 CLI command to add a delta to then get a distributed counter.
Jon Hall390696c2015-05-05 17:13:41 -07004793 Required arguments:
4794 counter - The name of the counter to increment.
4795 Optional arguments:
Jon Halle1a3b752015-07-22 13:02:46 -07004796 delta - The long to add to the counter
Jon Hall390696c2015-05-05 17:13:41 -07004797 returns:
4798 integer value of the counter or
4799 None on Error
4800 """
4801 try:
4802 counter = str( counter )
Jon Halle1a3b752015-07-22 13:02:46 -07004803 delta = int( delta )
Jon Hall390696c2015-05-05 17:13:41 -07004804 cmdStr = "counter-test-increment "
Jon Hall390696c2015-05-05 17:13:41 -07004805 cmdStr += counter
Jon Halle1a3b752015-07-22 13:02:46 -07004806 if delta != 1:
4807 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004808 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004809 pattern = counter + " was updated to (-?\d+)"
Jon Hall390696c2015-05-05 17:13:41 -07004810 match = re.search( pattern, output )
4811 if match:
4812 return int( match.group( 1 ) )
4813 else:
Jon Halle1a3b752015-07-22 13:02:46 -07004814 main.log.error( self.name + ": counterTestAddAndGet did not" +
Jon Hall390696c2015-05-05 17:13:41 -07004815 " match expected output." )
4816 main.log.debug( self.name + " expected: " + pattern )
4817 main.log.debug( self.name + " actual: " + repr( output ) )
4818 return None
Jon Hall390696c2015-05-05 17:13:41 -07004819 except TypeError:
4820 main.log.exception( self.name + ": Object not as expected" )
4821 return None
Jon Hall390696c2015-05-05 17:13:41 -07004822 except Exception:
4823 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004824 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004825
Jon Hall935db192016-04-19 00:22:04 -07004826 def counterTestGetAndAdd( self, counter, delta=1 ):
Jon Halle1a3b752015-07-22 13:02:46 -07004827 """
4828 CLI command to get a distributed counter then add a delta to it.
4829 Required arguments:
4830 counter - The name of the counter to increment.
4831 Optional arguments:
4832 delta - The long to add to the counter
Jon Halle1a3b752015-07-22 13:02:46 -07004833 returns:
4834 integer value of the counter or
4835 None on Error
4836 """
4837 try:
4838 counter = str( counter )
4839 delta = int( delta )
4840 cmdStr = "counter-test-increment -g "
Jon Halle1a3b752015-07-22 13:02:46 -07004841 cmdStr += counter
4842 if delta != 1:
4843 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004844 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004845 pattern = counter + " was updated to (-?\d+)"
4846 match = re.search( pattern, output )
4847 if match:
4848 return int( match.group( 1 ) )
4849 else:
4850 main.log.error( self.name + ": counterTestGetAndAdd did not" +
4851 " match expected output." )
4852 main.log.debug( self.name + " expected: " + pattern )
4853 main.log.debug( self.name + " actual: " + repr( output ) )
4854 return None
Jon Halle1a3b752015-07-22 13:02:46 -07004855 except TypeError:
4856 main.log.exception( self.name + ": Object not as expected" )
4857 return None
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004858 except Exception:
4859 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004860 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004861
4862 def valueTestGet( self, valueName ):
4863 """
4864 CLI command to get the value of an atomic value.
4865 Required arguments:
4866 valueName - The name of the value to get.
4867 returns:
4868 string value of the value or
4869 None on Error
4870 """
4871 try:
4872 valueName = str( valueName )
4873 cmdStr = "value-test "
4874 operation = "get"
4875 cmdStr = "value-test {} {}".format( valueName,
4876 operation )
4877 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004878 main.log.debug( self.name + ": value test unparsed: " + output )
4879 output = output.split( "\r\n" )[ -1 ]
4880 main.log.debug( self.name + ": value test parsed: " + output )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004881 pattern = "(\w+)"
4882 match = re.search( pattern, output )
4883 if match:
4884 return match.group( 1 )
4885 else:
4886 main.log.error( self.name + ": valueTestGet did not" +
4887 " match expected output." )
4888 main.log.debug( self.name + " expected: " + pattern )
4889 main.log.debug( self.name + " actual: " + repr( output ) )
4890 return None
4891 except TypeError:
4892 main.log.exception( self.name + ": Object not as expected" )
4893 return None
4894 except Exception:
4895 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004896 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004897
4898 def valueTestSet( self, valueName, newValue ):
4899 """
4900 CLI command to set the value of an atomic value.
4901 Required arguments:
4902 valueName - The name of the value to set.
4903 newValue - The value to assign to the given value.
4904 returns:
4905 main.TRUE on success or
4906 main.ERROR on Error
4907 """
4908 try:
4909 valueName = str( valueName )
4910 newValue = str( newValue )
4911 operation = "set"
4912 cmdStr = "value-test {} {} {}".format( valueName,
4913 operation,
4914 newValue )
4915 output = self.distPrimitivesSend( cmdStr )
4916 if output is not None:
4917 return main.TRUE
4918 else:
4919 return main.ERROR
4920 except TypeError:
4921 main.log.exception( self.name + ": Object not as expected" )
4922 return main.ERROR
4923 except Exception:
4924 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004925 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004926
4927 def valueTestCompareAndSet( self, valueName, oldValue, newValue ):
4928 """
4929 CLI command to compareAndSet the value of an atomic value.
4930 Required arguments:
4931 valueName - The name of the value.
4932 oldValue - Compare the current value of the atomic value to this
4933 newValue - If the value equals oldValue, set the value to newValue
4934 returns:
4935 main.TRUE on success or
4936 main.FALSE on failure or
4937 main.ERROR on Error
4938 """
4939 try:
4940 valueName = str( valueName )
4941 oldValue = str( oldValue )
4942 newValue = str( newValue )
4943 operation = "compareAndSet"
4944 cmdStr = "value-test {} {} {} {}".format( valueName,
4945 operation,
4946 oldValue,
4947 newValue )
4948 output = self.distPrimitivesSend( cmdStr )
4949 pattern = "(\w+)"
4950 match = re.search( pattern, output )
4951 if match:
4952 result = match.group( 1 )
4953 if result == "true":
4954 return main.TRUE
4955 elif result == "false":
4956 return main.FALSE
4957 else:
4958 main.log.error( self.name + ": valueTestCompareAndSet did not" +
4959 " match expected output." )
4960 main.log.debug( self.name + " expected: " + pattern )
4961 main.log.debug( self.name + " actual: " + repr( output ) )
4962 return main.ERROR
4963 except TypeError:
4964 main.log.exception( self.name + ": Object not as expected" )
4965 return main.ERROR
4966 except Exception:
4967 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004968 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004969
4970 def valueTestGetAndSet( self, valueName, newValue ):
4971 """
4972 CLI command to getAndSet the value of an atomic value.
4973 Required arguments:
4974 valueName - The name of the value to get.
4975 newValue - The value to assign to the given value
4976 returns:
4977 string value of the value or
4978 None on Error
4979 """
4980 try:
4981 valueName = str( valueName )
4982 cmdStr = "value-test "
4983 operation = "getAndSet"
4984 cmdStr += valueName + " " + operation
4985 cmdStr = "value-test {} {} {}".format( valueName,
4986 operation,
4987 newValue )
4988 output = self.distPrimitivesSend( cmdStr )
4989 pattern = "(\w+)"
4990 match = re.search( pattern, output )
4991 if match:
4992 return match.group( 1 )
4993 else:
4994 main.log.error( self.name + ": valueTestGetAndSet did not" +
4995 " match expected output." )
4996 main.log.debug( self.name + " expected: " + pattern )
4997 main.log.debug( self.name + " actual: " + repr( output ) )
4998 return None
4999 except TypeError:
5000 main.log.exception( self.name + ": Object not as expected" )
5001 return None
5002 except Exception:
5003 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005004 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07005005
5006 def valueTestDestroy( self, valueName ):
5007 """
5008 CLI command to destroy an atomic value.
5009 Required arguments:
5010 valueName - The name of the value to destroy.
5011 returns:
5012 main.TRUE on success or
5013 main.ERROR on Error
5014 """
5015 try:
5016 valueName = str( valueName )
5017 cmdStr = "value-test "
5018 operation = "destroy"
5019 cmdStr += valueName + " " + operation
5020 output = self.distPrimitivesSend( cmdStr )
5021 if output is not None:
5022 return main.TRUE
5023 else:
5024 return main.ERROR
5025 except TypeError:
5026 main.log.exception( self.name + ": Object not as expected" )
5027 return main.ERROR
Jon Halle1a3b752015-07-22 13:02:46 -07005028 except Exception:
5029 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005030 main.cleanAndExit()
Jon Halle1a3b752015-07-22 13:02:46 -07005031
YPZhangfebf7302016-05-24 16:45:56 -07005032 def summary( self, jsonFormat=True, timeout=30 ):
kelvin-onlaba297c4d2015-06-01 13:53:55 -07005033 """
5034 Description: Execute summary command in onos
5035 Returns: json object ( summary -j ), returns main.FALSE if there is
5036 no output
5037
5038 """
5039 try:
5040 cmdStr = "summary"
5041 if jsonFormat:
5042 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07005043 handle = self.sendline( cmdStr, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07005044 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005045 assert "Command not found:" not in handle, handle
Jon Hall6e709752016-02-01 13:38:46 -08005046 assert "Error:" not in handle, handle
Devin Lima7cfdbd2017-09-29 15:02:22 -07005047 assert "Error executing" not in handle, handle
kelvin-onlaba297c4d2015-06-01 13:53:55 -07005048 if not handle:
5049 main.log.error( self.name + ": There is no output in " +
5050 "summary command" )
5051 return main.FALSE
5052 return handle
Jon Hallc6793552016-01-19 14:18:37 -08005053 except AssertionError:
Jon Hall6e709752016-02-01 13:38:46 -08005054 main.log.exception( "{} Error in summary output:".format( self.name ) )
Jon Hallc6793552016-01-19 14:18:37 -08005055 return None
kelvin-onlaba297c4d2015-06-01 13:53:55 -07005056 except TypeError:
5057 main.log.exception( self.name + ": Object not as expected" )
5058 return None
5059 except pexpect.EOF:
5060 main.log.error( self.name + ": EOF exception found" )
5061 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005062 main.cleanAndExit()
kelvin-onlaba297c4d2015-06-01 13:53:55 -07005063 except Exception:
5064 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005065 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07005066
Jon Hall06fd0df2021-01-25 15:50:06 -08005067 def getAddress( self):
5068 """
5069 Get the onos ip address from the cli. This is usefull when connecting using
5070 a container manager such as kubernetes. This function also sets self.address
5071 the value from ONOS.
5072
5073 Returns:
5074 The string value of the key or
5075 None on Error
5076 """
5077 try:
5078 output = self.summary()
5079 address = json.loads( output ).get( 'node' )
5080 self.address = address
5081 return address
You Wang327bad42021-03-24 14:19:58 -07005082 except ( TypeError, ValueError ):
Jon Hall06fd0df2021-01-25 15:50:06 -08005083 main.log.exception( self.name + ": Object not as expected" )
5084 return None
5085 except Exception:
5086 main.log.exception( self.name + ": Uncaught exception!" )
5087 main.cleanAndExit()
5088
Jon Hall935db192016-04-19 00:22:04 -07005089 def transactionalMapGet( self, keyName ):
Jon Hall2a5002c2015-08-21 16:49:11 -07005090 """
5091 CLI command to get the value of a key in a consistent map using
5092 transactions. This a test function and can only get keys from the
5093 test map hard coded into the cli command
5094 Required arguments:
5095 keyName - The name of the key to get
Jon Hall2a5002c2015-08-21 16:49:11 -07005096 returns:
5097 The string value of the key or
5098 None on Error
5099 """
5100 try:
5101 keyName = str( keyName )
5102 cmdStr = "transactional-map-test-get "
Jon Hall2a5002c2015-08-21 16:49:11 -07005103 cmdStr += keyName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07005104 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07005105 pattern = "Key-value pair \(" + keyName + ", (?P<value>.+)\) found."
5106 if "Key " + keyName + " not found." in output:
Jon Hall9bfadd22016-05-11 14:48:07 -07005107 main.log.warn( output )
Jon Hall2a5002c2015-08-21 16:49:11 -07005108 return None
5109 else:
5110 match = re.search( pattern, output )
5111 if match:
5112 return match.groupdict()[ 'value' ]
5113 else:
5114 main.log.error( self.name + ": transactionlMapGet did not" +
5115 " match expected output." )
5116 main.log.debug( self.name + " expected: " + pattern )
5117 main.log.debug( self.name + " actual: " + repr( output ) )
5118 return None
5119 except TypeError:
5120 main.log.exception( self.name + ": Object not as expected" )
5121 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07005122 except Exception:
5123 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005124 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07005125
Jon Hall935db192016-04-19 00:22:04 -07005126 def transactionalMapPut( self, numKeys, value ):
Jon Hall2a5002c2015-08-21 16:49:11 -07005127 """
5128 CLI command to put a value into 'numKeys' number of keys in a
5129 consistent map using transactions. This a test function and can only
5130 put into keys named 'Key#' of the test map hard coded into the cli command
5131 Required arguments:
5132 numKeys - Number of keys to add the value to
5133 value - The string value to put into the keys
Jon Hall2a5002c2015-08-21 16:49:11 -07005134 returns:
5135 A dictionary whose keys are the name of the keys put into the map
5136 and the values of the keys are dictionaries whose key-values are
5137 'value': value put into map and optionaly
5138 'oldValue': Previous value in the key or
5139 None on Error
5140
5141 Example output
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005142 { 'Key1': {'oldValue': 'oldTestValue', 'value': 'Testing'},
5143 'Key2': {'value': 'Testing'} }
Jon Hall2a5002c2015-08-21 16:49:11 -07005144 """
5145 try:
5146 numKeys = str( numKeys )
5147 value = str( value )
5148 cmdStr = "transactional-map-test-put "
Jon Hall2a5002c2015-08-21 16:49:11 -07005149 cmdStr += numKeys + " " + value
Jon Hall7a6ebfd2017-03-13 10:58:58 -07005150 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07005151 newPattern = 'Created Key (?P<key>(\w)+) with value (?P<value>(.)+)\.'
5152 updatedPattern = "Put (?P<value>(.)+) into key (?P<key>(\w)+)\. The old value was (?P<oldValue>(.)+)\."
5153 results = {}
5154 for line in output.splitlines():
5155 new = re.search( newPattern, line )
5156 updated = re.search( updatedPattern, line )
5157 if new:
5158 results[ new.groupdict()[ 'key' ] ] = { 'value': new.groupdict()[ 'value' ] }
5159 elif updated:
5160 results[ updated.groupdict()[ 'key' ] ] = { 'value': updated.groupdict()[ 'value' ],
Jon Hallc6793552016-01-19 14:18:37 -08005161 'oldValue': updated.groupdict()[ 'oldValue' ] }
Jon Hall2a5002c2015-08-21 16:49:11 -07005162 else:
5163 main.log.error( self.name + ": transactionlMapGet did not" +
5164 " match expected output." )
Jon Hallc6793552016-01-19 14:18:37 -08005165 main.log.debug( "{} expected: {!r} or {!r}".format( self.name,
5166 newPattern,
5167 updatedPattern ) )
Jon Hall2a5002c2015-08-21 16:49:11 -07005168 main.log.debug( self.name + " actual: " + repr( output ) )
5169 return results
Jon Hall0e240372018-05-02 11:21:57 -07005170 except ( TypeError, AttributeError ):
Jon Hall2a5002c2015-08-21 16:49:11 -07005171 main.log.exception( self.name + ": Object not as expected" )
5172 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07005173 except Exception:
5174 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005175 main.cleanAndExit()
Jon Hallc6793552016-01-19 14:18:37 -08005176
acsmarsdaea66c2015-09-03 11:44:06 -07005177 def maps( self, jsonFormat=True ):
5178 """
5179 Description: Returns result of onos:maps
5180 Optional:
5181 * jsonFormat: enable json formatting of output
5182 """
5183 try:
5184 cmdStr = "maps"
5185 if jsonFormat:
5186 cmdStr += " -j"
5187 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07005188 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005189 assert "Command not found:" not in handle, handle
acsmarsdaea66c2015-09-03 11:44:06 -07005190 return handle
Jon Hallc6793552016-01-19 14:18:37 -08005191 except AssertionError:
5192 main.log.exception( "" )
5193 return None
acsmarsdaea66c2015-09-03 11:44:06 -07005194 except TypeError:
5195 main.log.exception( self.name + ": Object not as expected" )
5196 return None
5197 except pexpect.EOF:
5198 main.log.error( self.name + ": EOF exception found" )
5199 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005200 main.cleanAndExit()
acsmarsdaea66c2015-09-03 11:44:06 -07005201 except Exception:
5202 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005203 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005204
5205 def getSwController( self, uri, jsonFormat=True ):
5206 """
5207 Descrition: Gets the controller information from the device
5208 """
5209 try:
5210 cmd = "device-controllers "
5211 if jsonFormat:
5212 cmd += "-j "
5213 response = self.sendline( cmd + uri )
Jon Halla495f562016-05-16 18:03:26 -07005214 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005215 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005216 return response
Jon Hallc6793552016-01-19 14:18:37 -08005217 except AssertionError:
5218 main.log.exception( "" )
5219 return None
GlennRC050596c2015-11-18 17:06:41 -08005220 except TypeError:
5221 main.log.exception( self.name + ": Object not as expected" )
5222 return None
5223 except pexpect.EOF:
5224 main.log.error( self.name + ": EOF exception found" )
5225 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005226 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005227 except Exception:
5228 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005229 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005230
5231 def setSwController( self, uri, ip, proto="tcp", port="6653", jsonFormat=True ):
5232 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005233 Descrition: sets the controller(s) for the specified device
GlennRC050596c2015-11-18 17:06:41 -08005234
5235 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005236 Required: uri - String: The uri of the device(switch).
GlennRC050596c2015-11-18 17:06:41 -08005237 ip - String or List: The ip address of the controller.
5238 This parameter can be formed in a couple of different ways.
5239 VALID:
5240 10.0.0.1 - just the ip address
5241 tcp:10.0.0.1 - the protocol and the ip address
5242 tcp:10.0.0.1:6653 - the protocol and port can be specified,
5243 so that you can add controllers with different
5244 protocols and ports
5245 INVALID:
5246 10.0.0.1:6653 - this is not supported by ONOS
5247
5248 Optional: proto - The type of connection e.g. tcp, ssl. If a list of ips are given
5249 port - The port number.
5250 jsonFormat - If set ONOS will output in json NOTE: This is currently not supported
5251
5252 Returns: main.TRUE if ONOS returns without any errors, otherwise returns main.FALSE
5253 """
5254 try:
5255 cmd = "device-setcontrollers"
5256
5257 if jsonFormat:
5258 cmd += " -j"
5259 cmd += " " + uri
5260 if isinstance( ip, str ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005261 ip = [ ip ]
GlennRC050596c2015-11-18 17:06:41 -08005262 for item in ip:
5263 if ":" in item:
5264 sitem = item.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005265 if len( sitem ) == 3:
GlennRC050596c2015-11-18 17:06:41 -08005266 cmd += " " + item
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005267 elif "." in sitem[ 1 ]:
5268 cmd += " {}:{}".format( item, port )
GlennRC050596c2015-11-18 17:06:41 -08005269 else:
5270 main.log.error( "Malformed entry: " + item )
5271 raise TypeError
5272 else:
5273 cmd += " {}:{}:{}".format( proto, item, port )
GlennRC050596c2015-11-18 17:06:41 -08005274 response = self.sendline( cmd )
Jon Halla495f562016-05-16 18:03:26 -07005275 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005276 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005277 if "Error" in response:
5278 main.log.error( response )
5279 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005280 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005281 except AssertionError:
5282 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005283 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005284 except TypeError:
5285 main.log.exception( self.name + ": Object not as expected" )
5286 return main.FALSE
5287 except pexpect.EOF:
5288 main.log.error( self.name + ": EOF exception found" )
5289 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005290 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005291 except Exception:
5292 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005293 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005294
5295 def removeDevice( self, device ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005296 '''
GlennRC20fc6522015-12-23 23:26:57 -08005297 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005298 Remove a device from ONOS by passing the uri of the device(s).
GlennRC20fc6522015-12-23 23:26:57 -08005299 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005300 device - (str or list) the id or uri of the device ex. "of:0000000000000001"
GlennRC20fc6522015-12-23 23:26:57 -08005301 Returns:
5302 Returns main.FALSE if an exception is thrown or an error is present
5303 in the response. Otherwise, returns main.TRUE.
5304 NOTE:
5305 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005306 '''
GlennRC20fc6522015-12-23 23:26:57 -08005307 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005308 if isinstance( device, str ):
You Wang823f5022016-08-18 15:24:41 -07005309 deviceStr = device
5310 device = []
5311 device.append( deviceStr )
GlennRC20fc6522015-12-23 23:26:57 -08005312
5313 for d in device:
5314 time.sleep( 1 )
5315 response = self.sendline( "device-remove {}".format( d ) )
Jon Halla495f562016-05-16 18:03:26 -07005316 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005317 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005318 if "Error" in response:
5319 main.log.warn( "Error for device: {}\nResponse: {}".format( d, response ) )
5320 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005321 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005322 except AssertionError:
5323 main.log.exception( "" )
5324 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005325 except TypeError:
5326 main.log.exception( self.name + ": Object not as expected" )
5327 return main.FALSE
5328 except pexpect.EOF:
5329 main.log.error( self.name + ": EOF exception found" )
5330 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005331 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005332 except Exception:
5333 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005334 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005335
5336 def removeHost( self, host ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005337 '''
GlennRC20fc6522015-12-23 23:26:57 -08005338 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005339 Remove a host from ONOS by passing the id of the host(s)
GlennRC20fc6522015-12-23 23:26:57 -08005340 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005341 hostId - (str or list) the id or mac of the host ex. "00:00:00:00:00:01"
GlennRC20fc6522015-12-23 23:26:57 -08005342 Returns:
5343 Returns main.FALSE if an exception is thrown or an error is present
5344 in the response. Otherwise, returns main.TRUE.
5345 NOTE:
5346 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005347 '''
GlennRC20fc6522015-12-23 23:26:57 -08005348 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005349 if isinstance( host, str ):
GlennRC20fc6522015-12-23 23:26:57 -08005350 host = list( host )
5351
5352 for h in host:
5353 time.sleep( 1 )
5354 response = self.sendline( "host-remove {}".format( h ) )
Jon Halla495f562016-05-16 18:03:26 -07005355 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005356 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005357 if "Error" in response:
5358 main.log.warn( "Error for host: {}\nResponse: {}".format( h, response ) )
5359 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005360 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005361 except AssertionError:
5362 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005363 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005364 except TypeError:
5365 main.log.exception( self.name + ": Object not as expected" )
5366 return main.FALSE
5367 except pexpect.EOF:
5368 main.log.error( self.name + ": EOF exception found" )
5369 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005370 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005371 except Exception:
5372 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005373 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005374
YPZhangfebf7302016-05-24 16:45:56 -07005375 def link( self, begin, end, state, timeout=30, showResponse=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005376 '''
GlennRCed771242016-01-13 17:02:47 -08005377 Description:
5378 Bring link down or up in the null-provider.
5379 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005380 begin - (string) One end of a device or switch.
5381 end - (string) the other end of the device or switch
GlennRCed771242016-01-13 17:02:47 -08005382 returns:
5383 main.TRUE if no exceptions were thrown and no Errors are
5384 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005385 '''
GlennRCed771242016-01-13 17:02:47 -08005386 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005387 cmd = "null-link null:{} null:{} {}".format( begin, end, state )
YPZhangfebf7302016-05-24 16:45:56 -07005388 response = self.sendline( cmd, showResponse=showResponse, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07005389 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005390 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08005391 if "Error" in response or "Failure" in response:
5392 main.log.error( response )
5393 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005394 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005395 except AssertionError:
5396 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005397 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005398 except TypeError:
5399 main.log.exception( self.name + ": Object not as expected" )
5400 return main.FALSE
5401 except pexpect.EOF:
5402 main.log.error( self.name + ": EOF exception found" )
5403 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005404 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005405 except Exception:
5406 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005407 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005408
Jon Hall2c8959e2016-12-16 12:17:34 -08005409 def portstate( self, dpid, port, state ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005410 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005411 Description:
5412 Changes the state of port in an OF switch by means of the
5413 PORTSTATUS OF messages.
5414 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005415 dpid - (string) Datapath ID of the device. Ex: 'of:0000000000000102'
5416 port - (string) target port in the device. Ex: '2'
5417 state - (string) target state (enable or disable)
Flavio Castro82ee2f62016-06-07 15:04:12 -07005418 returns:
5419 main.TRUE if no exceptions were thrown and no Errors are
5420 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005421 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005422 try:
Jon Hall2c8959e2016-12-16 12:17:34 -08005423 state = state.lower()
5424 assert state == 'enable' or state == 'disable', "Unknown state"
Jon Halle0f0b342017-04-18 11:43:47 -07005425 cmd = "portstate {} {} {}".format( dpid, port, state )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005426 response = self.sendline( cmd, showResponse=True )
5427 assert response is not None, "Error in sendline"
5428 assert "Command not found:" not in response, response
5429 if "Error" in response or "Failure" in response:
5430 main.log.error( response )
5431 return main.FALSE
5432 return main.TRUE
5433 except AssertionError:
5434 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005435 return main.FALSE
Flavio Castro82ee2f62016-06-07 15:04:12 -07005436 except TypeError:
5437 main.log.exception( self.name + ": Object not as expected" )
5438 return main.FALSE
5439 except pexpect.EOF:
5440 main.log.error( self.name + ": EOF exception found" )
5441 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005442 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005443 except Exception:
5444 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005445 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005446
5447 def logSet( self, level="INFO", app="org.onosproject" ):
5448 """
5449 Set the logging level to lvl for a specific app
5450 returns main.TRUE on success
5451 returns main.FALSE if Error occurred
5452 if noExit is True, TestON will not exit, but clean up
5453 Available level: DEBUG, TRACE, INFO, WARN, ERROR
5454 Level defaults to INFO
5455 """
5456 try:
You Wang22e807e2021-03-29 10:53:38 -07005457 handle = self.sendline( "log:set %s %s" % ( level, app ) )
5458 assert handle is not None, "Error in sendline"
5459 assert "Command not found:" not in handle, handle
5460 if re.search( "Error", handle ):
5461 main.log.error( self.name + ": Error in setting log level" )
5462 main.log.error( handle )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005463 return main.FALSE
You Wang22e807e2021-03-29 10:53:38 -07005464 else:
5465 return main.TRUE
5466 except AssertionError:
5467 main.log.exception( "" )
5468 return None
5469 except TypeError:
5470 main.log.exception( self.name + ": Object not as expected" )
5471 return None
Flavio Castro82ee2f62016-06-07 15:04:12 -07005472 except pexpect.EOF:
5473 main.log.error( self.name + ": EOF exception found" )
5474 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005475 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005476 except Exception:
5477 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005478 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07005479
Jon Hall06fd0df2021-01-25 15:50:06 -08005480 def logList( self, saveValues=True ):
5481 """
5482 Gets the current log levels and optionally saves them
5483 returns a dict of the log levels or
5484 returns main.FALSE if Error occurred
5485 """
5486 try:
5487 self.handle.sendline( "log:list" )
5488 self.handle.expect( self.karafPrompt )
5489
5490 response = self.handle.before
5491 logLevels = {}
5492 for line in response.splitlines():
5493 parsed = line.split('│')
5494 logger = parsed[0].strip()
5495 if len( parsed ) != 2 or 'Level' in parsed[1] or logger[0] == '─':
5496 continue
5497 level = parsed[1].strip()
5498 logLevels[ logger ] = level
5499 if saveValues:
5500 self.logLevels = logLevels
5501 return logLevels
5502 except pexpect.TIMEOUT:
5503 main.log.exception( self.name + ": TIMEOUT exception found" )
5504 main.cleanAndExit()
5505 except pexpect.EOF:
5506 main.log.error( self.name + ": EOF exception found" )
5507 main.log.error( self.name + ": " + self.handle.before )
5508 main.cleanAndExit()
5509 except Exception:
5510 main.log.exception( self.name + ": Uncaught exception!" )
5511 main.cleanAndExit()
5512
You Wangdb8cd0a2016-05-26 15:19:45 -07005513 def getGraphDict( self, timeout=60, includeHost=False ):
5514 """
5515 Return a dictionary which describes the latest network topology data as a
5516 graph.
5517 An example of the dictionary:
5518 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
5519 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
5520 Each vertex should at least have an 'edges' attribute which describes the
5521 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005522 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07005523 list of attributes.
5524 An example of the edges dictionary:
5525 'edges': { vertex2: { 'port': ..., 'weight': ... },
5526 vertex3: { 'port': ..., 'weight': ... } }
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005527 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07005528 in topology data.
5529 """
5530 graphDict = {}
5531 try:
5532 links = self.links()
5533 links = json.loads( links )
5534 devices = self.devices()
5535 devices = json.loads( devices )
5536 idToDevice = {}
5537 for device in devices:
5538 idToDevice[ device[ 'id' ] ] = device
5539 if includeHost:
5540 hosts = self.hosts()
5541 # FIXME: support 'includeHost' argument
5542 for link in links:
5543 nodeA = link[ 'src' ][ 'device' ]
5544 nodeB = link[ 'dst' ][ 'device' ]
5545 assert idToDevice[ nodeA ][ 'available' ] and idToDevice[ nodeB ][ 'available' ]
Jon Halle0f0b342017-04-18 11:43:47 -07005546 if nodeA not in graphDict.keys():
5547 graphDict[ nodeA ] = { 'edges': {},
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005548 'dpid': idToDevice[ nodeA ][ 'id' ][ 3: ],
Jon Halle0f0b342017-04-18 11:43:47 -07005549 'type': idToDevice[ nodeA ][ 'type' ],
5550 'available': idToDevice[ nodeA ][ 'available' ],
5551 'role': idToDevice[ nodeA ][ 'role' ],
5552 'mfr': idToDevice[ nodeA ][ 'mfr' ],
5553 'hw': idToDevice[ nodeA ][ 'hw' ],
5554 'sw': idToDevice[ nodeA ][ 'sw' ],
5555 'serial': idToDevice[ nodeA ][ 'serial' ],
5556 'chassisId': idToDevice[ nodeA ][ 'chassisId' ],
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005557 'annotations': idToDevice[ nodeA ][ 'annotations' ]}
You Wangdb8cd0a2016-05-26 15:19:45 -07005558 else:
5559 # Assert nodeB is not connected to any current links of nodeA
You Wang7d14d642019-01-23 15:10:08 -08005560 # assert nodeB not in graphDict[ nodeA ][ 'edges' ].keys()
5561 pass
Jon Halle0f0b342017-04-18 11:43:47 -07005562 graphDict[ nodeA ][ 'edges' ][ nodeB ] = { 'port': link[ 'src' ][ 'port' ],
5563 'type': link[ 'type' ],
5564 'state': link[ 'state' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07005565 return graphDict
5566 except ( TypeError, ValueError ):
5567 main.log.exception( self.name + ": Object not as expected" )
5568 return None
5569 except KeyError:
5570 main.log.exception( self.name + ": KeyError exception found" )
5571 return None
5572 except AssertionError:
5573 main.log.exception( self.name + ": AssertionError exception found" )
5574 return None
5575 except pexpect.EOF:
5576 main.log.error( self.name + ": EOF exception found" )
5577 main.log.error( self.name + ": " + self.handle.before )
5578 return None
5579 except Exception:
5580 main.log.exception( self.name + ": Uncaught exception!" )
5581 return None
YPZhangcbc2a062016-07-11 10:55:44 -07005582
5583 def getIntentPerfSummary( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005584 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005585 Send command to check intent-perf summary
5586 Returns: dictionary for intent-perf summary
5587 if something wrong, function will return None
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005588 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005589 cmd = "intent-perf -s"
5590 respDic = {}
5591 resp = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08005592 assert resp is not None, "Error in sendline"
5593 assert "Command not found:" not in resp, resp
YPZhangcbc2a062016-07-11 10:55:44 -07005594 try:
5595 # Generate the dictionary to return
5596 for l in resp.split( "\n" ):
5597 # Delete any white space in line
5598 temp = re.sub( r'\s+', '', l )
5599 temp = temp.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005600 respDic[ temp[ 0 ] ] = temp[ 1 ]
YPZhangcbc2a062016-07-11 10:55:44 -07005601
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005602 except ( TypeError, ValueError ):
YPZhangcbc2a062016-07-11 10:55:44 -07005603 main.log.exception( self.name + ": Object not as expected" )
5604 return None
5605 except KeyError:
5606 main.log.exception( self.name + ": KeyError exception found" )
5607 return None
5608 except AssertionError:
5609 main.log.exception( self.name + ": AssertionError exception found" )
5610 return None
5611 except pexpect.EOF:
5612 main.log.error( self.name + ": EOF exception found" )
5613 main.log.error( self.name + ": " + self.handle.before )
5614 return None
5615 except Exception:
5616 main.log.exception( self.name + ": Uncaught exception!" )
5617 return None
5618 return respDic
5619
Chiyu Chengec63bde2016-11-17 18:11:36 -08005620 def logSearch( self, mode='all', searchTerm='', startLine='', logNum=1 ):
chengchiyu08303a02016-09-08 17:40:26 -07005621 """
5622 Searches the latest ONOS log file for the given search term and
5623 return a list that contains all the lines that have the search term.
YPZhangcbc2a062016-07-11 10:55:44 -07005624
chengchiyu08303a02016-09-08 17:40:26 -07005625 Arguments:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005626 searchTerm:
5627 The string to grep from the ONOS log.
5628 startLine:
5629 The term that decides which line is the start to search the searchTerm in
5630 the karaf log. For now, startTerm only works in 'first' mode.
5631 logNum:
5632 In some extreme cases, one karaf log is not big enough to contain all the
5633 information.Because of this, search mutiply logs is necessary to capture
5634 the right result. logNum is the number of karaf logs that we need to search
5635 the searchTerm.
chengchiyu08303a02016-09-08 17:40:26 -07005636 mode:
5637 all: return all the strings that contain the search term
5638 last: return the last string that contains the search term
5639 first: return the first string that contains the search term
Chiyu Chengec63bde2016-11-17 18:11:36 -08005640 num: return the number of times that the searchTerm appears in the log
5641 total: return how many lines in karaf log
chengchiyu08303a02016-09-08 17:40:26 -07005642 """
5643 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005644 assert isinstance( searchTerm, str )
Jon Halle0f0b342017-04-18 11:43:47 -07005645 # Build the log paths string
Chiyu Chengec63bde2016-11-17 18:11:36 -08005646 logPath = '/opt/onos/log/karaf.log.'
5647 logPaths = '/opt/onos/log/karaf.log'
5648 for i in range( 1, logNum ):
5649 logPaths = logPath + str( i ) + " " + logPaths
5650 cmd = "cat " + logPaths
You Wang6d301d42017-04-21 10:49:33 -07005651 if startLine:
Jon Halla478b852017-12-04 15:00:15 -08005652 # 100000000 is just a extreme large number to make sure this function can
5653 # grep all the lines after startLine
You Wang6d301d42017-04-21 10:49:33 -07005654 cmd = cmd + " | grep -A 100000000 \'" + startLine + "\'"
Chiyu Chengec63bde2016-11-17 18:11:36 -08005655 if mode == 'all':
5656 cmd = cmd + " | grep \'" + searchTerm + "\'"
You Wang6d301d42017-04-21 10:49:33 -07005657 elif mode == 'last':
Chiyu Chengec63bde2016-11-17 18:11:36 -08005658 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | tail -n 1"
You Wang6d301d42017-04-21 10:49:33 -07005659 elif mode == 'first':
5660 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | head -n 1"
5661 elif mode == 'num':
You Wangd91a70f2019-01-03 15:28:10 -08005662 cmd = cmd + " | grep \'" + searchTerm + "\' | wc -l"
5663 num = self.lineCount( cmd )
Chiyu Chengb8c2c842016-10-05 12:40:49 -07005664 return num
You Wang6d301d42017-04-21 10:49:33 -07005665 elif mode == 'total':
Jon Halld5a94fb2018-11-13 14:32:23 -08005666 totalLines = self.lineCount( "cat /opt/onos/log/karaf.log | wc -l" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005667 return int( totalLines )
You Wang6d301d42017-04-21 10:49:33 -07005668 else:
5669 main.log.error( self.name + " unsupported mode" )
5670 return main.ERROR
chengchiyu08303a02016-09-08 17:40:26 -07005671 before = self.sendline( cmd )
5672 before = before.splitlines()
5673 # make sure the returned list only contains the search term
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005674 returnLines = [ line for line in before if searchTerm in line ]
chengchiyu08303a02016-09-08 17:40:26 -07005675 return returnLines
5676 except AssertionError:
5677 main.log.error( self.name + " searchTerm is not string type" )
5678 return None
5679 except pexpect.EOF:
5680 main.log.error( self.name + ": EOF exception found" )
5681 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005682 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005683 except pexpect.TIMEOUT:
5684 main.log.error( self.name + ": TIMEOUT exception found" )
5685 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005686 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005687 except Exception:
5688 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005689 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005690
5691 def vplsShow( self, jsonFormat=True ):
5692 """
5693 Description: Returns result of onos:vpls show, which should list the
5694 configured VPLS networks and the assigned interfaces.
5695 Optional:
5696 * jsonFormat: enable json formatting of output
5697 Returns:
5698 The output of the command or None on error.
5699 """
5700 try:
5701 cmdStr = "vpls show"
5702 if jsonFormat:
5703 raise NotImplementedError
5704 cmdStr += " -j"
5705 handle = self.sendline( cmdStr )
5706 assert handle is not None, "Error in sendline"
5707 assert "Command not found:" not in handle, handle
5708 return handle
5709 except AssertionError:
5710 main.log.exception( "" )
5711 return None
5712 except TypeError:
5713 main.log.exception( self.name + ": Object not as expected" )
5714 return None
5715 except pexpect.EOF:
5716 main.log.error( self.name + ": EOF exception found" )
5717 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005718 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005719 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005720 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005721 return None
5722 except Exception:
5723 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005724 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005725
5726 def parseVplsShow( self ):
5727 """
5728 Parse the cli output of 'vpls show' into json output. This is required
5729 as there is currently no json output available.
5730 """
5731 try:
5732 output = []
5733 raw = self.vplsShow( jsonFormat=False )
5734 namePat = "VPLS name: (?P<name>\w+)"
5735 interfacesPat = "Associated interfaces: \[(?P<interfaces>.*)\]"
5736 encapPat = "Encapsulation: (?P<encap>\w+)"
5737 pattern = "\s+".join( [ namePat, interfacesPat, encapPat ] )
5738 mIter = re.finditer( pattern, raw )
5739 for match in mIter:
5740 item = {}
5741 item[ 'name' ] = match.group( 'name' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005742 ifaces = match.group( 'interfaces' ).split( ', ' )
Jon Hall2c8959e2016-12-16 12:17:34 -08005743 if ifaces == [ "" ]:
5744 ifaces = []
5745 item[ 'interfaces' ] = ifaces
5746 encap = match.group( 'encap' )
5747 if encap != 'NONE':
5748 item[ 'encapsulation' ] = encap.lower()
5749 output.append( item )
5750 return output
5751 except Exception:
5752 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005753 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005754
5755 def vplsList( self, jsonFormat=True ):
5756 """
5757 Description: Returns result of onos:vpls list, which should list the
5758 configured VPLS networks.
5759 Optional:
5760 * jsonFormat: enable json formatting of output
5761 """
5762 try:
5763 cmdStr = "vpls list"
5764 if jsonFormat:
5765 raise NotImplementedError
5766 cmdStr += " -j"
5767 handle = self.sendline( cmdStr )
5768 assert handle is not None, "Error in sendline"
5769 assert "Command not found:" not in handle, handle
5770 return handle
5771 except AssertionError:
5772 main.log.exception( "" )
5773 return None
5774 except TypeError:
5775 main.log.exception( self.name + ": Object not as expected" )
5776 return None
5777 except pexpect.EOF:
5778 main.log.error( self.name + ": EOF exception found" )
5779 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005780 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005781 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005782 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005783 return None
5784 except Exception:
5785 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005786 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005787
5788 def vplsCreate( self, network ):
5789 """
5790 CLI command to create a new VPLS network.
5791 Required arguments:
5792 network - String name of the network to create.
5793 returns:
5794 main.TRUE on success and main.FALSE on failure
5795 """
5796 try:
5797 network = str( network )
5798 cmdStr = "vpls create "
5799 cmdStr += network
5800 output = self.sendline( cmdStr )
5801 assert output is not None, "Error in sendline"
5802 assert "Command not found:" not in output, output
5803 assert "Error executing command" not in output, output
5804 assert "VPLS already exists:" not in output, output
5805 return main.TRUE
5806 except AssertionError:
5807 main.log.exception( "" )
5808 return main.FALSE
5809 except TypeError:
5810 main.log.exception( self.name + ": Object not as expected" )
5811 return main.FALSE
5812 except pexpect.EOF:
5813 main.log.error( self.name + ": EOF exception found" )
5814 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005815 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005816 except Exception:
5817 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005818 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005819
5820 def vplsDelete( self, network ):
5821 """
5822 CLI command to delete a VPLS network.
5823 Required arguments:
5824 network - Name of the network to delete.
5825 returns:
5826 main.TRUE on success and main.FALSE on failure
5827 """
5828 try:
5829 network = str( network )
5830 cmdStr = "vpls delete "
5831 cmdStr += network
5832 output = self.sendline( cmdStr )
5833 assert output is not None, "Error in sendline"
5834 assert "Command not found:" not in output, output
5835 assert "Error executing command" not in output, output
5836 assert " not found" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005837 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005838 return main.TRUE
5839 except AssertionError:
5840 main.log.exception( "" )
5841 return main.FALSE
5842 except TypeError:
5843 main.log.exception( self.name + ": Object not as expected" )
5844 return main.FALSE
5845 except pexpect.EOF:
5846 main.log.error( self.name + ": EOF exception found" )
5847 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005848 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005849 except Exception:
5850 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005851 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005852
5853 def vplsAddIface( self, network, iface ):
5854 """
5855 CLI command to add an interface to a VPLS network.
5856 Required arguments:
5857 network - Name of the network to add the interface to.
5858 iface - The ONOS name for an interface.
5859 returns:
5860 main.TRUE on success and main.FALSE on failure
5861 """
5862 try:
5863 network = str( network )
5864 iface = str( iface )
5865 cmdStr = "vpls add-if "
5866 cmdStr += network + " " + iface
5867 output = self.sendline( cmdStr )
5868 assert output is not None, "Error in sendline"
5869 assert "Command not found:" not in output, output
5870 assert "Error executing command" not in output, output
5871 assert "already associated to network" not in output, output
5872 assert "Interface cannot be added." not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005873 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005874 return main.TRUE
5875 except AssertionError:
5876 main.log.exception( "" )
5877 return main.FALSE
5878 except TypeError:
5879 main.log.exception( self.name + ": Object not as expected" )
5880 return main.FALSE
5881 except pexpect.EOF:
5882 main.log.error( self.name + ": EOF exception found" )
5883 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005884 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005885 except Exception:
5886 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005887 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005888
5889 def vplsRemIface( self, network, iface ):
5890 """
5891 CLI command to remove an interface from a VPLS network.
5892 Required arguments:
5893 network - Name of the network to remove the interface from.
5894 iface - Name of the interface to remove.
5895 returns:
5896 main.TRUE on success and main.FALSE on failure
5897 """
5898 try:
5899 iface = str( iface )
5900 cmdStr = "vpls rem-if "
5901 cmdStr += network + " " + iface
5902 output = self.sendline( cmdStr )
5903 assert output is not None, "Error in sendline"
5904 assert "Command not found:" not in output, output
5905 assert "Error executing command" not in output, output
5906 assert "is not configured" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005907 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005908 return main.TRUE
5909 except AssertionError:
5910 main.log.exception( "" )
5911 return main.FALSE
5912 except TypeError:
5913 main.log.exception( self.name + ": Object not as expected" )
5914 return main.FALSE
5915 except pexpect.EOF:
5916 main.log.error( self.name + ": EOF exception found" )
5917 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005918 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005919 except Exception:
5920 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005921 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005922
5923 def vplsClean( self ):
5924 """
5925 Description: Clears the VPLS app configuration.
5926 Returns: main.TRUE on success and main.FALSE on failure
5927 """
5928 try:
5929 cmdStr = "vpls clean"
5930 handle = self.sendline( cmdStr )
5931 assert handle is not None, "Error in sendline"
5932 assert "Command not found:" not in handle, handle
Jon Hallcf97cf12017-06-06 09:37:51 -07005933 assert "still updating" not in handle, handle
Jon Hall2c8959e2016-12-16 12:17:34 -08005934 return handle
5935 except AssertionError:
5936 main.log.exception( "" )
5937 return main.FALSE
5938 except TypeError:
5939 main.log.exception( self.name + ": Object not as expected" )
5940 return main.FALSE
5941 except pexpect.EOF:
5942 main.log.error( self.name + ": EOF exception found" )
5943 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005944 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005945 except Exception:
5946 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005947 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005948
5949 def vplsSetEncap( self, network, encapType ):
5950 """
5951 CLI command to add an interface to a VPLS network.
5952 Required arguments:
5953 network - Name of the network to create.
5954 encapType - Type of encapsulation.
5955 returns:
5956 main.TRUE on success and main.FALSE on failure
5957 """
5958 try:
5959 network = str( network )
5960 encapType = str( encapType ).upper()
5961 assert encapType in [ "MPLS", "VLAN", "NONE" ], "Incorrect type"
5962 cmdStr = "vpls set-encap "
5963 cmdStr += network + " " + encapType
5964 output = self.sendline( cmdStr )
5965 assert output is not None, "Error in sendline"
5966 assert "Command not found:" not in output, output
5967 assert "Error executing command" not in output, output
5968 assert "already associated to network" not in output, output
5969 assert "Encapsulation type " not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005970 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005971 return main.TRUE
5972 except AssertionError:
5973 main.log.exception( "" )
5974 return main.FALSE
5975 except TypeError:
5976 main.log.exception( self.name + ": Object not as expected" )
5977 return main.FALSE
5978 except pexpect.EOF:
5979 main.log.error( self.name + ": EOF exception found" )
5980 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005981 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005982 except Exception:
5983 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005984 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005985
5986 def interfaces( self, jsonFormat=True ):
5987 """
5988 Description: Returns result of interfaces command.
5989 Optional:
5990 * jsonFormat: enable json formatting of output
5991 Returns:
5992 The output of the command or None on error.
5993 """
5994 try:
5995 cmdStr = "interfaces"
5996 if jsonFormat:
Jon Halle0f0b342017-04-18 11:43:47 -07005997 raise NotImplementedError
Jon Hall2c8959e2016-12-16 12:17:34 -08005998 cmdStr += " -j"
5999 handle = self.sendline( cmdStr )
6000 assert handle is not None, "Error in sendline"
6001 assert "Command not found:" not in handle, handle
6002 return handle
6003 except AssertionError:
6004 main.log.exception( "" )
6005 return None
6006 except TypeError:
6007 main.log.exception( self.name + ": Object not as expected" )
6008 return None
6009 except pexpect.EOF:
6010 main.log.error( self.name + ": EOF exception found" )
6011 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07006012 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08006013 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006014 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08006015 return None
6016 except Exception:
6017 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006018 main.cleanAndExit()
Chiyu Chengec63bde2016-11-17 18:11:36 -08006019
6020 def getTimeStampFromLog( self, mode, searchTerm, splitTerm_before, splitTerm_after, startLine='', logNum=1 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00006021 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08006022 Get the timestamp of searchTerm from karaf log.
6023
6024 Arguments:
6025 splitTerm_before and splitTerm_after:
6026
6027 The terms that split the string that contains the timeStamp of
6028 searchTerm. For example, if that string is "xxxxxxxcreationTime =
6029 1419510501xxxxxx", then the splitTerm_before is "CreationTime = "
6030 and the splitTerm_after is "x"
6031
6032 others:
Jon Halle0f0b342017-04-18 11:43:47 -07006033 Please look at the "logsearch" Function in onosclidriver.py
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00006034 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08006035 if logNum < 0:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006036 main.log.error( "Get wrong log number ")
Chiyu Chengec63bde2016-11-17 18:11:36 -08006037 return main.ERROR
6038 lines = self.logSearch( mode=mode, searchTerm=searchTerm, startLine=startLine, logNum=logNum )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006039 if len( lines ) == 0:
Chiyu Chengec63bde2016-11-17 18:11:36 -08006040 main.log.warn( "Captured timestamp string is empty" )
6041 return main.ERROR
6042 lines = lines[ 0 ]
6043 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006044 assert isinstance( lines, str )
Chiyu Chengec63bde2016-11-17 18:11:36 -08006045 # get the target value
6046 line = lines.split( splitTerm_before )
6047 key = line[ 1 ].split( splitTerm_after )
6048 return int( key[ 0 ] )
6049 except IndexError:
6050 main.log.warn( "Index Error!" )
6051 return main.ERROR
6052 except AssertionError:
6053 main.log.warn( "Search Term Not Found " )
6054 return main.ERROR
Jon Halle0f0b342017-04-18 11:43:47 -07006055
6056 def workQueueAdd( self, queueName, value ):
6057 """
6058 CLI command to add a string to the specified Work Queue.
6059 This function uses the distributed primitives test app, which
6060 gives some cli access to distributed primitives for testing
6061 purposes only.
6062
6063 Required arguments:
6064 queueName - The name of the queue to add to
6065 value - The value to add to the queue
6066 returns:
6067 main.TRUE on success, main.FALSE on failure and
6068 main.ERROR on error.
6069 """
6070 try:
6071 queueName = str( queueName )
6072 value = str( value )
6073 prefix = "work-queue-test"
6074 operation = "add"
6075 cmdStr = " ".join( [ prefix, queueName, operation, value ] )
6076 output = self.distPrimitivesSend( cmdStr )
6077 if "Invalid operation name" in output:
6078 main.log.warn( output )
6079 return main.ERROR
6080 elif "Done" in output:
6081 return main.TRUE
6082 except TypeError:
6083 main.log.exception( self.name + ": Object not as expected" )
6084 return main.ERROR
6085 except Exception:
6086 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006087 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006088
6089 def workQueueAddMultiple( self, queueName, value1, value2 ):
6090 """
6091 CLI command to add two strings to the specified Work Queue.
6092 This function uses the distributed primitives test app, which
6093 gives some cli access to distributed primitives for testing
6094 purposes only.
6095
6096 Required arguments:
6097 queueName - The name of the queue to add to
6098 value1 - The first value to add to the queue
6099 value2 - The second value to add to the queue
6100 returns:
6101 main.TRUE on success, main.FALSE on failure and
6102 main.ERROR on error.
6103 """
6104 try:
6105 queueName = str( queueName )
6106 value1 = str( value1 )
6107 value2 = str( value2 )
6108 prefix = "work-queue-test"
6109 operation = "addMultiple"
6110 cmdStr = " ".join( [ prefix, queueName, operation, value1, value2 ] )
6111 output = self.distPrimitivesSend( cmdStr )
6112 if "Invalid operation name" in output:
6113 main.log.warn( output )
6114 return main.ERROR
6115 elif "Done" in output:
6116 return main.TRUE
6117 except TypeError:
6118 main.log.exception( self.name + ": Object not as expected" )
6119 return main.ERROR
6120 except Exception:
6121 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006122 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006123
6124 def workQueueTakeAndComplete( self, queueName, number=1 ):
6125 """
6126 CLI command to take a value from the specified Work Queue and compelte it.
6127 This function uses the distributed primitives test app, which
6128 gives some cli access to distributed primitives for testing
6129 purposes only.
6130
6131 Required arguments:
6132 queueName - The name of the queue to add to
6133 number - The number of items to take and complete
6134 returns:
6135 main.TRUE on success, main.FALSE on failure and
6136 main.ERROR on error.
6137 """
6138 try:
6139 queueName = str( queueName )
6140 number = str( int( number ) )
6141 prefix = "work-queue-test"
6142 operation = "takeAndComplete"
6143 cmdStr = " ".join( [ prefix, queueName, operation, number ] )
6144 output = self.distPrimitivesSend( cmdStr )
6145 if "Invalid operation name" in output:
6146 main.log.warn( output )
6147 return main.ERROR
6148 elif "Done" in output:
6149 return main.TRUE
6150 except TypeError:
6151 main.log.exception( self.name + ": Object not as expected" )
6152 return main.ERROR
6153 except Exception:
6154 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006155 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006156
6157 def workQueueDestroy( self, queueName ):
6158 """
6159 CLI command to destroy the specified Work Queue.
6160 This function uses the distributed primitives test app, which
6161 gives some cli access to distributed primitives for testing
6162 purposes only.
6163
6164 Required arguments:
6165 queueName - The name of the queue to add to
6166 returns:
6167 main.TRUE on success, main.FALSE on failure and
6168 main.ERROR on error.
6169 """
6170 try:
6171 queueName = str( queueName )
6172 prefix = "work-queue-test"
6173 operation = "destroy"
6174 cmdStr = " ".join( [ prefix, queueName, operation ] )
6175 output = self.distPrimitivesSend( cmdStr )
6176 if "Invalid operation name" in output:
6177 main.log.warn( output )
6178 return main.ERROR
6179 return main.TRUE
6180 except TypeError:
6181 main.log.exception( self.name + ": Object not as expected" )
6182 return main.ERROR
6183 except Exception:
6184 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006185 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006186
6187 def workQueueTotalPending( self, queueName ):
6188 """
6189 CLI command to get the Total Pending items of the specified Work Queue.
6190 This function uses the distributed primitives test app, which
6191 gives some cli access to distributed primitives for testing
6192 purposes only.
6193
6194 Required arguments:
6195 queueName - The name of the queue to add to
6196 returns:
6197 The number of Pending items in the specified work queue or
6198 None on error
6199 """
6200 try:
6201 queueName = str( queueName )
6202 prefix = "work-queue-test"
6203 operation = "totalPending"
6204 cmdStr = " ".join( [ prefix, queueName, operation ] )
6205 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006206 main.log.debug( self.name + ": work queue unparsed: " + output )
6207 output = output.split( "\r\n" )[ -1 ]
6208 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006209 pattern = r'\d+'
6210 if "Invalid operation name" in output:
6211 main.log.warn( output )
6212 return None
6213 else:
6214 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006215 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006216 except ( AttributeError, TypeError ):
6217 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6218 return None
6219 except Exception:
6220 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006221 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006222
6223 def workQueueTotalCompleted( self, queueName ):
6224 """
6225 CLI command to get the Total Completed items of the specified Work Queue.
6226 This function uses the distributed primitives test app, which
6227 gives some cli access to distributed primitives for testing
6228 purposes only.
6229
6230 Required arguments:
6231 queueName - The name of the queue to add to
6232 returns:
6233 The number of complete items in the specified work queue or
6234 None on error
6235 """
6236 try:
6237 queueName = str( queueName )
6238 prefix = "work-queue-test"
6239 operation = "totalCompleted"
6240 cmdStr = " ".join( [ prefix, queueName, operation ] )
6241 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006242 main.log.debug( self.name + ": work queue unparsed: " + output )
6243 output = output.split( "\r\n" )[ -1 ]
6244 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006245 pattern = r'\d+'
6246 if "Invalid operation name" in output:
6247 main.log.warn( output )
6248 return None
6249 else:
6250 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006251 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006252 except ( AttributeError, TypeError ):
6253 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6254 return None
6255 except Exception:
6256 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006257 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006258
6259 def workQueueTotalInProgress( self, queueName ):
6260 """
6261 CLI command to get the Total In Progress items of the specified Work Queue.
6262 This function uses the distributed primitives test app, which
6263 gives some cli access to distributed primitives for testing
6264 purposes only.
6265
6266 Required arguments:
6267 queueName - The name of the queue to add to
6268 returns:
6269 The number of In Progress items in the specified work queue or
6270 None on error
6271 """
6272 try:
6273 queueName = str( queueName )
6274 prefix = "work-queue-test"
6275 operation = "totalInProgress"
6276 cmdStr = " ".join( [ prefix, queueName, operation ] )
6277 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006278 main.log.debug( self.name + ": work queue unparsed: " + output )
6279 output = output.split( "\r\n" )[ -1 ]
6280 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006281 pattern = r'\d+'
6282 if "Invalid operation name" in output:
6283 main.log.warn( output )
6284 return None
6285 else:
6286 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006287 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006288 except ( AttributeError, TypeError ):
6289 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6290 return None
6291 except Exception:
6292 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006293 main.cleanAndExit()
Jeremy Ronquillo818bc7c2017-08-09 17:14:53 +00006294
6295 def events( self, args='-a' ):
6296 """
6297 Description: Returns events -a command output
6298 Optional:
6299 add other arguments
6300 """
6301 try:
6302 cmdStr = "events"
6303 if args:
6304 cmdStr += " " + args
6305 handle = self.sendline( cmdStr )
6306 assert handle is not None, "Error in sendline"
6307 assert "Command not found:" not in handle, handle
6308 return handle
6309 except AssertionError:
6310 main.log.exception( "" )
6311 return None
6312 except TypeError:
6313 main.log.exception( self.name + ": Object not as expected" )
6314 return None
6315 except pexpect.EOF:
6316 main.log.error( self.name + ": EOF exception found" )
6317 main.log.error( self.name + ": " + self.handle.before )
6318 main.cleanAndExit()
6319 except Exception:
6320 main.log.exception( self.name + ": Uncaught exception!" )
6321 main.cleanAndExit()
6322
6323 def getMaster( self, deviceID ):
6324 """
6325 Description: Obtains current master using "roles" command for a specific deviceID
6326 """
6327 try:
6328 return str( self.getRole( deviceID )[ 'master' ] )
6329 except AssertionError:
6330 main.log.exception( "" )
6331 return None
6332 except TypeError:
6333 main.log.exception( self.name + ": Object not as expected" )
6334 return None
6335 except pexpect.EOF:
6336 main.log.error( self.name + ": EOF exception found" )
6337 main.log.error( self.name + ": " + self.handle.before )
6338 main.cleanAndExit()
6339 except Exception:
6340 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lime6fe3c42017-10-18 16:28:40 -07006341 main.cleanAndExit()
Jon Halla478b852017-12-04 15:00:15 -08006342
6343 def issu( self ):
6344 """
6345 Short summary of In-Service Software Upgrade status
6346
6347 Returns the output of the cli command or None on Error
6348 """
6349 try:
6350 cmdStr = "issu"
6351 handle = self.sendline( cmdStr )
6352 assert handle is not None, "Error in sendline"
6353 assert "Command not found:" not in handle, handle
6354 assert "Unsupported command:" not in handle, handle
6355 return handle
6356 except AssertionError:
6357 main.log.exception( "" )
6358 return None
6359 except TypeError:
6360 main.log.exception( self.name + ": Object not as expected" )
6361 return None
6362 except pexpect.EOF:
6363 main.log.error( self.name + ": EOF exception found" )
6364 main.log.error( self.name + ": " + self.handle.before )
6365 main.cleanAndExit()
6366 except Exception:
6367 main.log.exception( self.name + ": Uncaught exception!" )
6368 main.cleanAndExit()
6369
6370 def issuInit( self ):
6371 """
6372 Initiates an In-Service Software Upgrade
6373
6374 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6375 """
6376 try:
6377 cmdStr = "issu init"
6378 handle = self.sendline( cmdStr )
6379 assert handle is not None, "Error in sendline"
6380 assert "Command not found:" not in handle, handle
6381 assert "Unsupported command:" not in handle, handle
6382 if "Initialized" in handle:
6383 return main.TRUE
6384 else:
6385 return main.FALSE
6386 except AssertionError:
6387 main.log.exception( "" )
6388 return main.ERROR
6389 except TypeError:
6390 main.log.exception( self.name + ": Object not as expected" )
6391 return main.ERROR
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 issuUpgrade( self ):
6401 """
6402 Transitions stores to upgraded nodes
6403
6404 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6405 """
6406 try:
6407 cmdStr = "issu upgrade"
6408 handle = self.sendline( cmdStr )
6409 assert handle is not None, "Error in sendline"
6410 assert "Command not found:" not in handle, handle
6411 assert "Unsupported command:" not in handle, handle
6412 if "Upgraded" in handle:
6413 return main.TRUE
6414 else:
6415 return main.FALSE
6416 except AssertionError:
6417 main.log.exception( "" )
6418 return main.ERROR
6419 except TypeError:
6420 main.log.exception( self.name + ": Object not as expected" )
6421 return main.ERROR
6422 except pexpect.EOF:
6423 main.log.error( self.name + ": EOF exception found" )
6424 main.log.error( self.name + ": " + self.handle.before )
6425 main.cleanAndExit()
6426 except Exception:
6427 main.log.exception( self.name + ": Uncaught exception!" )
6428 main.cleanAndExit()
6429
6430 def issuCommit( self ):
6431 """
6432 Finalizes an In-Service Software Upgrade
6433
6434 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6435 """
6436 try:
6437 cmdStr = "issu commit"
6438 handle = self.sendline( cmdStr )
6439 assert handle is not None, "Error in sendline"
6440 assert "Command not found:" not in handle, handle
6441 assert "Unsupported command:" not in handle, handle
6442 # TODO: Check the version returned by this command
6443 if "Committed version" in handle:
6444 return main.TRUE
6445 else:
6446 return main.FALSE
6447 except AssertionError:
6448 main.log.exception( "" )
6449 return main.ERROR
6450 except TypeError:
6451 main.log.exception( self.name + ": Object not as expected" )
6452 return main.ERROR
6453 except pexpect.EOF:
6454 main.log.error( self.name + ": EOF exception found" )
6455 main.log.error( self.name + ": " + self.handle.before )
6456 main.cleanAndExit()
6457 except Exception:
6458 main.log.exception( self.name + ": Uncaught exception!" )
6459 main.cleanAndExit()
6460
6461 def issuRollback( self ):
6462 """
6463 Rolls back an In-Service Software Upgrade
6464
6465 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6466 """
6467 try:
6468 cmdStr = "issu rollback"
6469 handle = self.sendline( cmdStr )
6470 assert handle is not None, "Error in sendline"
6471 assert "Command not found:" not in handle, handle
6472 assert "Unsupported command:" not in handle, handle
6473 # TODO: Check the version returned by this command
6474 if "Rolled back to version" in handle:
6475 return main.TRUE
6476 else:
6477 return main.FALSE
6478 except AssertionError:
6479 main.log.exception( "" )
6480 return main.ERROR
6481 except TypeError:
6482 main.log.exception( self.name + ": Object not as expected" )
6483 return main.ERROR
6484 except pexpect.EOF:
6485 main.log.error( self.name + ": EOF exception found" )
6486 main.log.error( self.name + ": " + self.handle.before )
6487 main.cleanAndExit()
6488 except Exception:
6489 main.log.exception( self.name + ": Uncaught exception!" )
6490 main.cleanAndExit()
6491
6492 def issuReset( self ):
6493 """
6494 Resets the In-Service Software Upgrade status after a rollback
6495
6496 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6497 """
6498 try:
6499 cmdStr = "issu reset"
6500 handle = self.sendline( cmdStr )
6501 assert handle is not None, "Error in sendline"
6502 assert "Command not found:" not in handle, handle
6503 assert "Unsupported command:" not in handle, handle
6504 # TODO: Check the version returned by this command
6505 if "Reset version" in handle:
6506 return main.TRUE
6507 else:
6508 return main.FALSE
6509 except AssertionError:
6510 main.log.exception( "" )
6511 return main.ERROR
6512 except TypeError:
6513 main.log.exception( self.name + ": Object not as expected" )
6514 return main.ERROR
6515 except pexpect.EOF:
6516 main.log.error( self.name + ": EOF exception found" )
6517 main.log.error( self.name + ": " + self.handle.before )
6518 main.cleanAndExit()
6519 except Exception:
6520 main.log.exception( self.name + ": Uncaught exception!" )
6521 main.cleanAndExit()
6522
6523 def issuStatus( self ):
6524 """
6525 Status of an In-Service Software Upgrade
6526
6527 Returns the output of the cli command or None on Error
6528 """
6529 try:
6530 cmdStr = "issu status"
6531 handle = self.sendline( cmdStr )
6532 assert handle is not None, "Error in sendline"
6533 assert "Command not found:" not in handle, handle
6534 assert "Unsupported command:" not in handle, handle
6535 return handle
6536 except AssertionError:
6537 main.log.exception( "" )
6538 return None
6539 except TypeError:
6540 main.log.exception( self.name + ": Object not as expected" )
6541 return None
6542 except pexpect.EOF:
6543 main.log.error( self.name + ": EOF exception found" )
6544 main.log.error( self.name + ": " + self.handle.before )
6545 main.cleanAndExit()
6546 except Exception:
6547 main.log.exception( self.name + ": Uncaught exception!" )
6548 main.cleanAndExit()
6549
6550 def issuVersion( self ):
6551 """
6552 Get the version of an In-Service Software Upgrade
6553
6554 Returns the output of the cli command or None on Error
6555 """
6556 try:
6557 cmdStr = "issu version"
6558 handle = self.sendline( cmdStr )
6559 assert handle is not None, "Error in sendline"
6560 assert "Command not found:" not in handle, handle
6561 assert "Unsupported command:" not in handle, handle
6562 return handle
6563 except AssertionError:
6564 main.log.exception( "" )
6565 return None
6566 except TypeError:
6567 main.log.exception( self.name + ": Object not as expected" )
6568 return None
6569 except pexpect.EOF:
6570 main.log.error( self.name + ": EOF exception found" )
6571 main.log.error( self.name + ": " + self.handle.before )
6572 main.cleanAndExit()
6573 except Exception:
6574 main.log.exception( self.name + ": Uncaught exception!" )
6575 main.cleanAndExit()
You Wange24d6272018-03-27 21:18:50 -07006576
6577 def mcastJoin( self, sIP, groupIP, sPort, dPorts ):
6578 """
6579 Create a multicast route by calling 'mcast-join' command
6580 sIP: source IP of the multicast route
6581 groupIP: group IP of the multicast route
6582 sPort: source port (e.g. of:0000000000000001/3 ) of the multicast route
6583 dPorts: a list of destination ports of the multicast route
6584 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6585 """
6586 try:
6587 cmdStr = "mcast-join"
6588 cmdStr += " " + str( sIP )
6589 cmdStr += " " + str( groupIP )
6590 cmdStr += " " + str( sPort )
6591 assert isinstance( dPorts, list )
6592 for dPort in dPorts:
6593 cmdStr += " " + str( dPort )
6594 handle = self.sendline( cmdStr )
6595 assert handle is not None, "Error in sendline"
6596 assert "Command not found:" not in handle, handle
6597 assert "Unsupported command:" not in handle, handle
6598 assert "Error executing command" not in handle, handle
6599 if "Added the mcast route" in handle:
6600 return main.TRUE
6601 else:
6602 return main.FALSE
6603 except AssertionError:
6604 main.log.exception( "" )
6605 return None
6606 except TypeError:
6607 main.log.exception( self.name + ": Object not as expected" )
6608 return None
6609 except pexpect.EOF:
6610 main.log.error( self.name + ": EOF exception found" )
6611 main.log.error( self.name + ": " + self.handle.before )
6612 main.cleanAndExit()
6613 except Exception:
6614 main.log.exception( self.name + ": Uncaught exception!" )
6615 main.cleanAndExit()
6616
6617 def mcastDelete( self, sIP, groupIP, dPorts ):
6618 """
6619 Delete a multicast route by calling 'mcast-delete' command
6620 sIP: source IP of the multicast route
6621 groupIP: group IP of the multicast route
6622 dPorts: a list of destination ports of the multicast route
6623 Returns main.TRUE if mcast route is deleted; Otherwise main.FALSE
6624 """
6625 try:
6626 cmdStr = "mcast-delete"
6627 cmdStr += " " + str( sIP )
6628 cmdStr += " " + str( groupIP )
6629 assert isinstance( dPorts, list )
6630 for dPort in dPorts:
6631 cmdStr += " " + str( dPort )
6632 handle = self.sendline( cmdStr )
6633 assert handle is not None, "Error in sendline"
6634 assert "Command not found:" not in handle, handle
6635 assert "Unsupported command:" not in handle, handle
6636 assert "Error executing command" not in handle, handle
6637 if "Updated the mcast route" in handle:
6638 return main.TRUE
6639 else:
6640 return main.FALSE
6641 except AssertionError:
6642 main.log.exception( "" )
6643 return None
6644 except TypeError:
6645 main.log.exception( self.name + ": Object not as expected" )
6646 return None
6647 except pexpect.EOF:
6648 main.log.error( self.name + ": EOF exception found" )
6649 main.log.error( self.name + ": " + self.handle.before )
6650 main.cleanAndExit()
6651 except Exception:
6652 main.log.exception( self.name + ": Uncaught exception!" )
6653 main.cleanAndExit()
6654
6655 def mcastHostJoin( self, sAddr, gAddr, srcs, sinks ):
6656 """
6657 Create a multicast route by calling 'mcast-host-join' command
6658 sAddr: we can provide * for ASM or a specific address for SSM
6659 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006660 srcs: a list of HostId of the sources e.g. ["00:AA:00:00:00:01/None"]
You Wange24d6272018-03-27 21:18:50 -07006661 sinks: a list of HostId of the sinks e.g. ["00:AA:00:00:01:05/40"]
6662 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6663 """
6664 try:
6665 cmdStr = "mcast-host-join"
6666 cmdStr += " -sAddr " + str( sAddr )
6667 cmdStr += " -gAddr " + str( gAddr )
6668 assert isinstance( srcs, list )
6669 for src in srcs:
6670 cmdStr += " -srcs " + str( src )
6671 assert isinstance( sinks, list )
6672 for sink in sinks:
6673 cmdStr += " -sinks " + str( sink )
6674 handle = self.sendline( cmdStr )
6675 assert handle is not None, "Error in sendline"
6676 assert "Command not found:" not in handle, handle
6677 assert "Unsupported command:" not in handle, handle
6678 assert "Error executing command" not in handle, handle
6679 if "Added the mcast route" in handle:
6680 return main.TRUE
6681 else:
6682 return main.FALSE
6683 except AssertionError:
6684 main.log.exception( "" )
6685 return None
6686 except TypeError:
6687 main.log.exception( self.name + ": Object not as expected" )
6688 return None
6689 except pexpect.EOF:
6690 main.log.error( self.name + ": EOF exception found" )
6691 main.log.error( self.name + ": " + self.handle.before )
6692 main.cleanAndExit()
6693 except Exception:
6694 main.log.exception( self.name + ": Uncaught exception!" )
6695 main.cleanAndExit()
6696
6697 def mcastHostDelete( self, sAddr, gAddr, host=None ):
6698 """
6699 Delete multicast sink(s) by calling 'mcast-host-delete' command
6700 sAddr: we can provide * for ASM or a specific address for SSM
6701 gAddr: specifies multicast group address
You Wangc02d8352018-04-17 16:42:10 -07006702 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
You Wange24d6272018-03-27 21:18:50 -07006703 will delete the route if not specified
6704 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6705 """
6706 try:
6707 cmdStr = "mcast-host-delete"
6708 cmdStr += " -sAddr " + str( sAddr )
6709 cmdStr += " -gAddr " + str( gAddr )
6710 if host:
6711 cmdStr += " -h " + str( host )
6712 handle = self.sendline( cmdStr )
6713 assert handle is not None, "Error in sendline"
6714 assert "Command not found:" not in handle, handle
6715 assert "Unsupported command:" not in handle, handle
6716 assert "Error executing command" not in handle, handle
6717 if "Updated the mcast route" in handle:
6718 return main.TRUE
6719 elif "Deleted the mcast route" in handle:
6720 return main.TRUE
6721 else:
6722 return main.FALSE
6723 except AssertionError:
6724 main.log.exception( "" )
6725 return None
6726 except TypeError:
6727 main.log.exception( self.name + ": Object not as expected" )
6728 return None
6729 except pexpect.EOF:
6730 main.log.error( self.name + ": EOF exception found" )
6731 main.log.error( self.name + ": " + self.handle.before )
6732 main.cleanAndExit()
6733 except Exception:
6734 main.log.exception( self.name + ": Uncaught exception!" )
6735 main.cleanAndExit()
6736
You Wang547893e2018-05-08 13:34:59 -07006737 def mcastSinkDelete( self, sAddr, gAddr, sink=None ):
6738 """
6739 Delete multicast sink(s) by calling 'mcast-sink-delete' command
6740 sAddr: we can provide * for ASM or a specific address for SSM
6741 gAddr: specifies multicast group address
6742 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
6743 will delete the route if not specified
6744 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6745 """
6746 try:
6747 cmdStr = "mcast-sink-delete"
6748 cmdStr += " -sAddr " + str( sAddr )
6749 cmdStr += " -gAddr " + str( gAddr )
6750 if sink:
6751 cmdStr += " -s " + str( sink )
6752 handle = self.sendline( cmdStr )
6753 assert handle is not None, "Error in sendline"
6754 assert "Command not found:" not in handle, handle
6755 assert "Unsupported command:" not in handle, handle
6756 assert "Error executing command" not in handle, handle
6757 if "Updated the mcast route" in handle:
6758 return main.TRUE
6759 elif "Deleted the mcast route" in handle:
6760 return main.TRUE
6761 else:
6762 return main.FALSE
6763 except AssertionError:
6764 main.log.exception( "" )
6765 return None
6766 except TypeError:
6767 main.log.exception( self.name + ": Object not as expected" )
6768 return None
6769 except pexpect.EOF:
6770 main.log.error( self.name + ": EOF exception found" )
6771 main.log.error( self.name + ": " + self.handle.before )
6772 main.cleanAndExit()
6773 except Exception:
6774 main.log.exception( self.name + ": Uncaught exception!" )
6775 main.cleanAndExit()
6776
You Wange24d6272018-03-27 21:18:50 -07006777 def mcastSourceDelete( self, sAddr, gAddr, srcs=None ):
6778 """
6779 Delete multicast src(s) by calling 'mcast-source-delete' command
6780 sAddr: we can provide * for ASM or a specific address for SSM
6781 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006782 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 -07006783 will delete the route if not specified
6784 Returns main.TRUE if mcast sink is deleted; Otherwise main.FALSE
6785 """
6786 try:
6787 cmdStr = "mcast-source-delete"
6788 cmdStr += " -sAddr " + str( sAddr )
6789 cmdStr += " -gAddr " + str( gAddr )
6790 if srcs:
6791 assert isinstance( srcs, list )
6792 for src in srcs:
6793 cmdStr += " -src " + str( src )
6794 handle = self.sendline( cmdStr )
6795 assert handle is not None, "Error in sendline"
6796 assert "Command not found:" not in handle, handle
6797 assert "Unsupported command:" not in handle, handle
6798 assert "Error executing command" not in handle, handle
6799 if "Updated the mcast route" in handle:
6800 return main.TRUE
6801 elif "Deleted the mcast route" in handle:
6802 return main.TRUE
6803 else:
6804 return main.FALSE
6805 except AssertionError:
6806 main.log.exception( "" )
6807 return None
6808 except TypeError:
6809 main.log.exception( self.name + ": Object not as expected" )
6810 return None
6811 except pexpect.EOF:
6812 main.log.error( self.name + ": EOF exception found" )
6813 main.log.error( self.name + ": " + self.handle.before )
6814 main.cleanAndExit()
6815 except Exception:
6816 main.log.exception( self.name + ": Uncaught exception!" )
6817 main.cleanAndExit()
You Wang5da39c82018-04-26 22:55:08 -07006818
6819 def netcfg( self, jsonFormat=True, args="" ):
6820 """
6821 Run netcfg cli command with given args
6822 """
6823 try:
6824 cmdStr = "netcfg"
6825 if jsonFormat:
6826 cmdStr = cmdStr + " -j"
6827 if args:
6828 cmdStr = cmdStr + " " + str( args )
6829 handle = self.sendline( cmdStr )
6830 assert handle is not None, "Error in sendline"
6831 assert "Command not found:" not in handle, handle
6832 assert "Unsupported command:" not in handle, handle
6833 assert "Error executing command" not in handle, handle
6834 return handle
6835 except AssertionError:
6836 main.log.exception( "" )
6837 return None
6838 except TypeError:
6839 main.log.exception( self.name + ": Object not as expected" )
6840 return None
6841 except pexpect.EOF:
6842 main.log.error( self.name + ": EOF exception found" )
6843 main.log.error( self.name + ": " + self.handle.before )
6844 main.cleanAndExit()
6845 except Exception:
6846 main.log.exception( self.name + ": Uncaught exception!" )
6847 main.cleanAndExit()
6848
You Wang0fa76e72018-05-18 11:33:25 -07006849 def composeT3Command( self, sAddr, dAddr, ipv6=False, verbose=True, simple=False ):
You Wang5da39c82018-04-26 22:55:08 -07006850 """
You Wang54b1d672018-06-11 16:44:13 -07006851 Compose and return a list of t3-troubleshoot cli commands for given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006852 Options:
6853 sAddr: IP address of the source host
6854 dAddr: IP address of the destination host
You Wang0fa76e72018-05-18 11:33:25 -07006855 ipv6: True if hosts are IPv6
6856 verbose: return verbose t3 output if True
6857 simple: compose command for t3-troubleshoot-simple if True
You Wang5da39c82018-04-26 22:55:08 -07006858 """
6859 try:
6860 # Collect information of both hosts from onos
6861 hosts = self.hosts()
6862 hosts = json.loads( hosts )
6863 sHost = None
6864 dHost = None
6865 for host in hosts:
6866 if sAddr in host[ "ipAddresses" ]:
6867 sHost = host
6868 elif dAddr in host[ "ipAddresses" ]:
6869 dHost = host
6870 if sHost and dHost:
6871 break
6872 assert sHost, "Not able to find host with IP {}".format( sAddr )
You Wang54b1d672018-06-11 16:44:13 -07006873 cmdList = []
You Wang5d9527b2018-05-29 17:08:54 -07006874 if simple:
6875 assert dHost, "Not able to find host with IP {}".format( dAddr )
You Wang54b1d672018-06-11 16:44:13 -07006876 cmdStr = "t3-troubleshoot-simple"
6877 if verbose:
6878 cmdStr += " -vv"
6879 if ipv6:
6880 cmdStr += " -et ipv6"
You Wang0fa76e72018-05-18 11:33:25 -07006881 cmdStr += " {}/{} {}/{}".format( sHost[ "mac" ], sHost[ "vlan" ], dHost[ "mac" ], dHost[ "vlan" ] )
You Wang54b1d672018-06-11 16:44:13 -07006882 cmdList.append( cmdStr )
You Wang0fa76e72018-05-18 11:33:25 -07006883 else:
You Wang54b1d672018-06-11 16:44:13 -07006884 for location in sHost[ "locations" ]:
6885 cmdStr = "t3-troubleshoot"
6886 if verbose:
6887 cmdStr += " -vv"
6888 if ipv6:
6889 cmdStr += " -et ipv6"
6890 cmdStr += " -s " + str( sAddr )
6891 cmdStr += " -sp " + str( location[ "elementId" ] ) + "/" + str( location[ "port" ] )
6892 cmdStr += " -sm " + str( sHost[ "mac" ] )
6893 if sHost[ "vlan" ] != "None":
6894 cmdStr += " -vid " + sHost[ "vlan" ]
6895 cmdStr += " -d " + str( dAddr )
6896 netcfg = self.netcfg( args="devices {}".format( location[ "elementId" ] ) )
6897 netcfg = json.loads( netcfg )
6898 assert netcfg, "Failed to get netcfg"
6899 cmdStr += " -dm " + str( netcfg[ "segmentrouting" ][ "routerMac" ] )
6900 cmdList.append( cmdStr )
6901 return cmdList
You Wang5da39c82018-04-26 22:55:08 -07006902 except AssertionError:
6903 main.log.exception( "" )
6904 return None
6905 except ( KeyError, TypeError ):
6906 main.log.exception( self.name + ": Object not as expected" )
6907 return None
6908 except Exception:
6909 main.log.exception( self.name + ": Uncaught exception!" )
6910 main.cleanAndExit()
6911
6912 def t3( self, sAddr, dAddr, ipv6=False ):
6913 """
You Wang54b1d672018-06-11 16:44:13 -07006914 Run t3-troubleshoot cli commands for all posible routes given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006915 Options:
6916 sAddr: IP address of the source host
6917 dAddr: IP address of the destination host
6918 """
6919 try:
You Wang54b1d672018-06-11 16:44:13 -07006920 cmdList = self.composeT3Command( sAddr, dAddr, ipv6 )
6921 assert cmdList is not None, "composeT3Command returned None"
6922 t3Output = ""
6923 for cmdStr in cmdList:
6924 handle = self.sendline( cmdStr )
6925 assert handle is not None, "Error in sendline"
6926 assert "Command not found:" not in handle, handle
6927 assert "Unsupported command:" not in handle, handle
6928 assert "Error executing command" not in handle, handle
6929 assert "Tracing packet" in handle
6930 t3Output += handle
6931 return t3Output
You Wang5da39c82018-04-26 22:55:08 -07006932 except AssertionError:
6933 main.log.exception( "" )
6934 return None
6935 except pexpect.EOF:
6936 main.log.error( self.name + ": EOF exception found" )
6937 main.log.error( self.name + ": " + self.handle.before )
6938 main.cleanAndExit()
6939 except Exception:
6940 main.log.exception( self.name + ": Uncaught exception!" )
6941 main.cleanAndExit()
Jon Hall3c0114c2020-08-11 15:07:42 -07006942
6943 def prepareForCLI( self, debug=True, maxRetries=120 ):
6944 """
6945 Prepare docker container to connect to onos cli
6946 """
6947 try:
6948 # Wait for log files to be created
6949 ready = 0
6950 retries = 0
6951 while not ready and retries < maxRetries:
6952 retries += 1
6953 self.handle.sendline( "ls -al /root/onos/apache-karaf-*/data/log" )
6954 ready = self.handle.expect( [ "No such file or directory", self.dockerPrompt ] )
6955 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6956 if not ready:
6957 self.handle.expect( self.dockerPrompt )
6958 time.sleep( 1 )
Jon Hall3c0114c2020-08-11 15:07:42 -07006959
6960 cmdList = []
6961 cmdList.append( "apt-get update" )
6962 cmdList.append( "apt-get install -y openssh-server" )
6963 # Some built in scripts are hardcoded
6964 cmdList.append( "ln -s /root/onos /opt/onos" )
6965 cmdList.append( "ln -s /root/onos/apache-karaf-*/data/log /opt/onos/log" )
6966 cmdList.append( "ls -al /opt/onos" )
6967 output = ""
6968 for cmdStr in cmdList:
6969 self.handle.sendline( cmdStr )
Jon Hall627b1572020-12-01 12:01:15 -08006970 self.handle.expect( self.dockerPrompt, timeout=420 )
Jon Hall3c0114c2020-08-11 15:07:42 -07006971 self.handle.sendline( "" )
6972 self.handle.expect( self.dockerPrompt )
6973 handle = self.handle.before
6974 assert "command not found" not in handle, handle
6975 assert "No such file or directory" not in handle, handle
6976 output += handle
6977 if debug:
6978 main.log.debug( "%s: %s" % ( self.name, output ) )
6979 return output
6980 except AssertionError:
6981 main.log.exception( "" )
6982 return None
6983 except pexpect.EOF:
6984 main.log.error( self.name + ": EOF exception found" )
6985 main.log.error( self.name + ": " + self.handle.before )
6986 main.cleanAndExit()
6987 except Exception:
6988 main.log.exception( self.name + ": Uncaught exception!" )
6989 main.cleanAndExit()
6990
6991 def onosSecureSSH( self, userName="onos", userPWD="rocks" ):
6992 """
6993 Enables secure access to ONOS console
6994 by removing default users & keys.
6995
6996 bin/onos-user-password onos rocks
6997
6998 Returns: main.TRUE on success and main.FALSE on failure
6999 """
7000
7001 try:
7002 self.handle.sendline( "" )
7003 self.handle.expect( self.dockerPrompt )
7004
7005 self.handle.sendline( "[ ! -f ~/.ssh/id_rsa.pub ] && ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' -q" )
7006 self.handle.expect( self.dockerPrompt )
7007 main.log.debug( "%s: %s%s" % ( self.name, self.handle.before, self.handle.after ) )
7008
7009 self.handle.sendline( "bin/onos-user-key $(id -un) $(cut -d\\\\ -f2 ~/.ssh/id_rsa.pub)" )
7010 self.handle.expect( pexpect.TIMEOUT, timeout=10 )
7011 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
7012
7013 self.handle.sendline( "bin/onos-user-password %s %s" % ( userName, userPWD ) )
7014 i = self.handle.expect( [ "usage",
7015 self.dockerPrompt,
7016 pexpect.TIMEOUT ] )
7017 if i == 0:
7018 # malformed command
7019 main.log.warn( self.name + ": Could not parse onos-user-password command" )
7020 self.handle.expect( self.dockerPrompt )
7021 return main.FALSE
7022 elif i == 1:
7023 # Process started
7024 main.log.info( self.name + ": SSH password added for user " + userName )
7025 return main.TRUE
7026 elif i == 2:
7027 # timeout
7028 main.log.error( self.name + ": Failed to secure onos ssh " )
7029 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
7030 except pexpect.EOF:
7031 main.log.error( self.name + ": EOF exception found" )
7032 main.log.error( self.name + ": " + self.handle.before )
7033 main.cleanAndExit()
7034 except Exception:
7035 main.log.exception( self.name + ": Uncaught exception!" )
7036 main.cleanAndExit()
Jon Hall62ab6752021-08-22 16:47:43 -07007037
7038 def routeAdd( self, prefix, nextHop, jsonFormat=True ):
7039 """
7040 Add a route with the given prefix and nextHop
7041 """
7042 try:
7043 cmdStr = "route-add %s %s %s" % ( "-j" if jsonFormat else "", prefix, nextHop )
7044 handle = self.sendline( cmdStr )
7045 assert handle is not None, "Error in sendline"
7046 assert "Command not found:" not in handle, handle
7047 assert "Unsupported command:" not in handle, handle
7048 assert "Error executing command" not in handle, handle
7049 return handle
7050 except AssertionError:
7051 main.log.exception( "" )
7052 return None
7053 except TypeError:
7054 main.log.exception( self.name + ": Object not as expected" )
7055 return None
7056 except pexpect.EOF:
7057 main.log.error( self.name + ": EOF exception found" )
7058 main.log.error( self.name + ": " + self.handle.before )
7059 main.cleanAndExit()
7060 except Exception:
7061 main.log.exception( self.name + ": Uncaught exception!" )
7062 main.cleanAndExit()
7063
7064 def routeRemove( self, prefix, nextHop, source=None, jsonFormat=True ):
7065 """
7066 Remove a route with the given prefix and nextHop
7067 """
7068 try:
7069 if source:
7070 raise NotImplemented
7071 cmdStr = "route-remove %s %s %s" % ( "-j" if jsonFormat else "", prefix, nextHop )
7072 handle = self.sendline( cmdStr )
7073 assert handle is not None, "Error in sendline"
7074 assert "Command not found:" not in handle, handle
7075 assert "Unsupported command:" not in handle, handle
7076 assert "Error executing command" not in handle, handle
7077 return handle
7078 except AssertionError:
7079 main.log.exception( "" )
7080 return None
7081 except TypeError:
7082 main.log.exception( self.name + ": Object not as expected" )
7083 return None
7084 except pexpect.EOF:
7085 main.log.error( self.name + ": EOF exception found" )
7086 main.log.error( self.name + ": " + self.handle.before )
7087 main.cleanAndExit()
7088 except Exception:
7089 main.log.exception( self.name + ": Uncaught exception!" )
7090 main.cleanAndExit()
7091
7092 def routes( self, jsonFormat=True, args="" ):
7093 """
7094 Get routes from ONOS
7095 """
7096 try:
7097 cmdStr = "routes"
7098 if jsonFormat:
7099 cmdStr = cmdStr + " -j"
7100 handle = self.sendline( cmdStr )
7101 assert handle is not None, "Error in sendline"
7102 assert "Command not found:" not in handle, handle
7103 assert "Unsupported command:" not in handle, handle
7104 assert "Error executing command" not in handle, handle
7105 return handle
7106 except AssertionError:
7107 main.log.exception( "" )
7108 return None
7109 except TypeError:
7110 main.log.exception( self.name + ": Object not as expected" )
7111 return None
7112 except pexpect.EOF:
7113 main.log.error( self.name + ": EOF exception found" )
7114 main.log.error( self.name + ": " + self.handle.before )
7115 main.cleanAndExit()
7116 except Exception:
7117 main.log.exception( self.name + ": Uncaught exception!" )
7118 main.cleanAndExit()