blob: f0418714a332cae4ee8b70375a84bbe150b3cc07 [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
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002679 def flows( self, state="any", jsonFormat=True, timeout=60, noExit=False, noCore=False, device=""):
kelvin8ec71442015-01-15 16:57:00 -08002680 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002681 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002682 * jsonFormat: enable output formatting in json
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002683 * noCore: suppress core flows
Shreya Shah0f01c812014-10-26 20:15:28 -04002684 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002685 Obtain flows currently installed
kelvin-onlab898a6c62015-01-16 14:13:53 -08002686 """
Shreya Shah0f01c812014-10-26 20:15:28 -04002687 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002688 cmdStr = "flows"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002689 if jsonFormat:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002690 cmdStr += " -j"
Jeremy Songster306ed7a2016-07-19 10:59:07 -07002691 if noCore:
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07002692 cmdStr += " -n"
2693 cmdStr += " " + state
2694 cmdStr += " " + device
YPZhangebf9eb52016-05-12 15:20:24 -07002695 handle = self.sendline( cmdStr, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002696 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002697 assert "Command not found:" not in handle, handle
2698 if re.search( "Error:", handle ):
2699 main.log.error( self.name + ": flows() response: " +
2700 str( handle ) )
2701 return handle
2702 except AssertionError:
2703 main.log.exception( "" )
GlennRCed771242016-01-13 17:02:47 -08002704 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002705 except TypeError:
2706 main.log.exception( self.name + ": Object not as expected" )
2707 return None
Jon Hallc6793552016-01-19 14:18:37 -08002708 except pexpect.TIMEOUT:
2709 main.log.error( self.name + ": ONOS timeout" )
2710 return None
Shreya Shah0f01c812014-10-26 20:15:28 -04002711 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002712 main.log.error( self.name + ": EOF exception found" )
2713 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002714 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002715 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002716 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002717 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002718
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002719 def checkFlowCount( self, min=0, timeout=60 ):
Flavio Castroa1286fe2016-07-25 14:48:51 -07002720 count = self.getTotalFlowsNum( timeout=timeout )
Jon Halle0f0b342017-04-18 11:43:47 -07002721 count = int( count ) if count else 0
steven30801eccfe212019-01-24 13:00:42 +08002722 main.log.debug( "found {} flows".format( count ) )
Jon Hall39570262020-11-17 12:18:19 -08002723 return count if ( count >= min ) else False
GlennRCed771242016-01-13 17:02:47 -08002724
Jon Halle0f0b342017-04-18 11:43:47 -07002725 def checkFlowsState( self, isPENDING=True, timeout=60, noExit=False ):
kelvin-onlab4df89f22015-04-13 18:10:23 -07002726 """
2727 Description:
GlennRCed771242016-01-13 17:02:47 -08002728 Check the if all the current flows are in ADDED state
Jon Hallc6793552016-01-19 14:18:37 -08002729 We check PENDING_ADD, PENDING_REMOVE, REMOVED, and FAILED flows,
2730 if the count of those states is 0, which means all current flows
2731 are in ADDED state, and return main.TRUE otherwise return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002732 Optional:
GlennRCed771242016-01-13 17:02:47 -08002733 * isPENDING: whether the PENDING_ADD is also a correct status
kelvin-onlab4df89f22015-04-13 18:10:23 -07002734 Return:
2735 returnValue - Returns main.TRUE only if all flows are in
Jon Hallc6793552016-01-19 14:18:37 -08002736 ADDED state or PENDING_ADD if the isPENDING
pingping-linbab7f8a2015-09-21 17:33:36 -07002737 parameter is set true, return main.FALSE otherwise.
kelvin-onlab4df89f22015-04-13 18:10:23 -07002738 """
2739 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002740 states = [ "PENDING_ADD", "PENDING_REMOVE", "REMOVED", "FAILED" ]
GlennRCed771242016-01-13 17:02:47 -08002741 checkedStates = []
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002742 statesCount = [ 0, 0, 0, 0 ]
GlennRCed771242016-01-13 17:02:47 -08002743 for s in states:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002744 rawFlows = self.flows( state=s, timeout = timeout )
YPZhang240842b2016-05-17 12:00:50 -07002745 if rawFlows:
2746 # if we didn't get flows or flows function return None, we should return
2747 # main.Flase
2748 checkedStates.append( json.loads( rawFlows ) )
2749 else:
2750 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08002751 for i in range( len( states ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002752 for c in checkedStates[ i ]:
Jon Hallc6793552016-01-19 14:18:37 -08002753 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002754 statesCount[ i ] += int( c.get( "flowCount" ) )
Jon Hallc6793552016-01-19 14:18:37 -08002755 except TypeError:
2756 main.log.exception( "Json object not as expected" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002757 main.log.info( states[ i ] + " flows: " + str( statesCount[ i ] ) )
kelvin-onlabf2ec6e02015-05-27 14:15:28 -07002758
GlennRCed771242016-01-13 17:02:47 -08002759 # We want to count PENDING_ADD if isPENDING is true
2760 if isPENDING:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002761 if statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002762 return main.FALSE
pingping-linbab7f8a2015-09-21 17:33:36 -07002763 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002764 if statesCount[ 0 ] + statesCount[ 1 ] + statesCount[ 2 ] + statesCount[ 3 ] > 0:
GlennRCed771242016-01-13 17:02:47 -08002765 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08002766 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08002767 except ( TypeError, ValueError ):
2768 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawFlows ) )
kelvin-onlab4df89f22015-04-13 18:10:23 -07002769 return None
Jeremy Songster9385d412016-06-02 17:57:36 -07002770
YPZhang240842b2016-05-17 12:00:50 -07002771 except AssertionError:
2772 main.log.exception( "" )
2773 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002774 except pexpect.TIMEOUT:
2775 main.log.error( self.name + ": ONOS timeout" )
2776 return None
kelvin-onlab4df89f22015-04-13 18:10:23 -07002777 except pexpect.EOF:
2778 main.log.error( self.name + ": EOF exception found" )
2779 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002780 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002781 except Exception:
2782 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002783 main.cleanAndExit()
kelvin-onlab4df89f22015-04-13 18:10:23 -07002784
GlennRCed771242016-01-13 17:02:47 -08002785 def pushTestIntents( self, ingress, egress, batchSize, offset="",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002786 options="", timeout=10, background = False, noExit=False, getResponse=False ):
kelvin8ec71442015-01-15 16:57:00 -08002787 """
andrewonlab87852b02014-11-19 18:44:19 -05002788 Description:
Jon Halle3f39ff2015-01-13 11:50:53 -08002789 Push a number of intents in a batch format to
andrewonlab87852b02014-11-19 18:44:19 -05002790 a specific point-to-point intent definition
2791 Required:
GlennRCed771242016-01-13 17:02:47 -08002792 * ingress: specify source dpid
2793 * egress: specify destination dpid
2794 * batchSize: specify number of intents to push
andrewonlab87852b02014-11-19 18:44:19 -05002795 Optional:
GlennRCed771242016-01-13 17:02:47 -08002796 * offset: the keyOffset is where the next batch of intents
2797 will be installed
YPZhangb34b7e12016-06-14 14:28:19 -07002798 * noExit: If set to True, TestON will not exit if any error when issus command
2799 * getResponse: If set to True, function will return ONOS response.
2800
GlennRCed771242016-01-13 17:02:47 -08002801 Returns: If failed to push test intents, it will returen None,
2802 if successful, return true.
2803 Timeout expection will return None,
2804 TypeError will return false
2805 other expections will exit()
kelvin8ec71442015-01-15 16:57:00 -08002806 """
andrewonlab87852b02014-11-19 18:44:19 -05002807 try:
GlennRCed771242016-01-13 17:02:47 -08002808 if background:
2809 back = "&"
andrewonlab87852b02014-11-19 18:44:19 -05002810 else:
GlennRCed771242016-01-13 17:02:47 -08002811 back = ""
2812 cmd = "push-test-intents {} {} {} {} {} {}".format( options,
Jon Hallc6793552016-01-19 14:18:37 -08002813 ingress,
2814 egress,
2815 batchSize,
2816 offset,
2817 back )
YPZhangebf9eb52016-05-12 15:20:24 -07002818 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
You Wangb5a55f72017-03-03 12:51:05 -08002819 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002820 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08002821 main.log.info( response )
YPZhangb34b7e12016-06-14 14:28:19 -07002822 if getResponse:
2823 return response
2824
GlennRCed771242016-01-13 17:02:47 -08002825 # TODO: We should handle if there is failure in installation
2826 return main.TRUE
2827
Jon Hallc6793552016-01-19 14:18:37 -08002828 except AssertionError:
2829 main.log.exception( "" )
2830 return None
GlennRCed771242016-01-13 17:02:47 -08002831 except pexpect.TIMEOUT:
2832 main.log.error( self.name + ": ONOS timeout" )
Jon Halld4d4b372015-01-28 16:02:41 -08002833 return None
andrewonlab87852b02014-11-19 18:44:19 -05002834 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002835 main.log.error( self.name + ": EOF exception found" )
2836 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002837 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08002838 except TypeError:
2839 main.log.exception( self.name + ": Object not as expected" )
Jon Hallc6793552016-01-19 14:18:37 -08002840 return None
Jon Hallfebb1c72015-03-05 13:30:09 -08002841 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002842 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002843 main.cleanAndExit()
andrewonlab87852b02014-11-19 18:44:19 -05002844
YPZhangebf9eb52016-05-12 15:20:24 -07002845 def getTotalFlowsNum( self, timeout=60, noExit=False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002846 """
2847 Description:
YPZhangf6f14a02016-01-28 15:17:31 -08002848 Get the number of ADDED flows.
YPZhangb5d3f832016-01-23 22:54:26 -08002849 Return:
YPZhangf6f14a02016-01-28 15:17:31 -08002850 The number of ADDED flows
YPZhang14a4aa92016-07-15 13:37:15 -07002851 Or return None if any exceptions
YPZhangb5d3f832016-01-23 22:54:26 -08002852 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002853
YPZhangb5d3f832016-01-23 22:54:26 -08002854 try:
YPZhange3109a72016-02-02 11:25:37 -08002855 # get total added flows number
YPZhang14a4aa92016-07-15 13:37:15 -07002856 cmd = "flows -c added"
2857 rawFlows = self.sendline( cmd, timeout=timeout, noExit=noExit )
2858 if rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002859 rawFlows = rawFlows.split( "\n" )
YPZhange3109a72016-02-02 11:25:37 -08002860 totalFlows = 0
YPZhang14a4aa92016-07-15 13:37:15 -07002861 for l in rawFlows:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002862 totalFlows += int( l.split( "Count=" )[ 1 ] )
YPZhang14a4aa92016-07-15 13:37:15 -07002863 else:
You Wang68568b12019-03-04 11:49:57 -08002864 main.log.warn( "Response not as expected!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002865 return None
2866 return totalFlows
YPZhange3109a72016-02-02 11:25:37 -08002867
You Wangd3097f72018-12-12 11:56:03 -08002868 except IndexError:
2869 main.log.exception( "{}: Object not as expected!".format( self.name ) )
2870 main.log.debug( "rawFlows: {}".format( rawFlows ) )
2871 return None
You Wangd3cb2ce2016-05-16 14:01:24 -07002872 except ( TypeError, ValueError ):
YPZhang14a4aa92016-07-15 13:37:15 -07002873 main.log.exception( "{}: Object not as expected!".format( self.name ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002874 return None
2875 except pexpect.EOF:
2876 main.log.error( self.name + ": EOF exception found" )
2877 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002878 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002879 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002880 return None
Jon Halle0f0b342017-04-18 11:43:47 -07002881 except pexpect.TIMEOUT:
2882 main.log.error( self.name + ": ONOS timeout" )
2883 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002884 except Exception:
2885 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002886 if not noExit:
Devin Lim44075962017-08-11 10:56:37 -07002887 main.cleanAndExit()
YPZhang14a4aa92016-07-15 13:37:15 -07002888 return None
YPZhangb5d3f832016-01-23 22:54:26 -08002889
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002890 def getTotalIntentsNum( self, timeout=60, noExit = False ):
YPZhangb5d3f832016-01-23 22:54:26 -08002891 """
2892 Description:
2893 Get the total number of intents, include every states.
YPZhang14a4aa92016-07-15 13:37:15 -07002894 Optional:
2895 noExit - If noExit, TestON will not exit if any except.
YPZhangb5d3f832016-01-23 22:54:26 -08002896 Return:
2897 The number of intents
2898 """
2899 try:
2900 cmd = "summary -j"
YPZhang14a4aa92016-07-15 13:37:15 -07002901 response = self.sendline( cmd, timeout=timeout, noExit=noExit )
Jon Halle0f0b342017-04-18 11:43:47 -07002902 if response is None:
2903 return -1
YPZhangb5d3f832016-01-23 22:54:26 -08002904 response = json.loads( response )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002905 return int( response.get( "intents" ) )
You Wangd3cb2ce2016-05-16 14:01:24 -07002906 except ( TypeError, ValueError ):
2907 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, response ) )
YPZhangb5d3f832016-01-23 22:54:26 -08002908 return None
2909 except pexpect.EOF:
2910 main.log.error( self.name + ": EOF exception found" )
2911 main.log.error( self.name + ": " + self.handle.before )
YPZhang14a4aa92016-07-15 13:37:15 -07002912 if noExit:
2913 return -1
2914 else:
Devin Lim44075962017-08-11 10:56:37 -07002915 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002916 except Exception:
2917 main.log.exception( self.name + ": Uncaught exception!" )
YPZhang14a4aa92016-07-15 13:37:15 -07002918 if noExit:
2919 return -1
2920 else:
Devin Lim44075962017-08-11 10:56:37 -07002921 main.cleanAndExit()
YPZhangb5d3f832016-01-23 22:54:26 -08002922
kelvin-onlabd3b64892015-01-20 13:26:24 -08002923 def intentsEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002924 """
Jon Halle3f39ff2015-01-13 11:50:53 -08002925 Description:Returns topology metrics
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002926 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002927 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002928 """
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002929 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002930 cmdStr = "intents-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002931 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002932 cmdStr += " -j"
2933 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002934 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002935 assert "Command not found:" not in handle, handle
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002936 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002937 except AssertionError:
2938 main.log.exception( "" )
2939 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002940 except TypeError:
2941 main.log.exception( self.name + ": Object not as expected" )
2942 return None
andrewonlab0dbb6ec2014-11-06 13:46:55 -05002943 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002944 main.log.error( self.name + ": EOF exception found" )
2945 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002946 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002947 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002948 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002949 main.cleanAndExit()
Shreya Shah0f01c812014-10-26 20:15:28 -04002950
kelvin-onlabd3b64892015-01-20 13:26:24 -08002951 def topologyEventsMetrics( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08002952 """
2953 Description:Returns topology metrics
andrewonlab867212a2014-10-22 20:13:38 -04002954 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08002955 * jsonFormat: enable json formatting of output
kelvin8ec71442015-01-15 16:57:00 -08002956 """
andrewonlab867212a2014-10-22 20:13:38 -04002957 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07002958 cmdStr = "topology-events-metrics"
kelvin-onlabd3b64892015-01-20 13:26:24 -08002959 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07002960 cmdStr += " -j"
2961 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08002962 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08002963 assert "Command not found:" not in handle, handle
jenkins7ead5a82015-03-13 10:28:21 -07002964 if handle:
2965 return handle
Jon Hallc6358dd2015-04-10 12:44:28 -07002966 elif jsonFormat:
Jon Hallbe379602015-03-24 13:39:32 -07002967 # Return empty json
jenkins7ead5a82015-03-13 10:28:21 -07002968 return '{}'
Jon Hallc6358dd2015-04-10 12:44:28 -07002969 else:
2970 return handle
Jon Hallc6793552016-01-19 14:18:37 -08002971 except AssertionError:
2972 main.log.exception( "" )
2973 return None
Jon Halld4d4b372015-01-28 16:02:41 -08002974 except TypeError:
2975 main.log.exception( self.name + ": Object not as expected" )
2976 return None
andrewonlab867212a2014-10-22 20:13:38 -04002977 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08002978 main.log.error( self.name + ": EOF exception found" )
2979 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002980 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08002981 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08002982 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002983 main.cleanAndExit()
andrewonlab867212a2014-10-22 20:13:38 -04002984
kelvin8ec71442015-01-15 16:57:00 -08002985 # Wrapper functions ****************
2986 # Wrapper functions use existing driver
2987 # functions and extends their use case.
2988 # For example, we may use the output of
2989 # a normal driver function, and parse it
2990 # using a wrapper function
andrewonlabc2d05aa2014-10-13 16:51:10 -04002991
kelvin-onlabd3b64892015-01-20 13:26:24 -08002992 def getAllIntentsId( self ):
kelvin8ec71442015-01-15 16:57:00 -08002993 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002994 Description:
2995 Obtain all intent id's in a list
kelvin8ec71442015-01-15 16:57:00 -08002996 """
andrewonlab9a50dfe2014-10-17 17:22:31 -04002997 try:
kelvin8ec71442015-01-15 16:57:00 -08002998 # Obtain output of intents function
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002999 intentsStr = self.intents( jsonFormat=True )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07003000 if intentsStr is None:
3001 raise TypeError
Jon Hall6021e062017-01-30 11:10:06 -08003002 # Convert to a dictionary
3003 intents = json.loads( intentsStr )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003004 intentIdList = []
Jon Hall6021e062017-01-30 11:10:06 -08003005 for intent in intents:
3006 intentIdList.append( intent[ 'id' ] )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003007 return intentIdList
Jon Halld4d4b372015-01-28 16:02:41 -08003008 except TypeError:
3009 main.log.exception( self.name + ": Object not as expected" )
3010 return None
andrewonlab9a50dfe2014-10-17 17:22:31 -04003011 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003012 main.log.error( self.name + ": EOF exception found" )
3013 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003014 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003015 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003016 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003017 main.cleanAndExit()
andrewonlab9a50dfe2014-10-17 17:22:31 -04003018
You Wang3c276252016-09-21 15:21:36 -07003019 def flowAddedCount( self, deviceId, core=False ):
Jon Hall30b82fa2015-03-04 17:15:43 -08003020 """
3021 Determine the number of flow rules for the given device id that are
3022 in the added state
You Wang3c276252016-09-21 15:21:36 -07003023 Params:
3024 core: if True, only return the number of core flows added
Jon Hall30b82fa2015-03-04 17:15:43 -08003025 """
3026 try:
You Wang3c276252016-09-21 15:21:36 -07003027 if core:
3028 cmdStr = "flows any " + str( deviceId ) + " | " +\
3029 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
3030 else:
3031 cmdStr = "flows any " + str( deviceId ) + " | " +\
3032 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003033 handle = self.lineCount( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003034 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003035 assert "Command not found:" not in handle, handle
Jon Hall30b82fa2015-03-04 17:15:43 -08003036 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003037 except AssertionError:
3038 main.log.exception( "" )
3039 return None
Jon Hall30b82fa2015-03-04 17:15:43 -08003040 except pexpect.EOF:
3041 main.log.error( self.name + ": EOF exception found" )
3042 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003043 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003044 except Exception:
Jon Hall30b82fa2015-03-04 17:15:43 -08003045 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003046 main.cleanAndExit()
andrewonlab95ce8322014-10-13 14:12:04 -04003047
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003048 def groupAddedCount( self, deviceId, core=False ):
3049 """
3050 Determine the number of group rules for the given device id that are
3051 in the added state
3052 Params:
3053 core: if True, only return the number of core groups added
3054 """
3055 try:
3056 if core:
3057 cmdStr = "groups any " + str( deviceId ) + " | " +\
3058 "grep 'state=ADDED' | grep org.onosproject.core | wc -l"
3059 else:
3060 cmdStr = "groups any " + str( deviceId ) + " | " +\
3061 "grep 'state=ADDED' | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003062 handle = self.lineCount( cmdStr )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003063 assert handle is not None, "Error in sendline"
3064 assert "Command not found:" not in handle, handle
3065 return handle
3066 except AssertionError:
3067 main.log.exception( "" )
3068 return None
3069 except pexpect.EOF:
3070 main.log.error( self.name + ": EOF exception found" )
3071 main.log.error( self.name + ": " + self.handle.before )
3072 main.cleanAndExit()
3073 except Exception:
3074 main.log.exception( self.name + ": Uncaught exception!" )
3075 main.cleanAndExit()
3076
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003077 def addStaticRoute( self, subnet, intf):
3078 """
3079 Adds a static route to onos.
3080 Params:
3081 subnet: The subnet reaching through this route
3082 intf: The interface this route is reachable through
3083 """
3084 try:
3085 cmdStr = "route-add " + subnet + " " + intf
3086 handle = self.sendline( cmdStr )
3087 assert handle is not None, "Error in sendline"
3088 assert "Command not found:" not in handle, handle
3089 return handle
3090 except AssertionError:
3091 main.log.exception( "" )
3092 return None
3093 except pexpect.EOF:
3094 main.log.error( self.name + ": EOF exception found" )
3095 main.log.error( self.name + ": " + self.handle.before )
3096 main.cleanAndExit()
3097 except Exception:
3098 main.log.exception( self.name + ": Uncaught exception!" )
3099 main.cleanAndExit()
3100
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003101 def checkGroupAddedCount( self, deviceId, expectedGroupCount=0, core=False, comparison=0):
3102 """
3103 Description:
3104 Check whether the number of groups for the given device id that
3105 are in ADDED state is bigger than minGroupCount.
3106 Required:
3107 * deviceId: device id to check the number of added group rules
3108 Optional:
3109 * minGroupCount: the number of groups to compare
3110 * core: if True, only check the number of core groups added
3111 * comparison: if 0, compare with greater than minFlowCount
3112 * if 1, compare with equal to minFlowCount
3113 Return:
3114 Returns the number of groups if it is bigger than minGroupCount,
3115 returns main.FALSE otherwise.
3116 """
3117 count = self.groupAddedCount( deviceId, core )
3118 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003119 main.log.debug( "found {} groups".format( count ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003120 return count if ((count > expectedGroupCount) if (comparison == 0) else (count == expectedGroupCount)) else main.FALSE
3121
You Wangc02f3be2018-05-18 12:14:23 -07003122 def getGroups( self, deviceId, groupType="any" ):
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003123 """
3124 Retrieve groups from a specific device.
You Wangc02f3be2018-05-18 12:14:23 -07003125 deviceId: Id of the device from which we retrieve groups
3126 groupType: Type of group
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003127 """
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003128 try:
You Wangc02f3be2018-05-18 12:14:23 -07003129 groupCmd = "groups -t {0} any {1}".format( groupType, deviceId )
3130 handle = self.sendline( groupCmd )
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003131 assert handle is not None, "Error in sendline"
3132 assert "Command not found:" not in handle, handle
3133 return handle
3134 except AssertionError:
3135 main.log.exception( "" )
3136 return None
3137 except TypeError:
3138 main.log.exception( self.name + ": Object not as expected" )
3139 return None
3140 except pexpect.EOF:
3141 main.log.error( self.name + ": EOF exception found" )
3142 main.log.error( self.name + ": " + self.handle.before )
3143 main.cleanAndExit()
3144 except Exception:
3145 main.log.exception( self.name + ": Uncaught exception!" )
3146 main.cleanAndExit()
3147
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003148 def checkFlowAddedCount( self, deviceId, expectedFlowCount=0, core=False, comparison=0):
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003149 """
3150 Description:
3151 Check whether the number of flow rules for the given device id that
3152 are in ADDED state is bigger than minFlowCount.
3153 Required:
3154 * deviceId: device id to check the number of added flow rules
3155 Optional:
3156 * minFlowCount: the number of flow rules to compare
3157 * core: if True, only check the number of core flows added
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003158 * comparison: if 0, compare with greater than minFlowCount
3159 * if 1, compare with equal to minFlowCount
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003160 Return:
3161 Returns the number of flow rules if it is bigger than minFlowCount,
3162 returns main.FALSE otherwise.
3163 """
3164 count = self.flowAddedCount( deviceId, core )
3165 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003166 main.log.debug( "found {} flows".format( count ) )
Jon Hall39570262020-11-17 12:18:19 -08003167 return count if ((count >= expectedFlowCount) if (comparison == 0) else (count == expectedFlowCount)) else main.FALSE
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003168
kelvin-onlabd3b64892015-01-20 13:26:24 -08003169 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003170 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003171 Use 'devices' function to obtain list of all devices
3172 and parse the result to obtain a list of all device
3173 id's. Returns this list. Returns empty list if no
3174 devices exist
kelvin8ec71442015-01-15 16:57:00 -08003175 List is ordered sequentially
3176
andrewonlab3e15ead2014-10-15 14:21:34 -04003177 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08003178 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04003179 the ids. By obtaining the list of device ids on the fly,
3180 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08003181 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003182 try:
kelvin8ec71442015-01-15 16:57:00 -08003183 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08003184 devicesStr = self.devices( jsonFormat=False )
3185 idList = []
kelvin8ec71442015-01-15 16:57:00 -08003186
kelvin-onlabd3b64892015-01-20 13:26:24 -08003187 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08003188 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003189 return idList
kelvin8ec71442015-01-15 16:57:00 -08003190
3191 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08003192 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08003193 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08003194 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08003195 # Split list further into arguments before and after string
3196 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08003197 # append to idList
3198 for arg in tempList:
3199 idList.append( arg.split( "id=" )[ 1 ] )
3200 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04003201
Jon Halld4d4b372015-01-28 16:02:41 -08003202 except TypeError:
3203 main.log.exception( self.name + ": Object not as expected" )
3204 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04003205 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003206 main.log.error( self.name + ": EOF exception found" )
3207 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003208 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003209 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003210 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003211 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003212
kelvin-onlabd3b64892015-01-20 13:26:24 -08003213 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003214 """
andrewonlab7c211572014-10-15 16:45:20 -04003215 Uses 'nodes' function to obtain list of all nodes
3216 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08003217 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04003218 Returns:
3219 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08003220 """
andrewonlab7c211572014-10-15 16:45:20 -04003221 try:
Jon Hall5aa168b2015-03-23 14:23:09 -07003222 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003223 idList = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003224 # Sample nodesStr output
Jon Hallbd182782016-03-28 16:42:22 -07003225 # id=local, address=127.0.0.1:9876, state=READY *
kelvin-onlabd3b64892015-01-20 13:26:24 -08003226 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08003227 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003228 return idList
Jon Hall5aa168b2015-03-23 14:23:09 -07003229 nodesJson = json.loads( nodesStr )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003230 idList = [ node.get( 'id' ) for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08003231 return idList
Jon Hallc6793552016-01-19 14:18:37 -08003232 except ( TypeError, ValueError ):
3233 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, nodesStr ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003234 return None
andrewonlab7c211572014-10-15 16:45:20 -04003235 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003236 main.log.error( self.name + ": EOF exception found" )
3237 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003238 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003239 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003240 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003241 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003242
kelvin-onlabd3b64892015-01-20 13:26:24 -08003243 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08003244 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003245 Return the first device from the devices api whose 'id' contains 'dpid'
3246 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08003247 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003248 try:
kelvin8ec71442015-01-15 16:57:00 -08003249 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04003250 return None
3251 else:
kelvin8ec71442015-01-15 16:57:00 -08003252 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003253 rawDevices = self.devices()
3254 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08003255 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08003256 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08003257 # print "%s in %s?" % ( dpid, device[ 'id' ] )
3258 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04003259 return device
3260 return None
Jon Hallc6793552016-01-19 14:18:37 -08003261 except ( TypeError, ValueError ):
3262 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawDevices ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003263 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04003264 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003265 main.log.error( self.name + ": EOF exception found" )
3266 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003267 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003268 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003269 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003270 main.cleanAndExit()
Jon Halla91c4dc2014-10-22 12:57:04 -04003271
You Wang24139872016-05-03 11:48:47 -07003272 def getTopology( self, topologyOutput ):
3273 """
3274 Definition:
3275 Loads a json topology output
3276 Return:
3277 topology = current ONOS topology
3278 """
You Wang24139872016-05-03 11:48:47 -07003279 try:
3280 # either onos:topology or 'topology' will work in CLI
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003281 topology = json.loads( topologyOutput )
Jeremy Songsterbc2d8ac2016-05-04 11:25:42 -07003282 main.log.debug( topology )
You Wang24139872016-05-03 11:48:47 -07003283 return topology
You Wangd3cb2ce2016-05-16 14:01:24 -07003284 except ( TypeError, ValueError ):
3285 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, topologyOutput ) )
3286 return None
You Wang24139872016-05-03 11:48:47 -07003287 except pexpect.EOF:
3288 main.log.error( self.name + ": EOF exception found" )
3289 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003290 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003291 except Exception:
3292 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003293 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003294
Jon Hall39570262020-11-17 12:18:19 -08003295 def checkStatus( self, numoswitch, numolink = -1, numoctrl = -1, numoSCCs=1, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08003296 """
Jon Hallefbd9792015-03-05 16:11:36 -08003297 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08003298 supplied values. By default this will report to main.log, but the
You Wang24139872016-05-03 11:48:47 -07003299 log level can be specific.
kelvin8ec71442015-01-15 16:57:00 -08003300
Flavio Castro82ee2f62016-06-07 15:04:12 -07003301 Params: numoswitch = expected number of switches
Jon Hallefbd9792015-03-05 16:11:36 -08003302 numolink = expected number of links
Flavio Castro82ee2f62016-06-07 15:04:12 -07003303 numoctrl = expected number of controllers
Jon Hall39570262020-11-17 12:18:19 -08003304 numoSCCs = Number of expected SCCs
You Wang24139872016-05-03 11:48:47 -07003305 logLevel = level to log to.
3306 Currently accepts 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04003307
Jon Hallefbd9792015-03-05 16:11:36 -08003308 Returns: main.TRUE if the number of switches and links are correct,
3309 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04003310 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08003311 """
Jon Hall42db6dc2014-10-24 19:03:48 -04003312 try:
You Wang13310252016-07-31 10:56:14 -07003313 summary = self.summary()
3314 summary = json.loads( summary )
Flavio Castrof5b3f872016-06-23 17:52:31 -07003315 except ( TypeError, ValueError ):
3316 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summary ) )
3317 return main.ERROR
3318 try:
3319 topology = self.getTopology( self.topology() )
Jon Halle0f0b342017-04-18 11:43:47 -07003320 if topology == {} or topology is None or summary == {} or summary is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04003321 return main.ERROR
3322 output = ""
kelvin8ec71442015-01-15 16:57:00 -08003323 # Is the number of switches is what we expected
3324 devices = topology.get( 'devices', False )
3325 links = topology.get( 'links', False )
Flavio Castro82ee2f62016-06-07 15:04:12 -07003326 nodes = summary.get( 'nodes', False )
Jon Hall39570262020-11-17 12:18:19 -08003327 SCCs = summary.get( 'SCC(s)', False )
3328 if devices is False or links is False or nodes is False or SCCs is False:
3329 main.log.warn( "Issues parsing topology and summary output" )
3330 main.log.debug( topology )
3331 main.log.debug( summary )
Jon Hall42db6dc2014-10-24 19:03:48 -04003332 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08003333 switchCheck = ( int( devices ) == int( numoswitch ) )
Jon Hall39570262020-11-17 12:18:19 -08003334 if not switchCheck:
3335 main.log.debug( "switch Check Failed" )
Pier6a0c4de2018-03-18 16:01:30 -07003336 linkCheck = ( int( links ) == int( numolink ) ) or int( numolink ) == -1
Jon Hall39570262020-11-17 12:18:19 -08003337 if not linkCheck:
3338 main.log.debug( "link Check Failed" )
Flavio Castro82ee2f62016-06-07 15:04:12 -07003339 nodeCheck = ( int( nodes ) == int( numoctrl ) ) or int( numoctrl ) == -1
Jon Hall39570262020-11-17 12:18:19 -08003340 if not nodeCheck:
3341 main.log.debug( "node Check Failed" )
3342 SCCsCheck = ( int( SCCs ) == int( numoSCCs ) ) or int( numoSCCs ) == -1
3343 if not SCCsCheck:
3344 main.log.debug( "SCCs Check Failed" )
3345 if switchCheck and linkCheck and nodeCheck and SCCsCheck:
kelvin8ec71442015-01-15 16:57:00 -08003346 # We expected the correct numbers
Jon Hall39570262020-11-17 12:18:19 -08003347 output = output + "The number of links, switches, nodes, and SCCs match "\
You Wang24139872016-05-03 11:48:47 -07003348 + "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003349 result = main.TRUE
3350 else:
You Wang24139872016-05-03 11:48:47 -07003351 output = output + \
Jon Hall627b1572020-12-01 12:01:15 -08003352 "The number of links, switches, nodes, and SCCs does not match " + \
You Wang24139872016-05-03 11:48:47 -07003353 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003354 result = main.FALSE
Jon Hall39570262020-11-17 12:18:19 -08003355 output = output + "\n ONOS sees %i devices " % int( devices )
3356 output = output + "(%i expected) " % int( numoswitch )
3357 if int( numolink ) >= 0:
Pier6a0c4de2018-03-18 16:01:30 -07003358 output = output + "and %i links " % int( links )
Jon Hall39570262020-11-17 12:18:19 -08003359 output = output + "(%i expected) " % int( numolink )
3360 if int( numoctrl ) >= 0:
Flavio Castro82ee2f62016-06-07 15:04:12 -07003361 output = output + "and %i controllers " % int( nodes )
Jon Hall39570262020-11-17 12:18:19 -08003362 output = output + "(%i expected) " % int( numoctrl )
3363 if int( numoSCCs ) >= 0:
3364 output = output + "and %i SCCs " % int( SCCs )
3365 output = output + "(%i expected)" % int( numoSCCs )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003366 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08003367 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003368 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08003369 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04003370 else:
You Wang24139872016-05-03 11:48:47 -07003371 main.log.info( output )
Jon Hall39570262020-11-17 12:18:19 -08003372 main.TOPOOUTPUT = output
kelvin8ec71442015-01-15 16:57:00 -08003373 return result
Jon Hall42db6dc2014-10-24 19:03:48 -04003374 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003375 main.log.error( self.name + ": EOF exception found" )
3376 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003377 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003378 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003379 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003380 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003381
kelvin-onlabd3b64892015-01-20 13:26:24 -08003382 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08003383 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003384 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08003385 deviceId must be the id of a device as seen in the onos devices command
3386 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04003387 role must be either master, standby, or none
3388
Jon Halle3f39ff2015-01-13 11:50:53 -08003389 Returns:
3390 main.TRUE or main.FALSE based on argument verification and
3391 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003392 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003393 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003394 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04003395 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08003396 cmdStr = "device-role " +\
3397 str( deviceId ) + " " +\
3398 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003399 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003400 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003401 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003402 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08003403 if re.search( "Error", handle ):
3404 # end color output to escape any colours
3405 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08003406 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003407 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08003408 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08003409 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04003410 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003411 main.log.error( "Invalid 'role' given to device_role(). " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003412 "Value was '" + str( role ) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04003413 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003414 except AssertionError:
3415 main.log.exception( "" )
3416 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003417 except TypeError:
3418 main.log.exception( self.name + ": Object not as expected" )
3419 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04003420 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003421 main.log.error( self.name + ": EOF exception found" )
3422 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003423 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003424 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003425 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003426 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003427
kelvin-onlabd3b64892015-01-20 13:26:24 -08003428 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08003429 """
Jon Hall0dd09952018-04-19 09:59:11 -07003430 Lists all topology clusters
Jon Hallffb386d2014-11-21 13:43:38 -08003431 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003432 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08003433 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08003434 try:
Jon Hall0dd09952018-04-19 09:59:11 -07003435 cmdStr = "topo-clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003436 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003437 cmdStr += " -j"
3438 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003439 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003440 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07003441 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003442 except AssertionError:
3443 main.log.exception( "" )
3444 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003445 except TypeError:
3446 main.log.exception( self.name + ": Object not as expected" )
3447 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08003448 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003449 main.log.error( self.name + ": EOF exception found" )
3450 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003451 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003452 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003453 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003454 main.cleanAndExit()
Jon Hall73cf9cc2014-11-20 22:28:38 -08003455
kelvin-onlabd3b64892015-01-20 13:26:24 -08003456 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003457 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003458 CLI command to get the current leader for the Election test application
3459 NOTE: Requires installation of the onos-app-election feature
3460 Returns: Node IP of the leader if one exists
3461 None if none exists
3462 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003463 """
Jon Hall94fd0472014-12-08 11:52:42 -08003464 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003465 cmdStr = "election-test-leader"
3466 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003467 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003468 assert "Command not found:" not in response, response
Jon Halle3f39ff2015-01-13 11:50:53 -08003469 # Leader
3470 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003471 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08003472 nodeSearch = re.search( leaderPattern, response )
3473 if nodeSearch:
3474 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08003475 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003476 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08003477 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08003478 # no leader
3479 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003480 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003481 nullSearch = re.search( nullPattern, response )
3482 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08003483 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003484 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08003485 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08003486 # error
Jon Hall0e240372018-05-02 11:21:57 -07003487 main.log.error( self.name + ": Error in electionTestLeader on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003488 ": " + "unexpected response" )
3489 main.log.error( repr( response ) )
3490 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003491 except AssertionError:
3492 main.log.exception( "" )
3493 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003494 except TypeError:
3495 main.log.exception( self.name + ": Object not as expected" )
3496 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003497 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003498 main.log.error( self.name + ": EOF exception found" )
3499 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003500 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003501 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003502 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003503 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003504
kelvin-onlabd3b64892015-01-20 13:26:24 -08003505 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003506 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003507 CLI command to run for leadership of the Election test application.
3508 NOTE: Requires installation of the onos-app-election feature
3509 Returns: Main.TRUE on success
3510 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003511 """
Jon Hall94fd0472014-12-08 11:52:42 -08003512 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003513 cmdStr = "election-test-run"
3514 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003515 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003516 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003517 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003518 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003519 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003520 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08003521 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08003522 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003523 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003524 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003525 # error
Jon Hall0e240372018-05-02 11:21:57 -07003526 main.log.error( self.name + ": Error in electionTestRun on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003527 ": " + "unexpected response" )
3528 main.log.error( repr( response ) )
3529 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003530 except AssertionError:
3531 main.log.exception( "" )
3532 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003533 except TypeError:
3534 main.log.exception( self.name + ": Object not as expected" )
3535 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003536 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003537 main.log.error( self.name + ": EOF exception found" )
3538 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003539 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003540 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003541 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003542 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003543
kelvin-onlabd3b64892015-01-20 13:26:24 -08003544 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08003545 """
Jon Hall94fd0472014-12-08 11:52:42 -08003546 * CLI command to withdraw the local node from leadership election for
3547 * the Election test application.
3548 #NOTE: Requires installation of the onos-app-election feature
3549 Returns: Main.TRUE on success
3550 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08003551 """
Jon Hall94fd0472014-12-08 11:52:42 -08003552 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003553 cmdStr = "election-test-withdraw"
3554 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003555 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003556 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003557 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003558 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003559 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003560 if re.search( successPattern, response ):
3561 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003562 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003563 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003564 # error
Jon Hall0e240372018-05-02 11:21:57 -07003565 main.log.error( self.name + ": Error in electionTestWithdraw on " +
Jon Hall97cf84a2016-06-20 13:35:58 -07003566 self.name + ": " + "unexpected response" )
3567 main.log.error( repr( response ) )
3568 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003569 except AssertionError:
3570 main.log.exception( "" )
3571 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003572 except TypeError:
3573 main.log.exception( self.name + ": Object not as expected" )
3574 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003575 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003576 main.log.error( self.name + ": EOF exception found" )
3577 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003578 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003579 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003580 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003581 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003582
kelvin8ec71442015-01-15 16:57:00 -08003583 def getDevicePortsEnabledCount( self, dpid ):
3584 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003585 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003586 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003587 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003588 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003589 cmdStr = "onos:ports -e " + dpid + " | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003590 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003591 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003592 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003593 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003594 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003595 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003596 return output
Jon Hallc6793552016-01-19 14:18:37 -08003597 except AssertionError:
3598 main.log.exception( "" )
3599 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003600 except TypeError:
3601 main.log.exception( self.name + ": Object not as expected" )
3602 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003603 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003604 main.log.error( self.name + ": EOF exception found" )
3605 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003606 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003607 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003608 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003609 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003610
kelvin8ec71442015-01-15 16:57:00 -08003611 def getDeviceLinksActiveCount( self, dpid ):
3612 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003613 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003614 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003615 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003616 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003617 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003618 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003619 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003620 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003621 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003622 main.log.error( self.name + ": Error in getting ports " )
kelvin-onlab898a6c62015-01-16 14:13:53 -08003623 return ( output, "Error " )
Jon Halla495f562016-05-16 18:03:26 -07003624 return output
Jon Hallc6793552016-01-19 14:18:37 -08003625 except AssertionError:
3626 main.log.exception( "" )
3627 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003628 except TypeError:
3629 main.log.exception( self.name + ": Object not as expected" )
3630 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003631 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003632 main.log.error( self.name + ": EOF exception found" )
3633 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003634 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003635 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003636 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003637 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003638
kelvin8ec71442015-01-15 16:57:00 -08003639 def getAllIntentIds( self ):
3640 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003641 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08003642 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003643 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003644 cmdStr = "onos:intents | grep id="
3645 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003646 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003647 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003648 if re.search( "Error", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003649 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003650 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003651 return output
Jon Hallc6793552016-01-19 14:18:37 -08003652 except AssertionError:
3653 main.log.exception( "" )
3654 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003655 except TypeError:
3656 main.log.exception( self.name + ": Object not as expected" )
3657 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003658 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003659 main.log.error( self.name + ": EOF exception found" )
3660 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003661 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003662 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003663 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003664 main.cleanAndExit()
Jon Halld4d4b372015-01-28 16:02:41 -08003665
Jon Hall73509952015-02-24 16:42:56 -08003666 def intentSummary( self ):
3667 """
Jon Hallefbd9792015-03-05 16:11:36 -08003668 Returns a dictionary containing the current intent states and the count
Jon Hall73509952015-02-24 16:42:56 -08003669 """
3670 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003671 intents = self.intents( )
Jon Hall08f61bc2015-04-13 16:00:30 -07003672 states = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003673 for intent in json.loads( intents ):
Jon Hall08f61bc2015-04-13 16:00:30 -07003674 states.append( intent.get( 'state', None ) )
3675 out = [ ( i, states.count( i ) ) for i in set( states ) ]
Jon Hall63604932015-02-26 17:09:50 -08003676 main.log.info( dict( out ) )
Jon Hall73509952015-02-24 16:42:56 -08003677 return dict( out )
Jon Hallc6793552016-01-19 14:18:37 -08003678 except ( TypeError, ValueError ):
3679 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intents ) )
Jon Hall73509952015-02-24 16:42:56 -08003680 return None
3681 except pexpect.EOF:
3682 main.log.error( self.name + ": EOF exception found" )
3683 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003684 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003685 except Exception:
Jon Hall73509952015-02-24 16:42:56 -08003686 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003687 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003688
Jon Hall61282e32015-03-19 11:34:11 -07003689 def leaders( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003690 """
3691 Returns the output of the leaders command.
Jon Hall61282e32015-03-19 11:34:11 -07003692 Optional argument:
3693 * jsonFormat - boolean indicating if you want output in json
Jon Hall63604932015-02-26 17:09:50 -08003694 """
Jon Hall63604932015-02-26 17:09:50 -08003695 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003696 cmdStr = "onos:leaders"
Jon Hall61282e32015-03-19 11:34:11 -07003697 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003698 cmdStr += " -j"
3699 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003700 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003701 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003702 return output
Jon Hallc6793552016-01-19 14:18:37 -08003703 except AssertionError:
3704 main.log.exception( "" )
3705 return None
Jon Hall63604932015-02-26 17:09:50 -08003706 except TypeError:
3707 main.log.exception( self.name + ": Object not as expected" )
3708 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003709 except pexpect.EOF:
3710 main.log.error( self.name + ": EOF exception found" )
3711 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003712 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003713 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003714 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003715 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003716
acsmarsa4a4d1e2015-07-10 16:01:24 -07003717 def leaderCandidates( self, jsonFormat=True ):
3718 """
3719 Returns the output of the leaders -c command.
3720 Optional argument:
3721 * jsonFormat - boolean indicating if you want output in json
3722 """
3723 try:
3724 cmdStr = "onos:leaders -c"
3725 if jsonFormat:
3726 cmdStr += " -j"
3727 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003728 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003729 assert "Command not found:" not in output, output
acsmarsa4a4d1e2015-07-10 16:01:24 -07003730 return output
Jon Hallc6793552016-01-19 14:18:37 -08003731 except AssertionError:
3732 main.log.exception( "" )
3733 return None
acsmarsa4a4d1e2015-07-10 16:01:24 -07003734 except TypeError:
3735 main.log.exception( self.name + ": Object not as expected" )
3736 return None
3737 except pexpect.EOF:
3738 main.log.error( self.name + ": EOF exception found" )
3739 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003740 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003741 except Exception:
3742 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003743 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003744
Jon Hallc6793552016-01-19 14:18:37 -08003745 def specificLeaderCandidate( self, topic ):
acsmarsa4a4d1e2015-07-10 16:01:24 -07003746 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003747 Returns a list in format [leader,candidate1,candidate2,...] for a given
acsmarsa4a4d1e2015-07-10 16:01:24 -07003748 topic parameter and an empty list if the topic doesn't exist
3749 If no leader is elected leader in the returned list will be "none"
3750 Returns None if there is a type error processing the json object
3751 """
3752 try:
Jon Hall6e709752016-02-01 13:38:46 -08003753 cmdStr = "onos:leaders -j"
Jon Hallc6793552016-01-19 14:18:37 -08003754 rawOutput = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003755 assert rawOutput is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003756 assert "Command not found:" not in rawOutput, rawOutput
3757 output = json.loads( rawOutput )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003758 results = []
3759 for dict in output:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003760 if dict[ "topic" ] == topic:
3761 leader = dict[ "leader" ]
3762 candidates = re.split( ", ", dict[ "candidates" ][ 1:-1 ] )
Jon Hallc6793552016-01-19 14:18:37 -08003763 results.append( leader )
3764 results.extend( candidates )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003765 return results
Jon Hallc6793552016-01-19 14:18:37 -08003766 except AssertionError:
3767 main.log.exception( "" )
3768 return None
3769 except ( TypeError, ValueError ):
3770 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawOutput ) )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003771 return None
3772 except pexpect.EOF:
3773 main.log.error( self.name + ": EOF exception found" )
3774 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003775 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003776 except Exception:
3777 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003778 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003779
Jon Hall61282e32015-03-19 11:34:11 -07003780 def pendingMap( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003781 """
3782 Returns the output of the intent Pending map.
3783 """
Jon Hall63604932015-02-26 17:09:50 -08003784 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003785 cmdStr = "onos:intents -p"
Jon Hall61282e32015-03-19 11:34:11 -07003786 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003787 cmdStr += " -j"
3788 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003789 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003790 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003791 return output
Jon Hallc6793552016-01-19 14:18:37 -08003792 except AssertionError:
3793 main.log.exception( "" )
3794 return None
Jon Hall63604932015-02-26 17:09:50 -08003795 except TypeError:
3796 main.log.exception( self.name + ": Object not as expected" )
3797 return None
3798 except pexpect.EOF:
3799 main.log.error( self.name + ": EOF exception found" )
3800 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003801 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003802 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003803 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003804 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003805
Jon Hall2c8959e2016-12-16 12:17:34 -08003806 def partitions( self, candidates=False, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003807 """
3808 Returns the output of the raft partitions command for ONOS.
3809 """
Jon Hall61282e32015-03-19 11:34:11 -07003810 # Sample JSON
3811 # {
3812 # "leader": "tcp://10.128.30.11:7238",
3813 # "members": [
3814 # "tcp://10.128.30.11:7238",
3815 # "tcp://10.128.30.17:7238",
3816 # "tcp://10.128.30.13:7238",
3817 # ],
3818 # "name": "p1",
3819 # "term": 3
3820 # },
Jon Hall63604932015-02-26 17:09:50 -08003821 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003822 cmdStr = "onos:partitions"
Jon Hall2c8959e2016-12-16 12:17:34 -08003823 if candidates:
3824 cmdStr += " -c"
Jon Hall61282e32015-03-19 11:34:11 -07003825 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003826 cmdStr += " -j"
3827 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003828 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003829 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003830 return output
Jon Hallc6793552016-01-19 14:18:37 -08003831 except AssertionError:
3832 main.log.exception( "" )
3833 return None
Jon Hall63604932015-02-26 17:09:50 -08003834 except TypeError:
3835 main.log.exception( self.name + ": Object not as expected" )
3836 return None
3837 except pexpect.EOF:
3838 main.log.error( self.name + ": EOF exception found" )
3839 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003840 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003841 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003842 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003843 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003844
Jon Halle9f909e2016-09-23 10:43:12 -07003845 def apps( self, summary=False, active=False, jsonFormat=True ):
Jon Hallbe379602015-03-24 13:39:32 -07003846 """
3847 Returns the output of the apps command for ONOS. This command lists
3848 information about installed ONOS applications
3849 """
3850 # Sample JSON object
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003851 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
Jon Hallbe379602015-03-24 13:39:32 -07003852 # "description":"ONOS OpenFlow protocol southbound providers",
3853 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003854 # "features":"[onos-openflow]","state":"ACTIVE"}]
Jon Hallbe379602015-03-24 13:39:32 -07003855 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003856 cmdStr = "onos:apps"
Jon Hallf03ae762019-01-22 13:25:27 -08003857 expectJson = False
Jon Halle9f909e2016-09-23 10:43:12 -07003858 if summary:
3859 cmdStr += " -s"
3860 if active:
3861 cmdStr += " -a"
Jon Hallbe379602015-03-24 13:39:32 -07003862 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003863 cmdStr += " -j"
Jon Hallf03ae762019-01-22 13:25:27 -08003864 expectJson = True
3865 output = self.sendline( cmdStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07003866 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003867 assert "Command not found:" not in output, output
3868 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003869 return output
Jon Hallbe379602015-03-24 13:39:32 -07003870 # FIXME: look at specific exceptions/Errors
3871 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07003872 main.log.exception( self.name + ": Error in processing onos:app command." )
Jon Hallbe379602015-03-24 13:39:32 -07003873 return None
3874 except TypeError:
3875 main.log.exception( self.name + ": Object not as expected" )
3876 return None
3877 except pexpect.EOF:
3878 main.log.error( self.name + ": EOF exception found" )
3879 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003880 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003881 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003882 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003883 main.cleanAndExit()
Jon Hallbe379602015-03-24 13:39:32 -07003884
You Wangcdc51fe2018-08-12 17:14:56 -07003885 def appStatus( self, appName ):
Jon Hall146f1522015-03-24 15:33:24 -07003886 """
3887 Uses the onos:apps cli command to return the status of an application.
3888 Returns:
3889 "ACTIVE" - If app is installed and activated
3890 "INSTALLED" - If app is installed and deactivated
3891 "UNINSTALLED" - If app is not installed
3892 None - on error
3893 """
Jon Hall146f1522015-03-24 15:33:24 -07003894 try:
3895 if not isinstance( appName, types.StringType ):
3896 main.log.error( self.name + ".appStatus(): appName must be" +
3897 " a string" )
3898 return None
3899 output = self.apps( jsonFormat=True )
3900 appsJson = json.loads( output )
3901 state = None
3902 for app in appsJson:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003903 if appName == app.get( 'name' ):
3904 state = app.get( 'state' )
Jon Hall146f1522015-03-24 15:33:24 -07003905 break
3906 if state == "ACTIVE" or state == "INSTALLED":
3907 return state
3908 elif state is None:
You Wang0d9f2c02018-08-10 14:56:32 -07003909 main.log.warn( "{} app not found".format( appName ) )
Jon Hall146f1522015-03-24 15:33:24 -07003910 return "UNINSTALLED"
3911 elif state:
3912 main.log.error( "Unexpected state from 'onos:apps': " +
3913 str( state ) )
3914 return state
Jon Hallc6793552016-01-19 14:18:37 -08003915 except ( TypeError, ValueError ):
3916 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003917 return None
3918 except pexpect.EOF:
3919 main.log.error( self.name + ": EOF exception found" )
3920 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003921 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003922 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003923 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003924 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003925
Jon Hallbe379602015-03-24 13:39:32 -07003926 def app( self, appName, option ):
3927 """
3928 Interacts with the app command for ONOS. This command manages
3929 application inventory.
3930 """
Jon Hallbe379602015-03-24 13:39:32 -07003931 try:
Jon Hallbd16b922015-03-26 17:53:15 -07003932 # Validate argument types
3933 valid = True
3934 if not isinstance( appName, types.StringType ):
3935 main.log.error( self.name + ".app(): appName must be a " +
3936 "string" )
3937 valid = False
3938 if not isinstance( option, types.StringType ):
3939 main.log.error( self.name + ".app(): option must be a string" )
3940 valid = False
3941 if not valid:
3942 return main.FALSE
3943 # Validate Option
3944 option = option.lower()
3945 # NOTE: Install may become a valid option
3946 if option == "activate":
3947 pass
3948 elif option == "deactivate":
3949 pass
3950 elif option == "uninstall":
3951 pass
3952 else:
3953 # Invalid option
3954 main.log.error( "The ONOS app command argument only takes " +
3955 "the values: (activate|deactivate|uninstall)" +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003956 "; was given '" + option + "'" )
Jon Hallbd16b922015-03-26 17:53:15 -07003957 return main.FALSE
Jon Hall146f1522015-03-24 15:33:24 -07003958 cmdStr = "onos:app " + option + " " + appName
Jon Hallbe379602015-03-24 13:39:32 -07003959 output = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003960 assert output is not None, "Error in sendline"
3961 assert "Command not found:" not in output, output
Jon Hallbe379602015-03-24 13:39:32 -07003962 if "Error executing command" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003963 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hallbe379602015-03-24 13:39:32 -07003964 str( output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003965 return main.FALSE
Jon Hallbe379602015-03-24 13:39:32 -07003966 elif "No such application" in output:
3967 main.log.error( "The application '" + appName +
3968 "' is not installed in ONOS" )
Jon Hall146f1522015-03-24 15:33:24 -07003969 return main.FALSE
3970 elif "Command not found:" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003971 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hall146f1522015-03-24 15:33:24 -07003972 str( output ) )
3973 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003974 elif "Unsupported command:" in output:
3975 main.log.error( "Incorrect command given to 'app': " +
3976 str( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003977 # NOTE: we may need to add more checks here
Jon Hallbd16b922015-03-26 17:53:15 -07003978 # else: Command was successful
Jon Hall08f61bc2015-04-13 16:00:30 -07003979 # main.log.debug( "app response: " + repr( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07003980 return main.TRUE
You Wangb5a55f72017-03-03 12:51:05 -08003981 except AssertionError:
3982 main.log.exception( self.name + ": AssertionError exception found" )
3983 return main.ERROR
Jon Hallbe379602015-03-24 13:39:32 -07003984 except TypeError:
3985 main.log.exception( self.name + ": Object not as expected" )
3986 return main.ERROR
3987 except pexpect.EOF:
3988 main.log.error( self.name + ": EOF exception found" )
3989 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003990 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003991 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003992 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003993 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003994
Jon Hallbd16b922015-03-26 17:53:15 -07003995 def activateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07003996 """
3997 Activate an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07003998 appName is the hierarchical app name, not the feature name
3999 If check is True, method will check the status of the app after the
4000 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004001 Returns main.TRUE if the command was successfully sent
4002 main.FALSE if the cli responded with an error or given
4003 incorrect input
4004 """
4005 try:
4006 if not isinstance( appName, types.StringType ):
4007 main.log.error( self.name + ".activateApp(): appName must be" +
4008 " a string" )
4009 return main.FALSE
4010 status = self.appStatus( appName )
4011 if status == "INSTALLED":
4012 response = self.app( appName, "activate" )
Jon Hallbd16b922015-03-26 17:53:15 -07004013 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004014 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004015 status = self.appStatus( appName )
4016 if status == "ACTIVE":
4017 return main.TRUE
4018 else:
Jon Hall050e1bd2015-03-30 13:33:02 -07004019 main.log.debug( "The state of application " +
4020 appName + " is " + status )
Jon Hallbd16b922015-03-26 17:53:15 -07004021 time.sleep( 1 )
4022 return main.FALSE
4023 else: # not 'check' or command didn't succeed
4024 return response
Jon Hall146f1522015-03-24 15:33:24 -07004025 elif status == "ACTIVE":
4026 return main.TRUE
4027 elif status == "UNINSTALLED":
4028 main.log.error( self.name + ": Tried to activate the " +
4029 "application '" + appName + "' which is not " +
4030 "installed." )
4031 else:
4032 main.log.error( "Unexpected return value from appStatus: " +
4033 str( status ) )
4034 return main.ERROR
4035 except TypeError:
4036 main.log.exception( self.name + ": Object not as expected" )
4037 return main.ERROR
4038 except pexpect.EOF:
4039 main.log.error( self.name + ": EOF exception found" )
4040 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004041 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004042 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004043 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004044 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004045
Jon Hallbd16b922015-03-26 17:53:15 -07004046 def deactivateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004047 """
4048 Deactivate an app that is already activated in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004049 appName is the hierarchical app name, not the feature name
4050 If check is True, method will check the status of the app after the
4051 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004052 Returns main.TRUE if the command was successfully sent
4053 main.FALSE if the cli responded with an error or given
4054 incorrect input
4055 """
4056 try:
4057 if not isinstance( appName, types.StringType ):
4058 main.log.error( self.name + ".deactivateApp(): appName must " +
4059 "be a string" )
4060 return main.FALSE
4061 status = self.appStatus( appName )
4062 if status == "INSTALLED":
4063 return main.TRUE
4064 elif status == "ACTIVE":
4065 response = self.app( appName, "deactivate" )
Jon Hallbd16b922015-03-26 17:53:15 -07004066 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004067 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004068 status = self.appStatus( appName )
4069 if status == "INSTALLED":
4070 return main.TRUE
4071 else:
4072 time.sleep( 1 )
4073 return main.FALSE
4074 else: # not check or command didn't succeed
4075 return response
Jon Hall146f1522015-03-24 15:33:24 -07004076 elif status == "UNINSTALLED":
4077 main.log.warn( self.name + ": Tried to deactivate the " +
4078 "application '" + appName + "' which is not " +
4079 "installed." )
4080 return main.TRUE
4081 else:
4082 main.log.error( "Unexpected return value from appStatus: " +
4083 str( status ) )
4084 return main.ERROR
4085 except TypeError:
4086 main.log.exception( self.name + ": Object not as expected" )
4087 return main.ERROR
4088 except pexpect.EOF:
4089 main.log.error( self.name + ": EOF exception found" )
4090 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004091 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004092 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004093 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004094 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004095
Jon Hallbd16b922015-03-26 17:53:15 -07004096 def uninstallApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004097 """
4098 Uninstall an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004099 appName is the hierarchical app name, not the feature name
4100 If check is True, method will check the status of the app after the
4101 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004102 Returns main.TRUE if the command was successfully sent
4103 main.FALSE if the cli responded with an error or given
4104 incorrect input
4105 """
4106 # TODO: check with Thomas about the state machine for apps
4107 try:
4108 if not isinstance( appName, types.StringType ):
4109 main.log.error( self.name + ".uninstallApp(): appName must " +
4110 "be a string" )
4111 return main.FALSE
4112 status = self.appStatus( appName )
4113 if status == "INSTALLED":
4114 response = self.app( appName, "uninstall" )
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 == "UNINSTALLED":
4119 return main.TRUE
4120 else:
4121 time.sleep( 1 )
4122 return main.FALSE
4123 else: # not check or command didn't succeed
4124 return response
Jon Hall146f1522015-03-24 15:33:24 -07004125 elif status == "ACTIVE":
4126 main.log.warn( self.name + ": Tried to uninstall the " +
4127 "application '" + appName + "' which is " +
4128 "currently active." )
4129 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004130 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004131 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004132 status = self.appStatus( appName )
4133 if status == "UNINSTALLED":
4134 return main.TRUE
4135 else:
4136 time.sleep( 1 )
4137 return main.FALSE
4138 else: # not check or command didn't succeed
4139 return response
Jon Hall146f1522015-03-24 15:33:24 -07004140 elif status == "UNINSTALLED":
4141 return main.TRUE
4142 else:
4143 main.log.error( "Unexpected return value from appStatus: " +
4144 str( status ) )
4145 return main.ERROR
4146 except TypeError:
4147 main.log.exception( self.name + ": Object not as expected" )
4148 return main.ERROR
4149 except pexpect.EOF:
4150 main.log.error( self.name + ": EOF exception found" )
4151 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004152 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004153 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004154 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004155 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004156
4157 def appIDs( self, jsonFormat=True ):
4158 """
4159 Show the mappings between app id and app names given by the 'app-ids'
4160 cli command
4161 """
4162 try:
4163 cmdStr = "app-ids"
4164 if jsonFormat:
4165 cmdStr += " -j"
Jon Hallc6358dd2015-04-10 12:44:28 -07004166 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004167 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004168 assert "Command not found:" not in output, output
4169 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07004170 return output
Jon Hallbd16b922015-03-26 17:53:15 -07004171 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004172 main.log.exception( self.name + ": Error in processing onos:app-ids command." )
Jon Hallbd16b922015-03-26 17:53:15 -07004173 return None
4174 except TypeError:
4175 main.log.exception( self.name + ": Object not as expected" )
4176 return None
4177 except pexpect.EOF:
4178 main.log.error( self.name + ": EOF exception found" )
4179 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004180 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004181 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004182 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004183 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004184
4185 def appToIDCheck( self ):
4186 """
4187 This method will check that each application's ID listed in 'apps' is
4188 the same as the ID listed in 'app-ids'. The check will also check that
4189 there are no duplicate IDs issued. Note that an app ID should be
4190 a globaly unique numerical identifier for app/app-like features. Once
4191 an ID is registered, the ID is never freed up so that if an app is
4192 reinstalled it will have the same ID.
4193
4194 Returns: main.TRUE if the check passes and
4195 main.FALSE if the check fails or
4196 main.ERROR if there is some error in processing the test
4197 """
4198 try:
Jon Hall0e240372018-05-02 11:21:57 -07004199 # Grab IDs
Jon Hallc6793552016-01-19 14:18:37 -08004200 rawJson = self.appIDs( jsonFormat=True )
4201 if rawJson:
4202 ids = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004203 else:
Jon Hall0e240372018-05-02 11:21:57 -07004204 main.log.error( "app-ids returned nothing: " + repr( rawJson ) )
4205 return main.FALSE
4206
4207 # Grab Apps
Jon Hallc6793552016-01-19 14:18:37 -08004208 rawJson = self.apps( jsonFormat=True )
4209 if rawJson:
4210 apps = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004211 else:
Jon Hallc6793552016-01-19 14:18:37 -08004212 main.log.error( "apps returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07004213 return main.FALSE
Jon Hall0e240372018-05-02 11:21:57 -07004214
Jon Hallbd16b922015-03-26 17:53:15 -07004215 result = main.TRUE
4216 for app in apps:
4217 appID = app.get( 'id' )
4218 if appID is None:
4219 main.log.error( "Error parsing app: " + str( app ) )
4220 result = main.FALSE
4221 appName = app.get( 'name' )
4222 if appName is None:
4223 main.log.error( "Error parsing app: " + str( app ) )
4224 result = main.FALSE
4225 # get the entry in ids that has the same appID
Jon Hall390696c2015-05-05 17:13:41 -07004226 current = filter( lambda item: item[ 'id' ] == appID, ids )
Jon Hallbd16b922015-03-26 17:53:15 -07004227 if not current: # if ids doesn't have this id
4228 result = main.FALSE
4229 main.log.error( "'app-ids' does not have the ID for " +
4230 str( appName ) + " that apps does." )
Jon Hallb9d381e2018-02-05 12:02:10 -08004231 main.log.debug( "apps command returned: " + str( app ) +
4232 "; app-ids has: " + str( ids ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004233 elif len( current ) > 1:
4234 # there is more than one app with this ID
4235 result = main.FALSE
4236 # We will log this later in the method
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004237 elif not current[ 0 ][ 'name' ] == appName:
4238 currentName = current[ 0 ][ 'name' ]
Jon Hallbd16b922015-03-26 17:53:15 -07004239 result = main.FALSE
4240 main.log.error( "'app-ids' has " + str( currentName ) +
4241 " registered under id:" + str( appID ) +
4242 " but 'apps' has " + str( appName ) )
4243 else:
4244 pass # id and name match!
Jon Hall0e240372018-05-02 11:21:57 -07004245
Jon Hallbd16b922015-03-26 17:53:15 -07004246 # now make sure that app-ids has no duplicates
4247 idsList = []
4248 namesList = []
4249 for item in ids:
4250 idsList.append( item[ 'id' ] )
4251 namesList.append( item[ 'name' ] )
4252 if len( idsList ) != len( set( idsList ) ) or\
4253 len( namesList ) != len( set( namesList ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004254 main.log.error( "'app-ids' has some duplicate entries: \n"
4255 + json.dumps( ids,
4256 sort_keys=True,
4257 indent=4,
4258 separators=( ',', ': ' ) ) )
4259 result = main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07004260 return result
Jon Hallc6793552016-01-19 14:18:37 -08004261 except ( TypeError, ValueError ):
4262 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004263 return main.ERROR
4264 except pexpect.EOF:
4265 main.log.error( self.name + ": EOF exception found" )
4266 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004267 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004268 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004269 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004270 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004271
Jon Hallfb760a02015-04-13 15:35:03 -07004272 def getCfg( self, component=None, propName=None, short=False,
4273 jsonFormat=True ):
4274 """
4275 Get configuration settings from onos cli
4276 Optional arguments:
4277 component - Optionally only list configurations for a specific
4278 component. If None, all components with configurations
4279 are displayed. Case Sensitive string.
4280 propName - If component is specified, propName option will show
4281 only this specific configuration from that component.
4282 Case Sensitive string.
4283 jsonFormat - Returns output as json. Note that this will override
4284 the short option
4285 short - Short, less verbose, version of configurations.
4286 This is overridden by the json option
4287 returns:
4288 Output from cli as a string or None on error
4289 """
4290 try:
4291 baseStr = "cfg"
4292 cmdStr = " get"
4293 componentStr = ""
4294 if component:
4295 componentStr += " " + component
4296 if propName:
4297 componentStr += " " + propName
4298 if jsonFormat:
4299 baseStr += " -j"
Jon Hall22e94ce2019-01-15 14:52:17 -08004300 expectJson = True
Jon Hallfb760a02015-04-13 15:35:03 -07004301 elif short:
4302 baseStr += " -s"
Jon Hall22e94ce2019-01-15 14:52:17 -08004303 expectJson = False
4304 output = self.sendline( baseStr + cmdStr + componentStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07004305 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004306 assert "Command not found:" not in output, output
4307 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004308 return output
4309 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004310 main.log.exception( self.name + ": Error in processing 'cfg get' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004311 return None
4312 except TypeError:
4313 main.log.exception( self.name + ": Object not as expected" )
4314 return None
4315 except pexpect.EOF:
4316 main.log.error( self.name + ": EOF exception found" )
4317 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004318 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004319 except Exception:
4320 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004321 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004322
4323 def setCfg( self, component, propName, value=None, check=True ):
4324 """
4325 Set/Unset configuration settings from ONOS cli
Jon Hall390696c2015-05-05 17:13:41 -07004326 Required arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004327 component - The case sensitive name of the component whose
4328 property is to be set
4329 propName - The case sensitive name of the property to be set/unset
Jon Hall390696c2015-05-05 17:13:41 -07004330 Optional arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004331 value - The value to set the property to. If None, will unset the
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004332 property and revert it to it's default value(if applicable)
Jon Hallfb760a02015-04-13 15:35:03 -07004333 check - Boolean, Check whether the option was successfully set this
4334 only applies when a value is given.
4335 returns:
4336 main.TRUE on success or main.FALSE on failure. If check is False,
4337 will return main.TRUE unless there is an error
4338 """
4339 try:
4340 baseStr = "cfg"
4341 cmdStr = " set " + str( component ) + " " + str( propName )
4342 if value is not None:
4343 cmdStr += " " + str( value )
4344 output = self.sendline( baseStr + cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004345 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004346 assert "Command not found:" not in output, output
4347 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004348 if value and check:
4349 results = self.getCfg( component=str( component ),
4350 propName=str( propName ),
4351 jsonFormat=True )
4352 # Check if current value is what we just set
4353 try:
4354 jsonOutput = json.loads( results )
4355 current = jsonOutput[ 'value' ]
Jon Hallc6793552016-01-19 14:18:37 -08004356 except ( TypeError, ValueError ):
Jon Hallfb760a02015-04-13 15:35:03 -07004357 main.log.exception( "Error parsing cfg output" )
4358 main.log.error( "output:" + repr( results ) )
4359 return main.FALSE
4360 if current == str( value ):
4361 return main.TRUE
4362 return main.FALSE
4363 return main.TRUE
4364 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004365 main.log.exception( self.name + ": Error in processing 'cfg set' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004366 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08004367 except ( TypeError, ValueError ):
4368 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, results ) )
Jon Hallfb760a02015-04-13 15:35:03 -07004369 return main.FALSE
4370 except pexpect.EOF:
4371 main.log.error( self.name + ": EOF exception found" )
4372 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004373 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004374 except Exception:
4375 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004376 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004377
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004378 def distPrimitivesSend( self, cmd ):
4379 """
4380 Function to handle sending cli commands for the distributed primitives test app
4381
4382 This command will catch some exceptions and retry the command on some
4383 specific store exceptions.
4384
4385 Required arguments:
4386 cmd - The command to send to the cli
4387 returns:
4388 string containing the cli output
4389 None on Error
4390 """
4391 try:
4392 output = self.sendline( cmd )
4393 try:
4394 assert output is not None, "Error in sendline"
4395 # TODO: Maybe make this less hardcoded
4396 # ConsistentMap Exceptions
4397 assert "org.onosproject.store.service" not in output
4398 # Node not leader
4399 assert "java.lang.IllegalStateException" not in output
4400 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004401 main.log.error( self.name + ": Error in processing '" + cmd + "' " +
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004402 "command: " + str( output ) )
4403 retryTime = 30 # Conservative time, given by Madan
4404 main.log.info( "Waiting " + str( retryTime ) +
4405 "seconds before retrying." )
4406 time.sleep( retryTime ) # Due to change in mastership
4407 output = self.sendline( cmd )
4408 assert output is not None, "Error in sendline"
4409 assert "Command not found:" not in output, output
4410 assert "Error executing command" not in output, output
4411 main.log.info( self.name + ": " + output )
4412 return output
4413 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004414 main.log.exception( self.name + ": Error in processing '" + cmd + "' command." )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004415 return None
4416 except TypeError:
4417 main.log.exception( self.name + ": Object not as expected" )
4418 return None
4419 except pexpect.EOF:
4420 main.log.error( self.name + ": EOF exception found" )
4421 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004422 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004423 except Exception:
4424 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004425 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004426
Jon Hall390696c2015-05-05 17:13:41 -07004427 def setTestAdd( self, setName, values ):
4428 """
4429 CLI command to add elements to a distributed set.
4430 Arguments:
4431 setName - The name of the set to add to.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004432 values - The value(s) to add to the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004433 Example usages:
4434 setTestAdd( "set1", "a b c" )
4435 setTestAdd( "set2", "1" )
4436 returns:
4437 main.TRUE on success OR
4438 main.FALSE if elements were already in the set OR
4439 main.ERROR on error
4440 """
4441 try:
4442 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004443 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004444 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
4445 negativeMatch = "\[(.*)\] was already in set " + str( setName )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004446 if re.search( positiveMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004447 return main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004448 elif re.search( negativeMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004449 return main.FALSE
4450 else:
4451 main.log.error( self.name + ": setTestAdd did not" +
4452 " match expected output" )
Jon Hall390696c2015-05-05 17:13:41 -07004453 main.log.debug( self.name + " actual: " + repr( output ) )
4454 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004455 except TypeError:
4456 main.log.exception( self.name + ": Object not as expected" )
4457 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004458 except Exception:
4459 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004460 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004461
4462 def setTestRemove( self, setName, values, clear=False, retain=False ):
4463 """
4464 CLI command to remove elements from a distributed set.
4465 Required arguments:
4466 setName - The name of the set to remove from.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004467 values - The value(s) to remove from the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004468 Optional arguments:
4469 clear - Clear all elements from the set
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004470 retain - Retain only the given values. (intersection of the
4471 original set and the given set)
Jon Hall390696c2015-05-05 17:13:41 -07004472 returns:
4473 main.TRUE on success OR
4474 main.FALSE if the set was not changed OR
4475 main.ERROR on error
4476 """
4477 try:
4478 cmdStr = "set-test-remove "
4479 if clear:
4480 cmdStr += "-c " + str( setName )
4481 elif retain:
4482 cmdStr += "-r " + str( setName ) + " " + str( values )
4483 else:
4484 cmdStr += str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004485 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004486 if clear:
4487 pattern = "Set " + str( setName ) + " cleared"
4488 if re.search( pattern, output ):
4489 return main.TRUE
4490 elif retain:
4491 positivePattern = str( setName ) + " was pruned to contain " +\
4492 "only elements of set \[(.*)\]"
4493 negativePattern = str( setName ) + " was not changed by " +\
4494 "retaining only elements of the set " +\
4495 "\[(.*)\]"
4496 if re.search( positivePattern, output ):
4497 return main.TRUE
4498 elif re.search( negativePattern, output ):
4499 return main.FALSE
4500 else:
4501 positivePattern = "\[(.*)\] was removed from the set " +\
4502 str( setName )
4503 if ( len( values.split() ) == 1 ):
4504 negativePattern = "\[(.*)\] was not in set " +\
4505 str( setName )
4506 else:
4507 negativePattern = "No element of \[(.*)\] was in set " +\
4508 str( setName )
4509 if re.search( positivePattern, output ):
4510 return main.TRUE
4511 elif re.search( negativePattern, output ):
4512 return main.FALSE
4513 main.log.error( self.name + ": setTestRemove did not" +
4514 " match expected output" )
4515 main.log.debug( self.name + " expected: " + pattern )
4516 main.log.debug( self.name + " actual: " + repr( output ) )
4517 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004518 except TypeError:
4519 main.log.exception( self.name + ": Object not as expected" )
4520 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004521 except Exception:
4522 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004523 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004524
4525 def setTestGet( self, setName, values="" ):
4526 """
4527 CLI command to get the elements in a distributed set.
4528 Required arguments:
4529 setName - The name of the set to remove from.
4530 Optional arguments:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004531 values - The value(s) to check if in the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004532 returns:
4533 main.ERROR on error OR
4534 A list of elements in the set if no optional arguments are
4535 supplied OR
4536 A tuple containing the list then:
4537 main.FALSE if the given values are not in the set OR
4538 main.TRUE if the given values are in the set OR
4539 """
4540 try:
4541 values = str( values ).strip()
4542 setName = str( setName ).strip()
4543 length = len( values.split() )
4544 containsCheck = None
4545 # Patterns to match
4546 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004547 pattern = "Items in set " + setName + ":\r\n" + setPattern
Jon Hall390696c2015-05-05 17:13:41 -07004548 containsTrue = "Set " + setName + " contains the value " + values
4549 containsFalse = "Set " + setName + " did not contain the value " +\
4550 values
4551 containsAllTrue = "Set " + setName + " contains the the subset " +\
4552 setPattern
4553 containsAllFalse = "Set " + setName + " did not contain the the" +\
4554 " subset " + setPattern
4555
4556 cmdStr = "set-test-get "
4557 cmdStr += setName + " " + values
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004558 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004559 if length == 0:
4560 match = re.search( pattern, output )
4561 else: # if given values
4562 if length == 1: # Contains output
Jon Hall54b994f2016-12-05 10:48:59 -08004563 patternTrue = pattern + "\r\n" + containsTrue
4564 patternFalse = pattern + "\r\n" + containsFalse
Jon Hall390696c2015-05-05 17:13:41 -07004565 else: # ContainsAll output
Jon Hall54b994f2016-12-05 10:48:59 -08004566 patternTrue = pattern + "\r\n" + containsAllTrue
4567 patternFalse = pattern + "\r\n" + containsAllFalse
Jon Hall390696c2015-05-05 17:13:41 -07004568 matchTrue = re.search( patternTrue, output )
4569 matchFalse = re.search( patternFalse, output )
4570 if matchTrue:
4571 containsCheck = main.TRUE
4572 match = matchTrue
4573 elif matchFalse:
4574 containsCheck = main.FALSE
4575 match = matchFalse
4576 else:
Jon Halle0f0b342017-04-18 11:43:47 -07004577 main.log.error( self.name + " setTestGet did not match " +
Jon Hall390696c2015-05-05 17:13:41 -07004578 "expected output" )
4579 main.log.debug( self.name + " expected: " + pattern )
4580 main.log.debug( self.name + " actual: " + repr( output ) )
4581 match = None
4582 if match:
4583 setMatch = match.group( 1 )
4584 if setMatch == '':
4585 setList = []
4586 else:
4587 setList = setMatch.split( ", " )
4588 if length > 0:
4589 return ( setList, containsCheck )
4590 else:
4591 return setList
4592 else: # no match
4593 main.log.error( self.name + ": setTestGet did not" +
4594 " match expected output" )
4595 main.log.debug( self.name + " expected: " + pattern )
4596 main.log.debug( self.name + " actual: " + repr( output ) )
4597 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004598 except TypeError:
4599 main.log.exception( self.name + ": Object not as expected" )
4600 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004601 except Exception:
4602 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004603 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004604
4605 def setTestSize( self, setName ):
4606 """
4607 CLI command to get the elements in a distributed set.
4608 Required arguments:
4609 setName - The name of the set to remove from.
4610 returns:
Jon Hallfeff3082015-05-19 10:23:26 -07004611 The integer value of the size returned or
Jon Hall390696c2015-05-05 17:13:41 -07004612 None on error
4613 """
4614 try:
4615 # TODO: Should this check against the number of elements returned
4616 # and then return true/false based on that?
4617 setName = str( setName ).strip()
4618 # Patterns to match
4619 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004620 pattern = "There are (\d+) items in set " + setName + ":\r\n" +\
Jon Hall390696c2015-05-05 17:13:41 -07004621 setPattern
4622 cmdStr = "set-test-get -s "
4623 cmdStr += setName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004624 output = self.distPrimitivesSend( cmdStr )
Jon Hall0e240372018-05-02 11:21:57 -07004625 if output:
4626 match = re.search( pattern, output )
4627 if match:
4628 setSize = int( match.group( 1 ) )
4629 setMatch = match.group( 2 )
4630 if len( setMatch.split() ) == setSize:
4631 main.log.info( "The size returned by " + self.name +
4632 " matches the number of elements in " +
4633 "the returned set" )
4634 else:
4635 main.log.error( "The size returned by " + self.name +
4636 " does not match the number of " +
4637 "elements in the returned set." )
4638 return setSize
Jon Hall390696c2015-05-05 17:13:41 -07004639 else: # no match
4640 main.log.error( self.name + ": setTestGet did not" +
4641 " match expected output" )
4642 main.log.debug( self.name + " expected: " + pattern )
4643 main.log.debug( self.name + " actual: " + repr( output ) )
4644 return None
Jon Hall390696c2015-05-05 17:13:41 -07004645 except TypeError:
4646 main.log.exception( self.name + ": Object not as expected" )
4647 return None
Jon Hall390696c2015-05-05 17:13:41 -07004648 except Exception:
4649 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004650 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004651
Jon Hall80daded2015-05-27 16:07:00 -07004652 def counters( self, jsonFormat=True ):
Jon Hall390696c2015-05-05 17:13:41 -07004653 """
4654 Command to list the various counters in the system.
4655 returns:
Jon Hall80daded2015-05-27 16:07:00 -07004656 if jsonFormat, a string of the json object returned by the cli
4657 command
4658 if not jsonFormat, the normal string output of the cli command
Jon Hall390696c2015-05-05 17:13:41 -07004659 None on error
4660 """
Jon Hall390696c2015-05-05 17:13:41 -07004661 try:
Jon Hall390696c2015-05-05 17:13:41 -07004662 cmdStr = "counters"
Jon Hall80daded2015-05-27 16:07:00 -07004663 if jsonFormat:
4664 cmdStr += " -j"
Jon Hall390696c2015-05-05 17:13:41 -07004665 output = self.sendline( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004666 main.log.debug( self.name + ": Counters unparsed: " + output )
4667 output = output.split( "\r\n" )[ -1 ]
4668 main.log.debug( self.name + ": Counters parsed: " + output )
Jon Halla495f562016-05-16 18:03:26 -07004669 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004670 assert "Command not found:" not in output, output
4671 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004672 main.log.info( self.name + ": " + output )
Jon Hall80daded2015-05-27 16:07:00 -07004673 return output
Jon Hall390696c2015-05-05 17:13:41 -07004674 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004675 main.log.exception( self.name + ": Error in processing 'counters' command." )
Jon Hall80daded2015-05-27 16:07:00 -07004676 return None
Jon Hall390696c2015-05-05 17:13:41 -07004677 except TypeError:
4678 main.log.exception( self.name + ": Object not as expected" )
Jon Hall80daded2015-05-27 16:07:00 -07004679 return None
Jon Hall390696c2015-05-05 17:13:41 -07004680 except pexpect.EOF:
4681 main.log.error( self.name + ": EOF exception found" )
4682 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004683 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004684 except Exception:
4685 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004686 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004687
Jon Hall935db192016-04-19 00:22:04 -07004688 def counterTestAddAndGet( self, counter, delta=1 ):
Jon Hall390696c2015-05-05 17:13:41 -07004689 """
Jon Halle1a3b752015-07-22 13:02:46 -07004690 CLI command to add a delta to then get a distributed counter.
Jon Hall390696c2015-05-05 17:13:41 -07004691 Required arguments:
4692 counter - The name of the counter to increment.
4693 Optional arguments:
Jon Halle1a3b752015-07-22 13:02:46 -07004694 delta - The long to add to the counter
Jon Hall390696c2015-05-05 17:13:41 -07004695 returns:
4696 integer value of the counter or
4697 None on Error
4698 """
4699 try:
4700 counter = str( counter )
Jon Halle1a3b752015-07-22 13:02:46 -07004701 delta = int( delta )
Jon Hall390696c2015-05-05 17:13:41 -07004702 cmdStr = "counter-test-increment "
Jon Hall390696c2015-05-05 17:13:41 -07004703 cmdStr += counter
Jon Halle1a3b752015-07-22 13:02:46 -07004704 if delta != 1:
4705 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004706 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004707 pattern = counter + " was updated to (-?\d+)"
Jon Hall390696c2015-05-05 17:13:41 -07004708 match = re.search( pattern, output )
4709 if match:
4710 return int( match.group( 1 ) )
4711 else:
Jon Halle1a3b752015-07-22 13:02:46 -07004712 main.log.error( self.name + ": counterTestAddAndGet did not" +
Jon Hall390696c2015-05-05 17:13:41 -07004713 " match expected output." )
4714 main.log.debug( self.name + " expected: " + pattern )
4715 main.log.debug( self.name + " actual: " + repr( output ) )
4716 return None
Jon Hall390696c2015-05-05 17:13:41 -07004717 except TypeError:
4718 main.log.exception( self.name + ": Object not as expected" )
4719 return None
Jon Hall390696c2015-05-05 17:13:41 -07004720 except Exception:
4721 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004722 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004723
Jon Hall935db192016-04-19 00:22:04 -07004724 def counterTestGetAndAdd( self, counter, delta=1 ):
Jon Halle1a3b752015-07-22 13:02:46 -07004725 """
4726 CLI command to get a distributed counter then add a delta to it.
4727 Required arguments:
4728 counter - The name of the counter to increment.
4729 Optional arguments:
4730 delta - The long to add to the counter
Jon Halle1a3b752015-07-22 13:02:46 -07004731 returns:
4732 integer value of the counter or
4733 None on Error
4734 """
4735 try:
4736 counter = str( counter )
4737 delta = int( delta )
4738 cmdStr = "counter-test-increment -g "
Jon Halle1a3b752015-07-22 13:02:46 -07004739 cmdStr += counter
4740 if delta != 1:
4741 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004742 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004743 pattern = counter + " was updated to (-?\d+)"
4744 match = re.search( pattern, output )
4745 if match:
4746 return int( match.group( 1 ) )
4747 else:
4748 main.log.error( self.name + ": counterTestGetAndAdd did not" +
4749 " match expected output." )
4750 main.log.debug( self.name + " expected: " + pattern )
4751 main.log.debug( self.name + " actual: " + repr( output ) )
4752 return None
Jon Halle1a3b752015-07-22 13:02:46 -07004753 except TypeError:
4754 main.log.exception( self.name + ": Object not as expected" )
4755 return None
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004756 except Exception:
4757 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004758 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004759
4760 def valueTestGet( self, valueName ):
4761 """
4762 CLI command to get the value of an atomic value.
4763 Required arguments:
4764 valueName - The name of the value to get.
4765 returns:
4766 string value of the value or
4767 None on Error
4768 """
4769 try:
4770 valueName = str( valueName )
4771 cmdStr = "value-test "
4772 operation = "get"
4773 cmdStr = "value-test {} {}".format( valueName,
4774 operation )
4775 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004776 main.log.debug( self.name + ": value test unparsed: " + output )
4777 output = output.split( "\r\n" )[ -1 ]
4778 main.log.debug( self.name + ": value test parsed: " + output )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004779 pattern = "(\w+)"
4780 match = re.search( pattern, output )
4781 if match:
4782 return match.group( 1 )
4783 else:
4784 main.log.error( self.name + ": valueTestGet did not" +
4785 " match expected output." )
4786 main.log.debug( self.name + " expected: " + pattern )
4787 main.log.debug( self.name + " actual: " + repr( output ) )
4788 return None
4789 except TypeError:
4790 main.log.exception( self.name + ": Object not as expected" )
4791 return None
4792 except Exception:
4793 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004794 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004795
4796 def valueTestSet( self, valueName, newValue ):
4797 """
4798 CLI command to set the value of an atomic value.
4799 Required arguments:
4800 valueName - The name of the value to set.
4801 newValue - The value to assign to the given value.
4802 returns:
4803 main.TRUE on success or
4804 main.ERROR on Error
4805 """
4806 try:
4807 valueName = str( valueName )
4808 newValue = str( newValue )
4809 operation = "set"
4810 cmdStr = "value-test {} {} {}".format( valueName,
4811 operation,
4812 newValue )
4813 output = self.distPrimitivesSend( cmdStr )
4814 if output is not None:
4815 return main.TRUE
4816 else:
4817 return main.ERROR
4818 except TypeError:
4819 main.log.exception( self.name + ": Object not as expected" )
4820 return main.ERROR
4821 except Exception:
4822 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004823 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004824
4825 def valueTestCompareAndSet( self, valueName, oldValue, newValue ):
4826 """
4827 CLI command to compareAndSet the value of an atomic value.
4828 Required arguments:
4829 valueName - The name of the value.
4830 oldValue - Compare the current value of the atomic value to this
4831 newValue - If the value equals oldValue, set the value to newValue
4832 returns:
4833 main.TRUE on success or
4834 main.FALSE on failure or
4835 main.ERROR on Error
4836 """
4837 try:
4838 valueName = str( valueName )
4839 oldValue = str( oldValue )
4840 newValue = str( newValue )
4841 operation = "compareAndSet"
4842 cmdStr = "value-test {} {} {} {}".format( valueName,
4843 operation,
4844 oldValue,
4845 newValue )
4846 output = self.distPrimitivesSend( cmdStr )
4847 pattern = "(\w+)"
4848 match = re.search( pattern, output )
4849 if match:
4850 result = match.group( 1 )
4851 if result == "true":
4852 return main.TRUE
4853 elif result == "false":
4854 return main.FALSE
4855 else:
4856 main.log.error( self.name + ": valueTestCompareAndSet did not" +
4857 " match expected output." )
4858 main.log.debug( self.name + " expected: " + pattern )
4859 main.log.debug( self.name + " actual: " + repr( output ) )
4860 return main.ERROR
4861 except TypeError:
4862 main.log.exception( self.name + ": Object not as expected" )
4863 return main.ERROR
4864 except Exception:
4865 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004866 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004867
4868 def valueTestGetAndSet( self, valueName, newValue ):
4869 """
4870 CLI command to getAndSet the value of an atomic value.
4871 Required arguments:
4872 valueName - The name of the value to get.
4873 newValue - The value to assign to the given value
4874 returns:
4875 string value of the value or
4876 None on Error
4877 """
4878 try:
4879 valueName = str( valueName )
4880 cmdStr = "value-test "
4881 operation = "getAndSet"
4882 cmdStr += valueName + " " + operation
4883 cmdStr = "value-test {} {} {}".format( valueName,
4884 operation,
4885 newValue )
4886 output = self.distPrimitivesSend( cmdStr )
4887 pattern = "(\w+)"
4888 match = re.search( pattern, output )
4889 if match:
4890 return match.group( 1 )
4891 else:
4892 main.log.error( self.name + ": valueTestGetAndSet did not" +
4893 " match expected output." )
4894 main.log.debug( self.name + " expected: " + pattern )
4895 main.log.debug( self.name + " actual: " + repr( output ) )
4896 return None
4897 except TypeError:
4898 main.log.exception( self.name + ": Object not as expected" )
4899 return None
4900 except Exception:
4901 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004902 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004903
4904 def valueTestDestroy( self, valueName ):
4905 """
4906 CLI command to destroy an atomic value.
4907 Required arguments:
4908 valueName - The name of the value to destroy.
4909 returns:
4910 main.TRUE on success or
4911 main.ERROR on Error
4912 """
4913 try:
4914 valueName = str( valueName )
4915 cmdStr = "value-test "
4916 operation = "destroy"
4917 cmdStr += valueName + " " + operation
4918 output = self.distPrimitivesSend( cmdStr )
4919 if output is not None:
4920 return main.TRUE
4921 else:
4922 return main.ERROR
4923 except TypeError:
4924 main.log.exception( self.name + ": Object not as expected" )
4925 return main.ERROR
Jon Halle1a3b752015-07-22 13:02:46 -07004926 except Exception:
4927 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004928 main.cleanAndExit()
Jon Halle1a3b752015-07-22 13:02:46 -07004929
YPZhangfebf7302016-05-24 16:45:56 -07004930 def summary( self, jsonFormat=True, timeout=30 ):
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004931 """
4932 Description: Execute summary command in onos
4933 Returns: json object ( summary -j ), returns main.FALSE if there is
4934 no output
4935
4936 """
4937 try:
4938 cmdStr = "summary"
4939 if jsonFormat:
4940 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07004941 handle = self.sendline( cmdStr, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07004942 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004943 assert "Command not found:" not in handle, handle
Jon Hall6e709752016-02-01 13:38:46 -08004944 assert "Error:" not in handle, handle
Devin Lima7cfdbd2017-09-29 15:02:22 -07004945 assert "Error executing" not in handle, handle
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004946 if not handle:
4947 main.log.error( self.name + ": There is no output in " +
4948 "summary command" )
4949 return main.FALSE
4950 return handle
Jon Hallc6793552016-01-19 14:18:37 -08004951 except AssertionError:
Jon Hall6e709752016-02-01 13:38:46 -08004952 main.log.exception( "{} Error in summary output:".format( self.name ) )
Jon Hallc6793552016-01-19 14:18:37 -08004953 return None
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004954 except TypeError:
4955 main.log.exception( self.name + ": Object not as expected" )
4956 return None
4957 except pexpect.EOF:
4958 main.log.error( self.name + ": EOF exception found" )
4959 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004960 main.cleanAndExit()
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004961 except Exception:
4962 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004963 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004964
Jon Hall06fd0df2021-01-25 15:50:06 -08004965 def getAddress( self):
4966 """
4967 Get the onos ip address from the cli. This is usefull when connecting using
4968 a container manager such as kubernetes. This function also sets self.address
4969 the value from ONOS.
4970
4971 Returns:
4972 The string value of the key or
4973 None on Error
4974 """
4975 try:
4976 output = self.summary()
4977 address = json.loads( output ).get( 'node' )
4978 self.address = address
4979 return address
You Wang327bad42021-03-24 14:19:58 -07004980 except ( TypeError, ValueError ):
Jon Hall06fd0df2021-01-25 15:50:06 -08004981 main.log.exception( self.name + ": Object not as expected" )
4982 return None
4983 except Exception:
4984 main.log.exception( self.name + ": Uncaught exception!" )
4985 main.cleanAndExit()
4986
Jon Hall935db192016-04-19 00:22:04 -07004987 def transactionalMapGet( self, keyName ):
Jon Hall2a5002c2015-08-21 16:49:11 -07004988 """
4989 CLI command to get the value of a key in a consistent map using
4990 transactions. This a test function and can only get keys from the
4991 test map hard coded into the cli command
4992 Required arguments:
4993 keyName - The name of the key to get
Jon Hall2a5002c2015-08-21 16:49:11 -07004994 returns:
4995 The string value of the key or
4996 None on Error
4997 """
4998 try:
4999 keyName = str( keyName )
5000 cmdStr = "transactional-map-test-get "
Jon Hall2a5002c2015-08-21 16:49:11 -07005001 cmdStr += keyName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07005002 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07005003 pattern = "Key-value pair \(" + keyName + ", (?P<value>.+)\) found."
5004 if "Key " + keyName + " not found." in output:
Jon Hall9bfadd22016-05-11 14:48:07 -07005005 main.log.warn( output )
Jon Hall2a5002c2015-08-21 16:49:11 -07005006 return None
5007 else:
5008 match = re.search( pattern, output )
5009 if match:
5010 return match.groupdict()[ 'value' ]
5011 else:
5012 main.log.error( self.name + ": transactionlMapGet did not" +
5013 " match expected output." )
5014 main.log.debug( self.name + " expected: " + pattern )
5015 main.log.debug( self.name + " actual: " + repr( output ) )
5016 return None
5017 except TypeError:
5018 main.log.exception( self.name + ": Object not as expected" )
5019 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07005020 except Exception:
5021 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005022 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07005023
Jon Hall935db192016-04-19 00:22:04 -07005024 def transactionalMapPut( self, numKeys, value ):
Jon Hall2a5002c2015-08-21 16:49:11 -07005025 """
5026 CLI command to put a value into 'numKeys' number of keys in a
5027 consistent map using transactions. This a test function and can only
5028 put into keys named 'Key#' of the test map hard coded into the cli command
5029 Required arguments:
5030 numKeys - Number of keys to add the value to
5031 value - The string value to put into the keys
Jon Hall2a5002c2015-08-21 16:49:11 -07005032 returns:
5033 A dictionary whose keys are the name of the keys put into the map
5034 and the values of the keys are dictionaries whose key-values are
5035 'value': value put into map and optionaly
5036 'oldValue': Previous value in the key or
5037 None on Error
5038
5039 Example output
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005040 { 'Key1': {'oldValue': 'oldTestValue', 'value': 'Testing'},
5041 'Key2': {'value': 'Testing'} }
Jon Hall2a5002c2015-08-21 16:49:11 -07005042 """
5043 try:
5044 numKeys = str( numKeys )
5045 value = str( value )
5046 cmdStr = "transactional-map-test-put "
Jon Hall2a5002c2015-08-21 16:49:11 -07005047 cmdStr += numKeys + " " + value
Jon Hall7a6ebfd2017-03-13 10:58:58 -07005048 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07005049 newPattern = 'Created Key (?P<key>(\w)+) with value (?P<value>(.)+)\.'
5050 updatedPattern = "Put (?P<value>(.)+) into key (?P<key>(\w)+)\. The old value was (?P<oldValue>(.)+)\."
5051 results = {}
5052 for line in output.splitlines():
5053 new = re.search( newPattern, line )
5054 updated = re.search( updatedPattern, line )
5055 if new:
5056 results[ new.groupdict()[ 'key' ] ] = { 'value': new.groupdict()[ 'value' ] }
5057 elif updated:
5058 results[ updated.groupdict()[ 'key' ] ] = { 'value': updated.groupdict()[ 'value' ],
Jon Hallc6793552016-01-19 14:18:37 -08005059 'oldValue': updated.groupdict()[ 'oldValue' ] }
Jon Hall2a5002c2015-08-21 16:49:11 -07005060 else:
5061 main.log.error( self.name + ": transactionlMapGet did not" +
5062 " match expected output." )
Jon Hallc6793552016-01-19 14:18:37 -08005063 main.log.debug( "{} expected: {!r} or {!r}".format( self.name,
5064 newPattern,
5065 updatedPattern ) )
Jon Hall2a5002c2015-08-21 16:49:11 -07005066 main.log.debug( self.name + " actual: " + repr( output ) )
5067 return results
Jon Hall0e240372018-05-02 11:21:57 -07005068 except ( TypeError, AttributeError ):
Jon Hall2a5002c2015-08-21 16:49:11 -07005069 main.log.exception( self.name + ": Object not as expected" )
5070 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07005071 except Exception:
5072 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005073 main.cleanAndExit()
Jon Hallc6793552016-01-19 14:18:37 -08005074
acsmarsdaea66c2015-09-03 11:44:06 -07005075 def maps( self, jsonFormat=True ):
5076 """
5077 Description: Returns result of onos:maps
5078 Optional:
5079 * jsonFormat: enable json formatting of output
5080 """
5081 try:
5082 cmdStr = "maps"
5083 if jsonFormat:
5084 cmdStr += " -j"
5085 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07005086 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005087 assert "Command not found:" not in handle, handle
acsmarsdaea66c2015-09-03 11:44:06 -07005088 return handle
Jon Hallc6793552016-01-19 14:18:37 -08005089 except AssertionError:
5090 main.log.exception( "" )
5091 return None
acsmarsdaea66c2015-09-03 11:44:06 -07005092 except TypeError:
5093 main.log.exception( self.name + ": Object not as expected" )
5094 return None
5095 except pexpect.EOF:
5096 main.log.error( self.name + ": EOF exception found" )
5097 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005098 main.cleanAndExit()
acsmarsdaea66c2015-09-03 11:44:06 -07005099 except Exception:
5100 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005101 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005102
5103 def getSwController( self, uri, jsonFormat=True ):
5104 """
5105 Descrition: Gets the controller information from the device
5106 """
5107 try:
5108 cmd = "device-controllers "
5109 if jsonFormat:
5110 cmd += "-j "
5111 response = self.sendline( cmd + uri )
Jon Halla495f562016-05-16 18:03:26 -07005112 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005113 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005114 return response
Jon Hallc6793552016-01-19 14:18:37 -08005115 except AssertionError:
5116 main.log.exception( "" )
5117 return None
GlennRC050596c2015-11-18 17:06:41 -08005118 except TypeError:
5119 main.log.exception( self.name + ": Object not as expected" )
5120 return None
5121 except pexpect.EOF:
5122 main.log.error( self.name + ": EOF exception found" )
5123 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005124 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005125 except Exception:
5126 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005127 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005128
5129 def setSwController( self, uri, ip, proto="tcp", port="6653", jsonFormat=True ):
5130 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005131 Descrition: sets the controller(s) for the specified device
GlennRC050596c2015-11-18 17:06:41 -08005132
5133 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005134 Required: uri - String: The uri of the device(switch).
GlennRC050596c2015-11-18 17:06:41 -08005135 ip - String or List: The ip address of the controller.
5136 This parameter can be formed in a couple of different ways.
5137 VALID:
5138 10.0.0.1 - just the ip address
5139 tcp:10.0.0.1 - the protocol and the ip address
5140 tcp:10.0.0.1:6653 - the protocol and port can be specified,
5141 so that you can add controllers with different
5142 protocols and ports
5143 INVALID:
5144 10.0.0.1:6653 - this is not supported by ONOS
5145
5146 Optional: proto - The type of connection e.g. tcp, ssl. If a list of ips are given
5147 port - The port number.
5148 jsonFormat - If set ONOS will output in json NOTE: This is currently not supported
5149
5150 Returns: main.TRUE if ONOS returns without any errors, otherwise returns main.FALSE
5151 """
5152 try:
5153 cmd = "device-setcontrollers"
5154
5155 if jsonFormat:
5156 cmd += " -j"
5157 cmd += " " + uri
5158 if isinstance( ip, str ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005159 ip = [ ip ]
GlennRC050596c2015-11-18 17:06:41 -08005160 for item in ip:
5161 if ":" in item:
5162 sitem = item.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005163 if len( sitem ) == 3:
GlennRC050596c2015-11-18 17:06:41 -08005164 cmd += " " + item
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005165 elif "." in sitem[ 1 ]:
5166 cmd += " {}:{}".format( item, port )
GlennRC050596c2015-11-18 17:06:41 -08005167 else:
5168 main.log.error( "Malformed entry: " + item )
5169 raise TypeError
5170 else:
5171 cmd += " {}:{}:{}".format( proto, item, port )
GlennRC050596c2015-11-18 17:06:41 -08005172 response = self.sendline( cmd )
Jon Halla495f562016-05-16 18:03:26 -07005173 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005174 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005175 if "Error" in response:
5176 main.log.error( response )
5177 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005178 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005179 except AssertionError:
5180 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005181 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005182 except TypeError:
5183 main.log.exception( self.name + ": Object not as expected" )
5184 return main.FALSE
5185 except pexpect.EOF:
5186 main.log.error( self.name + ": EOF exception found" )
5187 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005188 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005189 except Exception:
5190 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005191 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005192
5193 def removeDevice( self, device ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005194 '''
GlennRC20fc6522015-12-23 23:26:57 -08005195 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005196 Remove a device from ONOS by passing the uri of the device(s).
GlennRC20fc6522015-12-23 23:26:57 -08005197 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005198 device - (str or list) the id or uri of the device ex. "of:0000000000000001"
GlennRC20fc6522015-12-23 23:26:57 -08005199 Returns:
5200 Returns main.FALSE if an exception is thrown or an error is present
5201 in the response. Otherwise, returns main.TRUE.
5202 NOTE:
5203 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005204 '''
GlennRC20fc6522015-12-23 23:26:57 -08005205 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005206 if isinstance( device, str ):
You Wang823f5022016-08-18 15:24:41 -07005207 deviceStr = device
5208 device = []
5209 device.append( deviceStr )
GlennRC20fc6522015-12-23 23:26:57 -08005210
5211 for d in device:
5212 time.sleep( 1 )
5213 response = self.sendline( "device-remove {}".format( d ) )
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
GlennRC20fc6522015-12-23 23:26:57 -08005216 if "Error" in response:
5217 main.log.warn( "Error for device: {}\nResponse: {}".format( d, response ) )
5218 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005219 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005220 except AssertionError:
5221 main.log.exception( "" )
5222 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005223 except TypeError:
5224 main.log.exception( self.name + ": Object not as expected" )
5225 return main.FALSE
5226 except pexpect.EOF:
5227 main.log.error( self.name + ": EOF exception found" )
5228 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005229 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005230 except Exception:
5231 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005232 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005233
5234 def removeHost( self, host ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005235 '''
GlennRC20fc6522015-12-23 23:26:57 -08005236 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005237 Remove a host from ONOS by passing the id of the host(s)
GlennRC20fc6522015-12-23 23:26:57 -08005238 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005239 hostId - (str or list) the id or mac of the host ex. "00:00:00:00:00:01"
GlennRC20fc6522015-12-23 23:26:57 -08005240 Returns:
5241 Returns main.FALSE if an exception is thrown or an error is present
5242 in the response. Otherwise, returns main.TRUE.
5243 NOTE:
5244 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005245 '''
GlennRC20fc6522015-12-23 23:26:57 -08005246 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005247 if isinstance( host, str ):
GlennRC20fc6522015-12-23 23:26:57 -08005248 host = list( host )
5249
5250 for h in host:
5251 time.sleep( 1 )
5252 response = self.sendline( "host-remove {}".format( h ) )
Jon Halla495f562016-05-16 18:03:26 -07005253 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005254 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005255 if "Error" in response:
5256 main.log.warn( "Error for host: {}\nResponse: {}".format( h, response ) )
5257 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005258 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005259 except AssertionError:
5260 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005261 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005262 except TypeError:
5263 main.log.exception( self.name + ": Object not as expected" )
5264 return main.FALSE
5265 except pexpect.EOF:
5266 main.log.error( self.name + ": EOF exception found" )
5267 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005268 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005269 except Exception:
5270 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005271 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005272
YPZhangfebf7302016-05-24 16:45:56 -07005273 def link( self, begin, end, state, timeout=30, showResponse=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005274 '''
GlennRCed771242016-01-13 17:02:47 -08005275 Description:
5276 Bring link down or up in the null-provider.
5277 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005278 begin - (string) One end of a device or switch.
5279 end - (string) the other end of the device or switch
GlennRCed771242016-01-13 17:02:47 -08005280 returns:
5281 main.TRUE if no exceptions were thrown and no Errors are
5282 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005283 '''
GlennRCed771242016-01-13 17:02:47 -08005284 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005285 cmd = "null-link null:{} null:{} {}".format( begin, end, state )
YPZhangfebf7302016-05-24 16:45:56 -07005286 response = self.sendline( cmd, showResponse=showResponse, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07005287 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005288 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08005289 if "Error" in response or "Failure" in response:
5290 main.log.error( response )
5291 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005292 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005293 except AssertionError:
5294 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005295 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005296 except TypeError:
5297 main.log.exception( self.name + ": Object not as expected" )
5298 return main.FALSE
5299 except pexpect.EOF:
5300 main.log.error( self.name + ": EOF exception found" )
5301 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005302 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005303 except Exception:
5304 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005305 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005306
Jon Hall2c8959e2016-12-16 12:17:34 -08005307 def portstate( self, dpid, port, state ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005308 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005309 Description:
5310 Changes the state of port in an OF switch by means of the
5311 PORTSTATUS OF messages.
5312 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005313 dpid - (string) Datapath ID of the device. Ex: 'of:0000000000000102'
5314 port - (string) target port in the device. Ex: '2'
5315 state - (string) target state (enable or disable)
Flavio Castro82ee2f62016-06-07 15:04:12 -07005316 returns:
5317 main.TRUE if no exceptions were thrown and no Errors are
5318 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005319 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005320 try:
Jon Hall2c8959e2016-12-16 12:17:34 -08005321 state = state.lower()
5322 assert state == 'enable' or state == 'disable', "Unknown state"
Jon Halle0f0b342017-04-18 11:43:47 -07005323 cmd = "portstate {} {} {}".format( dpid, port, state )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005324 response = self.sendline( cmd, showResponse=True )
5325 assert response is not None, "Error in sendline"
5326 assert "Command not found:" not in response, response
5327 if "Error" in response or "Failure" in response:
5328 main.log.error( response )
5329 return main.FALSE
5330 return main.TRUE
5331 except AssertionError:
5332 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005333 return main.FALSE
Flavio Castro82ee2f62016-06-07 15:04:12 -07005334 except TypeError:
5335 main.log.exception( self.name + ": Object not as expected" )
5336 return main.FALSE
5337 except pexpect.EOF:
5338 main.log.error( self.name + ": EOF exception found" )
5339 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005340 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005341 except Exception:
5342 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005343 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005344
5345 def logSet( self, level="INFO", app="org.onosproject" ):
5346 """
5347 Set the logging level to lvl for a specific app
5348 returns main.TRUE on success
5349 returns main.FALSE if Error occurred
5350 if noExit is True, TestON will not exit, but clean up
5351 Available level: DEBUG, TRACE, INFO, WARN, ERROR
5352 Level defaults to INFO
5353 """
5354 try:
You Wang22e807e2021-03-29 10:53:38 -07005355 handle = self.sendline( "log:set %s %s" % ( level, app ) )
5356 assert handle is not None, "Error in sendline"
5357 assert "Command not found:" not in handle, handle
5358 if re.search( "Error", handle ):
5359 main.log.error( self.name + ": Error in setting log level" )
5360 main.log.error( handle )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005361 return main.FALSE
You Wang22e807e2021-03-29 10:53:38 -07005362 else:
5363 return main.TRUE
5364 except AssertionError:
5365 main.log.exception( "" )
5366 return None
5367 except TypeError:
5368 main.log.exception( self.name + ": Object not as expected" )
5369 return None
Flavio Castro82ee2f62016-06-07 15:04:12 -07005370 except pexpect.EOF:
5371 main.log.error( self.name + ": EOF exception found" )
5372 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005373 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005374 except Exception:
5375 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005376 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07005377
Jon Hall06fd0df2021-01-25 15:50:06 -08005378 def logList( self, saveValues=True ):
5379 """
5380 Gets the current log levels and optionally saves them
5381 returns a dict of the log levels or
5382 returns main.FALSE if Error occurred
5383 """
5384 try:
5385 self.handle.sendline( "log:list" )
5386 self.handle.expect( self.karafPrompt )
5387
5388 response = self.handle.before
5389 logLevels = {}
5390 for line in response.splitlines():
5391 parsed = line.split('│')
5392 logger = parsed[0].strip()
5393 if len( parsed ) != 2 or 'Level' in parsed[1] or logger[0] == '─':
5394 continue
5395 level = parsed[1].strip()
5396 logLevels[ logger ] = level
5397 if saveValues:
5398 self.logLevels = logLevels
5399 return logLevels
5400 except pexpect.TIMEOUT:
5401 main.log.exception( self.name + ": TIMEOUT exception found" )
5402 main.cleanAndExit()
5403 except pexpect.EOF:
5404 main.log.error( self.name + ": EOF exception found" )
5405 main.log.error( self.name + ": " + self.handle.before )
5406 main.cleanAndExit()
5407 except Exception:
5408 main.log.exception( self.name + ": Uncaught exception!" )
5409 main.cleanAndExit()
5410
You Wangdb8cd0a2016-05-26 15:19:45 -07005411 def getGraphDict( self, timeout=60, includeHost=False ):
5412 """
5413 Return a dictionary which describes the latest network topology data as a
5414 graph.
5415 An example of the dictionary:
5416 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
5417 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
5418 Each vertex should at least have an 'edges' attribute which describes the
5419 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005420 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07005421 list of attributes.
5422 An example of the edges dictionary:
5423 'edges': { vertex2: { 'port': ..., 'weight': ... },
5424 vertex3: { 'port': ..., 'weight': ... } }
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005425 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07005426 in topology data.
5427 """
5428 graphDict = {}
5429 try:
5430 links = self.links()
5431 links = json.loads( links )
5432 devices = self.devices()
5433 devices = json.loads( devices )
5434 idToDevice = {}
5435 for device in devices:
5436 idToDevice[ device[ 'id' ] ] = device
5437 if includeHost:
5438 hosts = self.hosts()
5439 # FIXME: support 'includeHost' argument
5440 for link in links:
5441 nodeA = link[ 'src' ][ 'device' ]
5442 nodeB = link[ 'dst' ][ 'device' ]
5443 assert idToDevice[ nodeA ][ 'available' ] and idToDevice[ nodeB ][ 'available' ]
Jon Halle0f0b342017-04-18 11:43:47 -07005444 if nodeA not in graphDict.keys():
5445 graphDict[ nodeA ] = { 'edges': {},
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005446 'dpid': idToDevice[ nodeA ][ 'id' ][ 3: ],
Jon Halle0f0b342017-04-18 11:43:47 -07005447 'type': idToDevice[ nodeA ][ 'type' ],
5448 'available': idToDevice[ nodeA ][ 'available' ],
5449 'role': idToDevice[ nodeA ][ 'role' ],
5450 'mfr': idToDevice[ nodeA ][ 'mfr' ],
5451 'hw': idToDevice[ nodeA ][ 'hw' ],
5452 'sw': idToDevice[ nodeA ][ 'sw' ],
5453 'serial': idToDevice[ nodeA ][ 'serial' ],
5454 'chassisId': idToDevice[ nodeA ][ 'chassisId' ],
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005455 'annotations': idToDevice[ nodeA ][ 'annotations' ]}
You Wangdb8cd0a2016-05-26 15:19:45 -07005456 else:
5457 # Assert nodeB is not connected to any current links of nodeA
You Wang7d14d642019-01-23 15:10:08 -08005458 # assert nodeB not in graphDict[ nodeA ][ 'edges' ].keys()
5459 pass
Jon Halle0f0b342017-04-18 11:43:47 -07005460 graphDict[ nodeA ][ 'edges' ][ nodeB ] = { 'port': link[ 'src' ][ 'port' ],
5461 'type': link[ 'type' ],
5462 'state': link[ 'state' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07005463 return graphDict
5464 except ( TypeError, ValueError ):
5465 main.log.exception( self.name + ": Object not as expected" )
5466 return None
5467 except KeyError:
5468 main.log.exception( self.name + ": KeyError exception found" )
5469 return None
5470 except AssertionError:
5471 main.log.exception( self.name + ": AssertionError exception found" )
5472 return None
5473 except pexpect.EOF:
5474 main.log.error( self.name + ": EOF exception found" )
5475 main.log.error( self.name + ": " + self.handle.before )
5476 return None
5477 except Exception:
5478 main.log.exception( self.name + ": Uncaught exception!" )
5479 return None
YPZhangcbc2a062016-07-11 10:55:44 -07005480
5481 def getIntentPerfSummary( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005482 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005483 Send command to check intent-perf summary
5484 Returns: dictionary for intent-perf summary
5485 if something wrong, function will return None
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005486 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005487 cmd = "intent-perf -s"
5488 respDic = {}
5489 resp = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08005490 assert resp is not None, "Error in sendline"
5491 assert "Command not found:" not in resp, resp
YPZhangcbc2a062016-07-11 10:55:44 -07005492 try:
5493 # Generate the dictionary to return
5494 for l in resp.split( "\n" ):
5495 # Delete any white space in line
5496 temp = re.sub( r'\s+', '', l )
5497 temp = temp.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005498 respDic[ temp[ 0 ] ] = temp[ 1 ]
YPZhangcbc2a062016-07-11 10:55:44 -07005499
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005500 except ( TypeError, ValueError ):
YPZhangcbc2a062016-07-11 10:55:44 -07005501 main.log.exception( self.name + ": Object not as expected" )
5502 return None
5503 except KeyError:
5504 main.log.exception( self.name + ": KeyError exception found" )
5505 return None
5506 except AssertionError:
5507 main.log.exception( self.name + ": AssertionError exception found" )
5508 return None
5509 except pexpect.EOF:
5510 main.log.error( self.name + ": EOF exception found" )
5511 main.log.error( self.name + ": " + self.handle.before )
5512 return None
5513 except Exception:
5514 main.log.exception( self.name + ": Uncaught exception!" )
5515 return None
5516 return respDic
5517
Chiyu Chengec63bde2016-11-17 18:11:36 -08005518 def logSearch( self, mode='all', searchTerm='', startLine='', logNum=1 ):
chengchiyu08303a02016-09-08 17:40:26 -07005519 """
5520 Searches the latest ONOS log file for the given search term and
5521 return a list that contains all the lines that have the search term.
YPZhangcbc2a062016-07-11 10:55:44 -07005522
chengchiyu08303a02016-09-08 17:40:26 -07005523 Arguments:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005524 searchTerm:
5525 The string to grep from the ONOS log.
5526 startLine:
5527 The term that decides which line is the start to search the searchTerm in
5528 the karaf log. For now, startTerm only works in 'first' mode.
5529 logNum:
5530 In some extreme cases, one karaf log is not big enough to contain all the
5531 information.Because of this, search mutiply logs is necessary to capture
5532 the right result. logNum is the number of karaf logs that we need to search
5533 the searchTerm.
chengchiyu08303a02016-09-08 17:40:26 -07005534 mode:
5535 all: return all the strings that contain the search term
5536 last: return the last string that contains the search term
5537 first: return the first string that contains the search term
Chiyu Chengec63bde2016-11-17 18:11:36 -08005538 num: return the number of times that the searchTerm appears in the log
5539 total: return how many lines in karaf log
chengchiyu08303a02016-09-08 17:40:26 -07005540 """
5541 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005542 assert isinstance( searchTerm, str )
Jon Halle0f0b342017-04-18 11:43:47 -07005543 # Build the log paths string
Chiyu Chengec63bde2016-11-17 18:11:36 -08005544 logPath = '/opt/onos/log/karaf.log.'
5545 logPaths = '/opt/onos/log/karaf.log'
5546 for i in range( 1, logNum ):
5547 logPaths = logPath + str( i ) + " " + logPaths
5548 cmd = "cat " + logPaths
You Wang6d301d42017-04-21 10:49:33 -07005549 if startLine:
Jon Halla478b852017-12-04 15:00:15 -08005550 # 100000000 is just a extreme large number to make sure this function can
5551 # grep all the lines after startLine
You Wang6d301d42017-04-21 10:49:33 -07005552 cmd = cmd + " | grep -A 100000000 \'" + startLine + "\'"
Chiyu Chengec63bde2016-11-17 18:11:36 -08005553 if mode == 'all':
5554 cmd = cmd + " | grep \'" + searchTerm + "\'"
You Wang6d301d42017-04-21 10:49:33 -07005555 elif mode == 'last':
Chiyu Chengec63bde2016-11-17 18:11:36 -08005556 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | tail -n 1"
You Wang6d301d42017-04-21 10:49:33 -07005557 elif mode == 'first':
5558 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | head -n 1"
5559 elif mode == 'num':
You Wangd91a70f2019-01-03 15:28:10 -08005560 cmd = cmd + " | grep \'" + searchTerm + "\' | wc -l"
5561 num = self.lineCount( cmd )
Chiyu Chengb8c2c842016-10-05 12:40:49 -07005562 return num
You Wang6d301d42017-04-21 10:49:33 -07005563 elif mode == 'total':
Jon Halld5a94fb2018-11-13 14:32:23 -08005564 totalLines = self.lineCount( "cat /opt/onos/log/karaf.log | wc -l" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005565 return int( totalLines )
You Wang6d301d42017-04-21 10:49:33 -07005566 else:
5567 main.log.error( self.name + " unsupported mode" )
5568 return main.ERROR
chengchiyu08303a02016-09-08 17:40:26 -07005569 before = self.sendline( cmd )
5570 before = before.splitlines()
5571 # make sure the returned list only contains the search term
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005572 returnLines = [ line for line in before if searchTerm in line ]
chengchiyu08303a02016-09-08 17:40:26 -07005573 return returnLines
5574 except AssertionError:
5575 main.log.error( self.name + " searchTerm is not string type" )
5576 return None
5577 except pexpect.EOF:
5578 main.log.error( self.name + ": EOF exception found" )
5579 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005580 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005581 except pexpect.TIMEOUT:
5582 main.log.error( self.name + ": TIMEOUT exception found" )
5583 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005584 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005585 except Exception:
5586 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005587 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005588
5589 def vplsShow( self, jsonFormat=True ):
5590 """
5591 Description: Returns result of onos:vpls show, which should list the
5592 configured VPLS networks and the assigned interfaces.
5593 Optional:
5594 * jsonFormat: enable json formatting of output
5595 Returns:
5596 The output of the command or None on error.
5597 """
5598 try:
5599 cmdStr = "vpls show"
5600 if jsonFormat:
5601 raise NotImplementedError
5602 cmdStr += " -j"
5603 handle = self.sendline( cmdStr )
5604 assert handle is not None, "Error in sendline"
5605 assert "Command not found:" not in handle, handle
5606 return handle
5607 except AssertionError:
5608 main.log.exception( "" )
5609 return None
5610 except TypeError:
5611 main.log.exception( self.name + ": Object not as expected" )
5612 return None
5613 except pexpect.EOF:
5614 main.log.error( self.name + ": EOF exception found" )
5615 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005616 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005617 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005618 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005619 return None
5620 except Exception:
5621 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005622 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005623
5624 def parseVplsShow( self ):
5625 """
5626 Parse the cli output of 'vpls show' into json output. This is required
5627 as there is currently no json output available.
5628 """
5629 try:
5630 output = []
5631 raw = self.vplsShow( jsonFormat=False )
5632 namePat = "VPLS name: (?P<name>\w+)"
5633 interfacesPat = "Associated interfaces: \[(?P<interfaces>.*)\]"
5634 encapPat = "Encapsulation: (?P<encap>\w+)"
5635 pattern = "\s+".join( [ namePat, interfacesPat, encapPat ] )
5636 mIter = re.finditer( pattern, raw )
5637 for match in mIter:
5638 item = {}
5639 item[ 'name' ] = match.group( 'name' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005640 ifaces = match.group( 'interfaces' ).split( ', ' )
Jon Hall2c8959e2016-12-16 12:17:34 -08005641 if ifaces == [ "" ]:
5642 ifaces = []
5643 item[ 'interfaces' ] = ifaces
5644 encap = match.group( 'encap' )
5645 if encap != 'NONE':
5646 item[ 'encapsulation' ] = encap.lower()
5647 output.append( item )
5648 return output
5649 except Exception:
5650 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005651 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005652
5653 def vplsList( self, jsonFormat=True ):
5654 """
5655 Description: Returns result of onos:vpls list, which should list the
5656 configured VPLS networks.
5657 Optional:
5658 * jsonFormat: enable json formatting of output
5659 """
5660 try:
5661 cmdStr = "vpls list"
5662 if jsonFormat:
5663 raise NotImplementedError
5664 cmdStr += " -j"
5665 handle = self.sendline( cmdStr )
5666 assert handle is not None, "Error in sendline"
5667 assert "Command not found:" not in handle, handle
5668 return handle
5669 except AssertionError:
5670 main.log.exception( "" )
5671 return None
5672 except TypeError:
5673 main.log.exception( self.name + ": Object not as expected" )
5674 return None
5675 except pexpect.EOF:
5676 main.log.error( self.name + ": EOF exception found" )
5677 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005678 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005679 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005680 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005681 return None
5682 except Exception:
5683 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005684 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005685
5686 def vplsCreate( self, network ):
5687 """
5688 CLI command to create a new VPLS network.
5689 Required arguments:
5690 network - String name of the network to create.
5691 returns:
5692 main.TRUE on success and main.FALSE on failure
5693 """
5694 try:
5695 network = str( network )
5696 cmdStr = "vpls create "
5697 cmdStr += network
5698 output = self.sendline( cmdStr )
5699 assert output is not None, "Error in sendline"
5700 assert "Command not found:" not in output, output
5701 assert "Error executing command" not in output, output
5702 assert "VPLS already exists:" not in output, output
5703 return main.TRUE
5704 except AssertionError:
5705 main.log.exception( "" )
5706 return main.FALSE
5707 except TypeError:
5708 main.log.exception( self.name + ": Object not as expected" )
5709 return main.FALSE
5710 except pexpect.EOF:
5711 main.log.error( self.name + ": EOF exception found" )
5712 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005713 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005714 except Exception:
5715 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005716 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005717
5718 def vplsDelete( self, network ):
5719 """
5720 CLI command to delete a VPLS network.
5721 Required arguments:
5722 network - Name of the network to delete.
5723 returns:
5724 main.TRUE on success and main.FALSE on failure
5725 """
5726 try:
5727 network = str( network )
5728 cmdStr = "vpls delete "
5729 cmdStr += network
5730 output = self.sendline( cmdStr )
5731 assert output is not None, "Error in sendline"
5732 assert "Command not found:" not in output, output
5733 assert "Error executing command" not in output, output
5734 assert " not found" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005735 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005736 return main.TRUE
5737 except AssertionError:
5738 main.log.exception( "" )
5739 return main.FALSE
5740 except TypeError:
5741 main.log.exception( self.name + ": Object not as expected" )
5742 return main.FALSE
5743 except pexpect.EOF:
5744 main.log.error( self.name + ": EOF exception found" )
5745 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005746 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005747 except Exception:
5748 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005749 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005750
5751 def vplsAddIface( self, network, iface ):
5752 """
5753 CLI command to add an interface to a VPLS network.
5754 Required arguments:
5755 network - Name of the network to add the interface to.
5756 iface - The ONOS name for an interface.
5757 returns:
5758 main.TRUE on success and main.FALSE on failure
5759 """
5760 try:
5761 network = str( network )
5762 iface = str( iface )
5763 cmdStr = "vpls add-if "
5764 cmdStr += network + " " + iface
5765 output = self.sendline( cmdStr )
5766 assert output is not None, "Error in sendline"
5767 assert "Command not found:" not in output, output
5768 assert "Error executing command" not in output, output
5769 assert "already associated to network" not in output, output
5770 assert "Interface cannot be added." not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005771 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005772 return main.TRUE
5773 except AssertionError:
5774 main.log.exception( "" )
5775 return main.FALSE
5776 except TypeError:
5777 main.log.exception( self.name + ": Object not as expected" )
5778 return main.FALSE
5779 except pexpect.EOF:
5780 main.log.error( self.name + ": EOF exception found" )
5781 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005782 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005783 except Exception:
5784 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005785 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005786
5787 def vplsRemIface( self, network, iface ):
5788 """
5789 CLI command to remove an interface from a VPLS network.
5790 Required arguments:
5791 network - Name of the network to remove the interface from.
5792 iface - Name of the interface to remove.
5793 returns:
5794 main.TRUE on success and main.FALSE on failure
5795 """
5796 try:
5797 iface = str( iface )
5798 cmdStr = "vpls rem-if "
5799 cmdStr += network + " " + iface
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 "is not configured" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005805 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005806 return main.TRUE
5807 except AssertionError:
5808 main.log.exception( "" )
5809 return main.FALSE
5810 except TypeError:
5811 main.log.exception( self.name + ": Object not as expected" )
5812 return main.FALSE
5813 except pexpect.EOF:
5814 main.log.error( self.name + ": EOF exception found" )
5815 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005816 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005817 except Exception:
5818 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005819 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005820
5821 def vplsClean( self ):
5822 """
5823 Description: Clears the VPLS app configuration.
5824 Returns: main.TRUE on success and main.FALSE on failure
5825 """
5826 try:
5827 cmdStr = "vpls clean"
5828 handle = self.sendline( cmdStr )
5829 assert handle is not None, "Error in sendline"
5830 assert "Command not found:" not in handle, handle
Jon Hallcf97cf12017-06-06 09:37:51 -07005831 assert "still updating" not in handle, handle
Jon Hall2c8959e2016-12-16 12:17:34 -08005832 return handle
5833 except AssertionError:
5834 main.log.exception( "" )
5835 return main.FALSE
5836 except TypeError:
5837 main.log.exception( self.name + ": Object not as expected" )
5838 return main.FALSE
5839 except pexpect.EOF:
5840 main.log.error( self.name + ": EOF exception found" )
5841 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005842 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005843 except Exception:
5844 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005845 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005846
5847 def vplsSetEncap( self, network, encapType ):
5848 """
5849 CLI command to add an interface to a VPLS network.
5850 Required arguments:
5851 network - Name of the network to create.
5852 encapType - Type of encapsulation.
5853 returns:
5854 main.TRUE on success and main.FALSE on failure
5855 """
5856 try:
5857 network = str( network )
5858 encapType = str( encapType ).upper()
5859 assert encapType in [ "MPLS", "VLAN", "NONE" ], "Incorrect type"
5860 cmdStr = "vpls set-encap "
5861 cmdStr += network + " " + encapType
5862 output = self.sendline( cmdStr )
5863 assert output is not None, "Error in sendline"
5864 assert "Command not found:" not in output, output
5865 assert "Error executing command" not in output, output
5866 assert "already associated to network" not in output, output
5867 assert "Encapsulation type " not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005868 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005869 return main.TRUE
5870 except AssertionError:
5871 main.log.exception( "" )
5872 return main.FALSE
5873 except TypeError:
5874 main.log.exception( self.name + ": Object not as expected" )
5875 return main.FALSE
5876 except pexpect.EOF:
5877 main.log.error( self.name + ": EOF exception found" )
5878 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005879 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005880 except Exception:
5881 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005882 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005883
5884 def interfaces( self, jsonFormat=True ):
5885 """
5886 Description: Returns result of interfaces command.
5887 Optional:
5888 * jsonFormat: enable json formatting of output
5889 Returns:
5890 The output of the command or None on error.
5891 """
5892 try:
5893 cmdStr = "interfaces"
5894 if jsonFormat:
Jon Halle0f0b342017-04-18 11:43:47 -07005895 raise NotImplementedError
Jon Hall2c8959e2016-12-16 12:17:34 -08005896 cmdStr += " -j"
5897 handle = self.sendline( cmdStr )
5898 assert handle is not None, "Error in sendline"
5899 assert "Command not found:" not in handle, handle
5900 return handle
5901 except AssertionError:
5902 main.log.exception( "" )
5903 return None
5904 except TypeError:
5905 main.log.exception( self.name + ": Object not as expected" )
5906 return None
5907 except pexpect.EOF:
5908 main.log.error( self.name + ": EOF exception found" )
5909 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005910 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005911 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005912 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005913 return None
5914 except Exception:
5915 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005916 main.cleanAndExit()
Chiyu Chengec63bde2016-11-17 18:11:36 -08005917
5918 def getTimeStampFromLog( self, mode, searchTerm, splitTerm_before, splitTerm_after, startLine='', logNum=1 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005919 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005920 Get the timestamp of searchTerm from karaf log.
5921
5922 Arguments:
5923 splitTerm_before and splitTerm_after:
5924
5925 The terms that split the string that contains the timeStamp of
5926 searchTerm. For example, if that string is "xxxxxxxcreationTime =
5927 1419510501xxxxxx", then the splitTerm_before is "CreationTime = "
5928 and the splitTerm_after is "x"
5929
5930 others:
Jon Halle0f0b342017-04-18 11:43:47 -07005931 Please look at the "logsearch" Function in onosclidriver.py
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005932 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005933 if logNum < 0:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005934 main.log.error( "Get wrong log number ")
Chiyu Chengec63bde2016-11-17 18:11:36 -08005935 return main.ERROR
5936 lines = self.logSearch( mode=mode, searchTerm=searchTerm, startLine=startLine, logNum=logNum )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005937 if len( lines ) == 0:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005938 main.log.warn( "Captured timestamp string is empty" )
5939 return main.ERROR
5940 lines = lines[ 0 ]
5941 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005942 assert isinstance( lines, str )
Chiyu Chengec63bde2016-11-17 18:11:36 -08005943 # get the target value
5944 line = lines.split( splitTerm_before )
5945 key = line[ 1 ].split( splitTerm_after )
5946 return int( key[ 0 ] )
5947 except IndexError:
5948 main.log.warn( "Index Error!" )
5949 return main.ERROR
5950 except AssertionError:
5951 main.log.warn( "Search Term Not Found " )
5952 return main.ERROR
Jon Halle0f0b342017-04-18 11:43:47 -07005953
5954 def workQueueAdd( self, queueName, value ):
5955 """
5956 CLI command to add a string to the specified Work Queue.
5957 This function uses the distributed primitives test app, which
5958 gives some cli access to distributed primitives for testing
5959 purposes only.
5960
5961 Required arguments:
5962 queueName - The name of the queue to add to
5963 value - The value to add to the queue
5964 returns:
5965 main.TRUE on success, main.FALSE on failure and
5966 main.ERROR on error.
5967 """
5968 try:
5969 queueName = str( queueName )
5970 value = str( value )
5971 prefix = "work-queue-test"
5972 operation = "add"
5973 cmdStr = " ".join( [ prefix, queueName, operation, value ] )
5974 output = self.distPrimitivesSend( cmdStr )
5975 if "Invalid operation name" in output:
5976 main.log.warn( output )
5977 return main.ERROR
5978 elif "Done" in output:
5979 return main.TRUE
5980 except TypeError:
5981 main.log.exception( self.name + ": Object not as expected" )
5982 return main.ERROR
5983 except Exception:
5984 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005985 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07005986
5987 def workQueueAddMultiple( self, queueName, value1, value2 ):
5988 """
5989 CLI command to add two strings to the specified Work Queue.
5990 This function uses the distributed primitives test app, which
5991 gives some cli access to distributed primitives for testing
5992 purposes only.
5993
5994 Required arguments:
5995 queueName - The name of the queue to add to
5996 value1 - The first value to add to the queue
5997 value2 - The second value to add to the queue
5998 returns:
5999 main.TRUE on success, main.FALSE on failure and
6000 main.ERROR on error.
6001 """
6002 try:
6003 queueName = str( queueName )
6004 value1 = str( value1 )
6005 value2 = str( value2 )
6006 prefix = "work-queue-test"
6007 operation = "addMultiple"
6008 cmdStr = " ".join( [ prefix, queueName, operation, value1, value2 ] )
6009 output = self.distPrimitivesSend( cmdStr )
6010 if "Invalid operation name" in output:
6011 main.log.warn( output )
6012 return main.ERROR
6013 elif "Done" in output:
6014 return main.TRUE
6015 except TypeError:
6016 main.log.exception( self.name + ": Object not as expected" )
6017 return main.ERROR
6018 except Exception:
6019 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006020 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006021
6022 def workQueueTakeAndComplete( self, queueName, number=1 ):
6023 """
6024 CLI command to take a value from the specified Work Queue and compelte it.
6025 This function uses the distributed primitives test app, which
6026 gives some cli access to distributed primitives for testing
6027 purposes only.
6028
6029 Required arguments:
6030 queueName - The name of the queue to add to
6031 number - The number of items to take and complete
6032 returns:
6033 main.TRUE on success, main.FALSE on failure and
6034 main.ERROR on error.
6035 """
6036 try:
6037 queueName = str( queueName )
6038 number = str( int( number ) )
6039 prefix = "work-queue-test"
6040 operation = "takeAndComplete"
6041 cmdStr = " ".join( [ prefix, queueName, operation, number ] )
6042 output = self.distPrimitivesSend( cmdStr )
6043 if "Invalid operation name" in output:
6044 main.log.warn( output )
6045 return main.ERROR
6046 elif "Done" in output:
6047 return main.TRUE
6048 except TypeError:
6049 main.log.exception( self.name + ": Object not as expected" )
6050 return main.ERROR
6051 except Exception:
6052 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006053 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006054
6055 def workQueueDestroy( self, queueName ):
6056 """
6057 CLI command to destroy the specified Work Queue.
6058 This function uses the distributed primitives test app, which
6059 gives some cli access to distributed primitives for testing
6060 purposes only.
6061
6062 Required arguments:
6063 queueName - The name of the queue to add to
6064 returns:
6065 main.TRUE on success, main.FALSE on failure and
6066 main.ERROR on error.
6067 """
6068 try:
6069 queueName = str( queueName )
6070 prefix = "work-queue-test"
6071 operation = "destroy"
6072 cmdStr = " ".join( [ prefix, queueName, operation ] )
6073 output = self.distPrimitivesSend( cmdStr )
6074 if "Invalid operation name" in output:
6075 main.log.warn( output )
6076 return main.ERROR
6077 return main.TRUE
6078 except TypeError:
6079 main.log.exception( self.name + ": Object not as expected" )
6080 return main.ERROR
6081 except Exception:
6082 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006083 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006084
6085 def workQueueTotalPending( self, queueName ):
6086 """
6087 CLI command to get the Total Pending items of the specified Work Queue.
6088 This function uses the distributed primitives test app, which
6089 gives some cli access to distributed primitives for testing
6090 purposes only.
6091
6092 Required arguments:
6093 queueName - The name of the queue to add to
6094 returns:
6095 The number of Pending items in the specified work queue or
6096 None on error
6097 """
6098 try:
6099 queueName = str( queueName )
6100 prefix = "work-queue-test"
6101 operation = "totalPending"
6102 cmdStr = " ".join( [ prefix, queueName, operation ] )
6103 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006104 main.log.debug( self.name + ": work queue unparsed: " + output )
6105 output = output.split( "\r\n" )[ -1 ]
6106 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006107 pattern = r'\d+'
6108 if "Invalid operation name" in output:
6109 main.log.warn( output )
6110 return None
6111 else:
6112 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006113 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006114 except ( AttributeError, TypeError ):
6115 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6116 return None
6117 except Exception:
6118 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006119 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006120
6121 def workQueueTotalCompleted( self, queueName ):
6122 """
6123 CLI command to get the Total Completed items of the specified Work Queue.
6124 This function uses the distributed primitives test app, which
6125 gives some cli access to distributed primitives for testing
6126 purposes only.
6127
6128 Required arguments:
6129 queueName - The name of the queue to add to
6130 returns:
6131 The number of complete items in the specified work queue or
6132 None on error
6133 """
6134 try:
6135 queueName = str( queueName )
6136 prefix = "work-queue-test"
6137 operation = "totalCompleted"
6138 cmdStr = " ".join( [ prefix, queueName, operation ] )
6139 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006140 main.log.debug( self.name + ": work queue unparsed: " + output )
6141 output = output.split( "\r\n" )[ -1 ]
6142 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006143 pattern = r'\d+'
6144 if "Invalid operation name" in output:
6145 main.log.warn( output )
6146 return None
6147 else:
6148 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006149 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006150 except ( AttributeError, TypeError ):
6151 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6152 return None
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 workQueueTotalInProgress( self, queueName ):
6158 """
6159 CLI command to get the Total In Progress items of 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 The number of In Progress items in the specified work queue or
6168 None on error
6169 """
6170 try:
6171 queueName = str( queueName )
6172 prefix = "work-queue-test"
6173 operation = "totalInProgress"
6174 cmdStr = " ".join( [ prefix, queueName, operation ] )
6175 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006176 main.log.debug( self.name + ": work queue unparsed: " + output )
6177 output = output.split( "\r\n" )[ -1 ]
6178 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006179 pattern = r'\d+'
6180 if "Invalid operation name" in output:
6181 main.log.warn( output )
6182 return None
6183 else:
6184 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006185 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006186 except ( AttributeError, TypeError ):
6187 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6188 return None
6189 except Exception:
6190 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006191 main.cleanAndExit()
Jeremy Ronquillo818bc7c2017-08-09 17:14:53 +00006192
6193 def events( self, args='-a' ):
6194 """
6195 Description: Returns events -a command output
6196 Optional:
6197 add other arguments
6198 """
6199 try:
6200 cmdStr = "events"
6201 if args:
6202 cmdStr += " " + args
6203 handle = self.sendline( cmdStr )
6204 assert handle is not None, "Error in sendline"
6205 assert "Command not found:" not in handle, handle
6206 return handle
6207 except AssertionError:
6208 main.log.exception( "" )
6209 return None
6210 except TypeError:
6211 main.log.exception( self.name + ": Object not as expected" )
6212 return None
6213 except pexpect.EOF:
6214 main.log.error( self.name + ": EOF exception found" )
6215 main.log.error( self.name + ": " + self.handle.before )
6216 main.cleanAndExit()
6217 except Exception:
6218 main.log.exception( self.name + ": Uncaught exception!" )
6219 main.cleanAndExit()
6220
6221 def getMaster( self, deviceID ):
6222 """
6223 Description: Obtains current master using "roles" command for a specific deviceID
6224 """
6225 try:
6226 return str( self.getRole( deviceID )[ 'master' ] )
6227 except AssertionError:
6228 main.log.exception( "" )
6229 return None
6230 except TypeError:
6231 main.log.exception( self.name + ": Object not as expected" )
6232 return None
6233 except pexpect.EOF:
6234 main.log.error( self.name + ": EOF exception found" )
6235 main.log.error( self.name + ": " + self.handle.before )
6236 main.cleanAndExit()
6237 except Exception:
6238 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lime6fe3c42017-10-18 16:28:40 -07006239 main.cleanAndExit()
Jon Halla478b852017-12-04 15:00:15 -08006240
6241 def issu( self ):
6242 """
6243 Short summary of In-Service Software Upgrade status
6244
6245 Returns the output of the cli command or None on Error
6246 """
6247 try:
6248 cmdStr = "issu"
6249 handle = self.sendline( cmdStr )
6250 assert handle is not None, "Error in sendline"
6251 assert "Command not found:" not in handle, handle
6252 assert "Unsupported command:" not in handle, handle
6253 return handle
6254 except AssertionError:
6255 main.log.exception( "" )
6256 return None
6257 except TypeError:
6258 main.log.exception( self.name + ": Object not as expected" )
6259 return None
6260 except pexpect.EOF:
6261 main.log.error( self.name + ": EOF exception found" )
6262 main.log.error( self.name + ": " + self.handle.before )
6263 main.cleanAndExit()
6264 except Exception:
6265 main.log.exception( self.name + ": Uncaught exception!" )
6266 main.cleanAndExit()
6267
6268 def issuInit( self ):
6269 """
6270 Initiates an In-Service Software Upgrade
6271
6272 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6273 """
6274 try:
6275 cmdStr = "issu init"
6276 handle = self.sendline( cmdStr )
6277 assert handle is not None, "Error in sendline"
6278 assert "Command not found:" not in handle, handle
6279 assert "Unsupported command:" not in handle, handle
6280 if "Initialized" in handle:
6281 return main.TRUE
6282 else:
6283 return main.FALSE
6284 except AssertionError:
6285 main.log.exception( "" )
6286 return main.ERROR
6287 except TypeError:
6288 main.log.exception( self.name + ": Object not as expected" )
6289 return main.ERROR
6290 except pexpect.EOF:
6291 main.log.error( self.name + ": EOF exception found" )
6292 main.log.error( self.name + ": " + self.handle.before )
6293 main.cleanAndExit()
6294 except Exception:
6295 main.log.exception( self.name + ": Uncaught exception!" )
6296 main.cleanAndExit()
6297
6298 def issuUpgrade( self ):
6299 """
6300 Transitions stores to upgraded nodes
6301
6302 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6303 """
6304 try:
6305 cmdStr = "issu upgrade"
6306 handle = self.sendline( cmdStr )
6307 assert handle is not None, "Error in sendline"
6308 assert "Command not found:" not in handle, handle
6309 assert "Unsupported command:" not in handle, handle
6310 if "Upgraded" in handle:
6311 return main.TRUE
6312 else:
6313 return main.FALSE
6314 except AssertionError:
6315 main.log.exception( "" )
6316 return main.ERROR
6317 except TypeError:
6318 main.log.exception( self.name + ": Object not as expected" )
6319 return main.ERROR
6320 except pexpect.EOF:
6321 main.log.error( self.name + ": EOF exception found" )
6322 main.log.error( self.name + ": " + self.handle.before )
6323 main.cleanAndExit()
6324 except Exception:
6325 main.log.exception( self.name + ": Uncaught exception!" )
6326 main.cleanAndExit()
6327
6328 def issuCommit( self ):
6329 """
6330 Finalizes an In-Service Software Upgrade
6331
6332 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6333 """
6334 try:
6335 cmdStr = "issu commit"
6336 handle = self.sendline( cmdStr )
6337 assert handle is not None, "Error in sendline"
6338 assert "Command not found:" not in handle, handle
6339 assert "Unsupported command:" not in handle, handle
6340 # TODO: Check the version returned by this command
6341 if "Committed version" in handle:
6342 return main.TRUE
6343 else:
6344 return main.FALSE
6345 except AssertionError:
6346 main.log.exception( "" )
6347 return main.ERROR
6348 except TypeError:
6349 main.log.exception( self.name + ": Object not as expected" )
6350 return main.ERROR
6351 except pexpect.EOF:
6352 main.log.error( self.name + ": EOF exception found" )
6353 main.log.error( self.name + ": " + self.handle.before )
6354 main.cleanAndExit()
6355 except Exception:
6356 main.log.exception( self.name + ": Uncaught exception!" )
6357 main.cleanAndExit()
6358
6359 def issuRollback( self ):
6360 """
6361 Rolls back an In-Service Software Upgrade
6362
6363 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6364 """
6365 try:
6366 cmdStr = "issu rollback"
6367 handle = self.sendline( cmdStr )
6368 assert handle is not None, "Error in sendline"
6369 assert "Command not found:" not in handle, handle
6370 assert "Unsupported command:" not in handle, handle
6371 # TODO: Check the version returned by this command
6372 if "Rolled back to version" in handle:
6373 return main.TRUE
6374 else:
6375 return main.FALSE
6376 except AssertionError:
6377 main.log.exception( "" )
6378 return main.ERROR
6379 except TypeError:
6380 main.log.exception( self.name + ": Object not as expected" )
6381 return main.ERROR
6382 except pexpect.EOF:
6383 main.log.error( self.name + ": EOF exception found" )
6384 main.log.error( self.name + ": " + self.handle.before )
6385 main.cleanAndExit()
6386 except Exception:
6387 main.log.exception( self.name + ": Uncaught exception!" )
6388 main.cleanAndExit()
6389
6390 def issuReset( self ):
6391 """
6392 Resets the In-Service Software Upgrade status after a rollback
6393
6394 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6395 """
6396 try:
6397 cmdStr = "issu reset"
6398 handle = self.sendline( cmdStr )
6399 assert handle is not None, "Error in sendline"
6400 assert "Command not found:" not in handle, handle
6401 assert "Unsupported command:" not in handle, handle
6402 # TODO: Check the version returned by this command
6403 if "Reset version" in handle:
6404 return main.TRUE
6405 else:
6406 return main.FALSE
6407 except AssertionError:
6408 main.log.exception( "" )
6409 return main.ERROR
6410 except TypeError:
6411 main.log.exception( self.name + ": Object not as expected" )
6412 return main.ERROR
6413 except pexpect.EOF:
6414 main.log.error( self.name + ": EOF exception found" )
6415 main.log.error( self.name + ": " + self.handle.before )
6416 main.cleanAndExit()
6417 except Exception:
6418 main.log.exception( self.name + ": Uncaught exception!" )
6419 main.cleanAndExit()
6420
6421 def issuStatus( self ):
6422 """
6423 Status of an In-Service Software Upgrade
6424
6425 Returns the output of the cli command or None on Error
6426 """
6427 try:
6428 cmdStr = "issu status"
6429 handle = self.sendline( cmdStr )
6430 assert handle is not None, "Error in sendline"
6431 assert "Command not found:" not in handle, handle
6432 assert "Unsupported command:" not in handle, handle
6433 return handle
6434 except AssertionError:
6435 main.log.exception( "" )
6436 return None
6437 except TypeError:
6438 main.log.exception( self.name + ": Object not as expected" )
6439 return None
6440 except pexpect.EOF:
6441 main.log.error( self.name + ": EOF exception found" )
6442 main.log.error( self.name + ": " + self.handle.before )
6443 main.cleanAndExit()
6444 except Exception:
6445 main.log.exception( self.name + ": Uncaught exception!" )
6446 main.cleanAndExit()
6447
6448 def issuVersion( self ):
6449 """
6450 Get the version of an In-Service Software Upgrade
6451
6452 Returns the output of the cli command or None on Error
6453 """
6454 try:
6455 cmdStr = "issu version"
6456 handle = self.sendline( cmdStr )
6457 assert handle is not None, "Error in sendline"
6458 assert "Command not found:" not in handle, handle
6459 assert "Unsupported command:" not in handle, handle
6460 return handle
6461 except AssertionError:
6462 main.log.exception( "" )
6463 return None
6464 except TypeError:
6465 main.log.exception( self.name + ": Object not as expected" )
6466 return None
6467 except pexpect.EOF:
6468 main.log.error( self.name + ": EOF exception found" )
6469 main.log.error( self.name + ": " + self.handle.before )
6470 main.cleanAndExit()
6471 except Exception:
6472 main.log.exception( self.name + ": Uncaught exception!" )
6473 main.cleanAndExit()
You Wange24d6272018-03-27 21:18:50 -07006474
6475 def mcastJoin( self, sIP, groupIP, sPort, dPorts ):
6476 """
6477 Create a multicast route by calling 'mcast-join' command
6478 sIP: source IP of the multicast route
6479 groupIP: group IP of the multicast route
6480 sPort: source port (e.g. of:0000000000000001/3 ) of the multicast route
6481 dPorts: a list of destination ports of the multicast route
6482 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6483 """
6484 try:
6485 cmdStr = "mcast-join"
6486 cmdStr += " " + str( sIP )
6487 cmdStr += " " + str( groupIP )
6488 cmdStr += " " + str( sPort )
6489 assert isinstance( dPorts, list )
6490 for dPort in dPorts:
6491 cmdStr += " " + str( dPort )
6492 handle = self.sendline( cmdStr )
6493 assert handle is not None, "Error in sendline"
6494 assert "Command not found:" not in handle, handle
6495 assert "Unsupported command:" not in handle, handle
6496 assert "Error executing command" not in handle, handle
6497 if "Added the mcast route" in handle:
6498 return main.TRUE
6499 else:
6500 return main.FALSE
6501 except AssertionError:
6502 main.log.exception( "" )
6503 return None
6504 except TypeError:
6505 main.log.exception( self.name + ": Object not as expected" )
6506 return None
6507 except pexpect.EOF:
6508 main.log.error( self.name + ": EOF exception found" )
6509 main.log.error( self.name + ": " + self.handle.before )
6510 main.cleanAndExit()
6511 except Exception:
6512 main.log.exception( self.name + ": Uncaught exception!" )
6513 main.cleanAndExit()
6514
6515 def mcastDelete( self, sIP, groupIP, dPorts ):
6516 """
6517 Delete a multicast route by calling 'mcast-delete' command
6518 sIP: source IP of the multicast route
6519 groupIP: group IP of the multicast route
6520 dPorts: a list of destination ports of the multicast route
6521 Returns main.TRUE if mcast route is deleted; Otherwise main.FALSE
6522 """
6523 try:
6524 cmdStr = "mcast-delete"
6525 cmdStr += " " + str( sIP )
6526 cmdStr += " " + str( groupIP )
6527 assert isinstance( dPorts, list )
6528 for dPort in dPorts:
6529 cmdStr += " " + str( dPort )
6530 handle = self.sendline( cmdStr )
6531 assert handle is not None, "Error in sendline"
6532 assert "Command not found:" not in handle, handle
6533 assert "Unsupported command:" not in handle, handle
6534 assert "Error executing command" not in handle, handle
6535 if "Updated the mcast route" in handle:
6536 return main.TRUE
6537 else:
6538 return main.FALSE
6539 except AssertionError:
6540 main.log.exception( "" )
6541 return None
6542 except TypeError:
6543 main.log.exception( self.name + ": Object not as expected" )
6544 return None
6545 except pexpect.EOF:
6546 main.log.error( self.name + ": EOF exception found" )
6547 main.log.error( self.name + ": " + self.handle.before )
6548 main.cleanAndExit()
6549 except Exception:
6550 main.log.exception( self.name + ": Uncaught exception!" )
6551 main.cleanAndExit()
6552
6553 def mcastHostJoin( self, sAddr, gAddr, srcs, sinks ):
6554 """
6555 Create a multicast route by calling 'mcast-host-join' command
6556 sAddr: we can provide * for ASM or a specific address for SSM
6557 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006558 srcs: a list of HostId of the sources e.g. ["00:AA:00:00:00:01/None"]
You Wange24d6272018-03-27 21:18:50 -07006559 sinks: a list of HostId of the sinks e.g. ["00:AA:00:00:01:05/40"]
6560 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6561 """
6562 try:
6563 cmdStr = "mcast-host-join"
6564 cmdStr += " -sAddr " + str( sAddr )
6565 cmdStr += " -gAddr " + str( gAddr )
6566 assert isinstance( srcs, list )
6567 for src in srcs:
6568 cmdStr += " -srcs " + str( src )
6569 assert isinstance( sinks, list )
6570 for sink in sinks:
6571 cmdStr += " -sinks " + str( sink )
6572 handle = self.sendline( cmdStr )
6573 assert handle is not None, "Error in sendline"
6574 assert "Command not found:" not in handle, handle
6575 assert "Unsupported command:" not in handle, handle
6576 assert "Error executing command" not in handle, handle
6577 if "Added the mcast route" in handle:
6578 return main.TRUE
6579 else:
6580 return main.FALSE
6581 except AssertionError:
6582 main.log.exception( "" )
6583 return None
6584 except TypeError:
6585 main.log.exception( self.name + ": Object not as expected" )
6586 return None
6587 except pexpect.EOF:
6588 main.log.error( self.name + ": EOF exception found" )
6589 main.log.error( self.name + ": " + self.handle.before )
6590 main.cleanAndExit()
6591 except Exception:
6592 main.log.exception( self.name + ": Uncaught exception!" )
6593 main.cleanAndExit()
6594
6595 def mcastHostDelete( self, sAddr, gAddr, host=None ):
6596 """
6597 Delete multicast sink(s) by calling 'mcast-host-delete' command
6598 sAddr: we can provide * for ASM or a specific address for SSM
6599 gAddr: specifies multicast group address
You Wangc02d8352018-04-17 16:42:10 -07006600 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
You Wange24d6272018-03-27 21:18:50 -07006601 will delete the route if not specified
6602 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6603 """
6604 try:
6605 cmdStr = "mcast-host-delete"
6606 cmdStr += " -sAddr " + str( sAddr )
6607 cmdStr += " -gAddr " + str( gAddr )
6608 if host:
6609 cmdStr += " -h " + str( host )
6610 handle = self.sendline( cmdStr )
6611 assert handle is not None, "Error in sendline"
6612 assert "Command not found:" not in handle, handle
6613 assert "Unsupported command:" not in handle, handle
6614 assert "Error executing command" not in handle, handle
6615 if "Updated the mcast route" in handle:
6616 return main.TRUE
6617 elif "Deleted the mcast route" in handle:
6618 return main.TRUE
6619 else:
6620 return main.FALSE
6621 except AssertionError:
6622 main.log.exception( "" )
6623 return None
6624 except TypeError:
6625 main.log.exception( self.name + ": Object not as expected" )
6626 return None
6627 except pexpect.EOF:
6628 main.log.error( self.name + ": EOF exception found" )
6629 main.log.error( self.name + ": " + self.handle.before )
6630 main.cleanAndExit()
6631 except Exception:
6632 main.log.exception( self.name + ": Uncaught exception!" )
6633 main.cleanAndExit()
6634
You Wang547893e2018-05-08 13:34:59 -07006635 def mcastSinkDelete( self, sAddr, gAddr, sink=None ):
6636 """
6637 Delete multicast sink(s) by calling 'mcast-sink-delete' command
6638 sAddr: we can provide * for ASM or a specific address for SSM
6639 gAddr: specifies multicast group address
6640 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
6641 will delete the route if not specified
6642 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6643 """
6644 try:
6645 cmdStr = "mcast-sink-delete"
6646 cmdStr += " -sAddr " + str( sAddr )
6647 cmdStr += " -gAddr " + str( gAddr )
6648 if sink:
6649 cmdStr += " -s " + str( sink )
6650 handle = self.sendline( cmdStr )
6651 assert handle is not None, "Error in sendline"
6652 assert "Command not found:" not in handle, handle
6653 assert "Unsupported command:" not in handle, handle
6654 assert "Error executing command" not in handle, handle
6655 if "Updated the mcast route" in handle:
6656 return main.TRUE
6657 elif "Deleted the mcast route" in handle:
6658 return main.TRUE
6659 else:
6660 return main.FALSE
6661 except AssertionError:
6662 main.log.exception( "" )
6663 return None
6664 except TypeError:
6665 main.log.exception( self.name + ": Object not as expected" )
6666 return None
6667 except pexpect.EOF:
6668 main.log.error( self.name + ": EOF exception found" )
6669 main.log.error( self.name + ": " + self.handle.before )
6670 main.cleanAndExit()
6671 except Exception:
6672 main.log.exception( self.name + ": Uncaught exception!" )
6673 main.cleanAndExit()
6674
You Wange24d6272018-03-27 21:18:50 -07006675 def mcastSourceDelete( self, sAddr, gAddr, srcs=None ):
6676 """
6677 Delete multicast src(s) by calling 'mcast-source-delete' command
6678 sAddr: we can provide * for ASM or a specific address for SSM
6679 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006680 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 -07006681 will delete the route if not specified
6682 Returns main.TRUE if mcast sink is deleted; Otherwise main.FALSE
6683 """
6684 try:
6685 cmdStr = "mcast-source-delete"
6686 cmdStr += " -sAddr " + str( sAddr )
6687 cmdStr += " -gAddr " + str( gAddr )
6688 if srcs:
6689 assert isinstance( srcs, list )
6690 for src in srcs:
6691 cmdStr += " -src " + str( src )
6692 handle = self.sendline( cmdStr )
6693 assert handle is not None, "Error in sendline"
6694 assert "Command not found:" not in handle, handle
6695 assert "Unsupported command:" not in handle, handle
6696 assert "Error executing command" not in handle, handle
6697 if "Updated the mcast route" in handle:
6698 return main.TRUE
6699 elif "Deleted the mcast route" in handle:
6700 return main.TRUE
6701 else:
6702 return main.FALSE
6703 except AssertionError:
6704 main.log.exception( "" )
6705 return None
6706 except TypeError:
6707 main.log.exception( self.name + ": Object not as expected" )
6708 return None
6709 except pexpect.EOF:
6710 main.log.error( self.name + ": EOF exception found" )
6711 main.log.error( self.name + ": " + self.handle.before )
6712 main.cleanAndExit()
6713 except Exception:
6714 main.log.exception( self.name + ": Uncaught exception!" )
6715 main.cleanAndExit()
You Wang5da39c82018-04-26 22:55:08 -07006716
6717 def netcfg( self, jsonFormat=True, args="" ):
6718 """
6719 Run netcfg cli command with given args
6720 """
6721 try:
6722 cmdStr = "netcfg"
6723 if jsonFormat:
6724 cmdStr = cmdStr + " -j"
6725 if args:
6726 cmdStr = cmdStr + " " + str( args )
6727 handle = self.sendline( cmdStr )
6728 assert handle is not None, "Error in sendline"
6729 assert "Command not found:" not in handle, handle
6730 assert "Unsupported command:" not in handle, handle
6731 assert "Error executing command" not in handle, handle
6732 return handle
6733 except AssertionError:
6734 main.log.exception( "" )
6735 return None
6736 except TypeError:
6737 main.log.exception( self.name + ": Object not as expected" )
6738 return None
6739 except pexpect.EOF:
6740 main.log.error( self.name + ": EOF exception found" )
6741 main.log.error( self.name + ": " + self.handle.before )
6742 main.cleanAndExit()
6743 except Exception:
6744 main.log.exception( self.name + ": Uncaught exception!" )
6745 main.cleanAndExit()
6746
You Wang0fa76e72018-05-18 11:33:25 -07006747 def composeT3Command( self, sAddr, dAddr, ipv6=False, verbose=True, simple=False ):
You Wang5da39c82018-04-26 22:55:08 -07006748 """
You Wang54b1d672018-06-11 16:44:13 -07006749 Compose and return a list of t3-troubleshoot cli commands for given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006750 Options:
6751 sAddr: IP address of the source host
6752 dAddr: IP address of the destination host
You Wang0fa76e72018-05-18 11:33:25 -07006753 ipv6: True if hosts are IPv6
6754 verbose: return verbose t3 output if True
6755 simple: compose command for t3-troubleshoot-simple if True
You Wang5da39c82018-04-26 22:55:08 -07006756 """
6757 try:
6758 # Collect information of both hosts from onos
6759 hosts = self.hosts()
6760 hosts = json.loads( hosts )
6761 sHost = None
6762 dHost = None
6763 for host in hosts:
6764 if sAddr in host[ "ipAddresses" ]:
6765 sHost = host
6766 elif dAddr in host[ "ipAddresses" ]:
6767 dHost = host
6768 if sHost and dHost:
6769 break
6770 assert sHost, "Not able to find host with IP {}".format( sAddr )
You Wang54b1d672018-06-11 16:44:13 -07006771 cmdList = []
You Wang5d9527b2018-05-29 17:08:54 -07006772 if simple:
6773 assert dHost, "Not able to find host with IP {}".format( dAddr )
You Wang54b1d672018-06-11 16:44:13 -07006774 cmdStr = "t3-troubleshoot-simple"
6775 if verbose:
6776 cmdStr += " -vv"
6777 if ipv6:
6778 cmdStr += " -et ipv6"
You Wang0fa76e72018-05-18 11:33:25 -07006779 cmdStr += " {}/{} {}/{}".format( sHost[ "mac" ], sHost[ "vlan" ], dHost[ "mac" ], dHost[ "vlan" ] )
You Wang54b1d672018-06-11 16:44:13 -07006780 cmdList.append( cmdStr )
You Wang0fa76e72018-05-18 11:33:25 -07006781 else:
You Wang54b1d672018-06-11 16:44:13 -07006782 for location in sHost[ "locations" ]:
6783 cmdStr = "t3-troubleshoot"
6784 if verbose:
6785 cmdStr += " -vv"
6786 if ipv6:
6787 cmdStr += " -et ipv6"
6788 cmdStr += " -s " + str( sAddr )
6789 cmdStr += " -sp " + str( location[ "elementId" ] ) + "/" + str( location[ "port" ] )
6790 cmdStr += " -sm " + str( sHost[ "mac" ] )
6791 if sHost[ "vlan" ] != "None":
6792 cmdStr += " -vid " + sHost[ "vlan" ]
6793 cmdStr += " -d " + str( dAddr )
6794 netcfg = self.netcfg( args="devices {}".format( location[ "elementId" ] ) )
6795 netcfg = json.loads( netcfg )
6796 assert netcfg, "Failed to get netcfg"
6797 cmdStr += " -dm " + str( netcfg[ "segmentrouting" ][ "routerMac" ] )
6798 cmdList.append( cmdStr )
6799 return cmdList
You Wang5da39c82018-04-26 22:55:08 -07006800 except AssertionError:
6801 main.log.exception( "" )
6802 return None
6803 except ( KeyError, TypeError ):
6804 main.log.exception( self.name + ": Object not as expected" )
6805 return None
6806 except Exception:
6807 main.log.exception( self.name + ": Uncaught exception!" )
6808 main.cleanAndExit()
6809
6810 def t3( self, sAddr, dAddr, ipv6=False ):
6811 """
You Wang54b1d672018-06-11 16:44:13 -07006812 Run t3-troubleshoot cli commands for all posible routes given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006813 Options:
6814 sAddr: IP address of the source host
6815 dAddr: IP address of the destination host
6816 """
6817 try:
You Wang54b1d672018-06-11 16:44:13 -07006818 cmdList = self.composeT3Command( sAddr, dAddr, ipv6 )
6819 assert cmdList is not None, "composeT3Command returned None"
6820 t3Output = ""
6821 for cmdStr in cmdList:
6822 handle = self.sendline( cmdStr )
6823 assert handle is not None, "Error in sendline"
6824 assert "Command not found:" not in handle, handle
6825 assert "Unsupported command:" not in handle, handle
6826 assert "Error executing command" not in handle, handle
6827 assert "Tracing packet" in handle
6828 t3Output += handle
6829 return t3Output
You Wang5da39c82018-04-26 22:55:08 -07006830 except AssertionError:
6831 main.log.exception( "" )
6832 return None
6833 except pexpect.EOF:
6834 main.log.error( self.name + ": EOF exception found" )
6835 main.log.error( self.name + ": " + self.handle.before )
6836 main.cleanAndExit()
6837 except Exception:
6838 main.log.exception( self.name + ": Uncaught exception!" )
6839 main.cleanAndExit()
Jon Hall3c0114c2020-08-11 15:07:42 -07006840
6841 def prepareForCLI( self, debug=True, maxRetries=120 ):
6842 """
6843 Prepare docker container to connect to onos cli
6844 """
6845 try:
6846 # Wait for log files to be created
6847 ready = 0
6848 retries = 0
6849 while not ready and retries < maxRetries:
6850 retries += 1
6851 self.handle.sendline( "ls -al /root/onos/apache-karaf-*/data/log" )
6852 ready = self.handle.expect( [ "No such file or directory", self.dockerPrompt ] )
6853 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6854 if not ready:
6855 self.handle.expect( self.dockerPrompt )
6856 time.sleep( 1 )
Jon Hall3c0114c2020-08-11 15:07:42 -07006857
6858 cmdList = []
6859 cmdList.append( "apt-get update" )
6860 cmdList.append( "apt-get install -y openssh-server" )
6861 # Some built in scripts are hardcoded
6862 cmdList.append( "ln -s /root/onos /opt/onos" )
6863 cmdList.append( "ln -s /root/onos/apache-karaf-*/data/log /opt/onos/log" )
6864 cmdList.append( "ls -al /opt/onos" )
6865 output = ""
6866 for cmdStr in cmdList:
6867 self.handle.sendline( cmdStr )
Jon Hall627b1572020-12-01 12:01:15 -08006868 self.handle.expect( self.dockerPrompt, timeout=420 )
Jon Hall3c0114c2020-08-11 15:07:42 -07006869 self.handle.sendline( "" )
6870 self.handle.expect( self.dockerPrompt )
6871 handle = self.handle.before
6872 assert "command not found" not in handle, handle
6873 assert "No such file or directory" not in handle, handle
6874 output += handle
6875 if debug:
6876 main.log.debug( "%s: %s" % ( self.name, output ) )
6877 return output
6878 except AssertionError:
6879 main.log.exception( "" )
6880 return None
6881 except pexpect.EOF:
6882 main.log.error( self.name + ": EOF exception found" )
6883 main.log.error( self.name + ": " + self.handle.before )
6884 main.cleanAndExit()
6885 except Exception:
6886 main.log.exception( self.name + ": Uncaught exception!" )
6887 main.cleanAndExit()
6888
6889 def onosSecureSSH( self, userName="onos", userPWD="rocks" ):
6890 """
6891 Enables secure access to ONOS console
6892 by removing default users & keys.
6893
6894 bin/onos-user-password onos rocks
6895
6896 Returns: main.TRUE on success and main.FALSE on failure
6897 """
6898
6899 try:
6900 self.handle.sendline( "" )
6901 self.handle.expect( self.dockerPrompt )
6902
6903 self.handle.sendline( "[ ! -f ~/.ssh/id_rsa.pub ] && ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' -q" )
6904 self.handle.expect( self.dockerPrompt )
6905 main.log.debug( "%s: %s%s" % ( self.name, self.handle.before, self.handle.after ) )
6906
6907 self.handle.sendline( "bin/onos-user-key $(id -un) $(cut -d\\\\ -f2 ~/.ssh/id_rsa.pub)" )
6908 self.handle.expect( pexpect.TIMEOUT, timeout=10 )
6909 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6910
6911 self.handle.sendline( "bin/onos-user-password %s %s" % ( userName, userPWD ) )
6912 i = self.handle.expect( [ "usage",
6913 self.dockerPrompt,
6914 pexpect.TIMEOUT ] )
6915 if i == 0:
6916 # malformed command
6917 main.log.warn( self.name + ": Could not parse onos-user-password command" )
6918 self.handle.expect( self.dockerPrompt )
6919 return main.FALSE
6920 elif i == 1:
6921 # Process started
6922 main.log.info( self.name + ": SSH password added for user " + userName )
6923 return main.TRUE
6924 elif i == 2:
6925 # timeout
6926 main.log.error( self.name + ": Failed to secure onos ssh " )
6927 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6928 except pexpect.EOF:
6929 main.log.error( self.name + ": EOF exception found" )
6930 main.log.error( self.name + ": " + self.handle.before )
6931 main.cleanAndExit()
6932 except Exception:
6933 main.log.exception( self.name + ": Uncaught exception!" )
6934 main.cleanAndExit()
Jon Hall62ab6752021-08-22 16:47:43 -07006935
6936 def routeAdd( self, prefix, nextHop, jsonFormat=True ):
6937 """
6938 Add a route with the given prefix and nextHop
6939 """
6940 try:
6941 cmdStr = "route-add %s %s %s" % ( "-j" if jsonFormat else "", prefix, nextHop )
6942 handle = self.sendline( cmdStr )
6943 assert handle is not None, "Error in sendline"
6944 assert "Command not found:" not in handle, handle
6945 assert "Unsupported command:" not in handle, handle
6946 assert "Error executing command" not in handle, handle
6947 return handle
6948 except AssertionError:
6949 main.log.exception( "" )
6950 return None
6951 except TypeError:
6952 main.log.exception( self.name + ": Object not as expected" )
6953 return None
6954 except pexpect.EOF:
6955 main.log.error( self.name + ": EOF exception found" )
6956 main.log.error( self.name + ": " + self.handle.before )
6957 main.cleanAndExit()
6958 except Exception:
6959 main.log.exception( self.name + ": Uncaught exception!" )
6960 main.cleanAndExit()
6961
6962 def routeRemove( self, prefix, nextHop, source=None, jsonFormat=True ):
6963 """
6964 Remove a route with the given prefix and nextHop
6965 """
6966 try:
6967 if source:
6968 raise NotImplemented
6969 cmdStr = "route-remove %s %s %s" % ( "-j" if jsonFormat else "", prefix, nextHop )
6970 handle = self.sendline( cmdStr )
6971 assert handle is not None, "Error in sendline"
6972 assert "Command not found:" not in handle, handle
6973 assert "Unsupported command:" not in handle, handle
6974 assert "Error executing command" not in handle, handle
6975 return handle
6976 except AssertionError:
6977 main.log.exception( "" )
6978 return None
6979 except TypeError:
6980 main.log.exception( self.name + ": Object not as expected" )
6981 return None
6982 except pexpect.EOF:
6983 main.log.error( self.name + ": EOF exception found" )
6984 main.log.error( self.name + ": " + self.handle.before )
6985 main.cleanAndExit()
6986 except Exception:
6987 main.log.exception( self.name + ": Uncaught exception!" )
6988 main.cleanAndExit()
6989
6990 def routes( self, jsonFormat=True, args="" ):
6991 """
6992 Get routes from ONOS
6993 """
6994 try:
6995 cmdStr = "routes"
6996 if jsonFormat:
6997 cmdStr = cmdStr + " -j"
6998 handle = self.sendline( cmdStr )
6999 assert handle is not None, "Error in sendline"
7000 assert "Command not found:" not in handle, handle
7001 assert "Unsupported command:" not in handle, handle
7002 assert "Error executing command" not in handle, handle
7003 return handle
7004 except AssertionError:
7005 main.log.exception( "" )
7006 return None
7007 except TypeError:
7008 main.log.exception( self.name + ": Object not as expected" )
7009 return None
7010 except pexpect.EOF:
7011 main.log.error( self.name + ": EOF exception found" )
7012 main.log.error( self.name + ": " + self.handle.before )
7013 main.cleanAndExit()
7014 except Exception:
7015 main.log.exception( self.name + ": Uncaught exception!" )
7016 main.cleanAndExit()