blob: 5694fc660337f1df7c8100de00620fbb8616f14d [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
Siddesh713c4c52022-01-14 22:08:05 +00003077 def sendOnosCliCommand( self, cmd, params=[] ):
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003078 """
Siddesh713c4c52022-01-14 22:08:05 +00003079 Handles sending an arbitrary command to the ONOS cli and parsing standard errors
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003080 Params:
Siddesh713c4c52022-01-14 22:08:05 +00003081 cmd: The command to be sent in the onos cli
3082 params: Sending the parameters within the command we send in the cli
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003083 """
3084 try:
Siddesh713c4c52022-01-14 22:08:05 +00003085 if not isinstance(params, list):
3086 params=[params]
3087 cmdStr = cmd + " " + ' '.join(params)
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003088 handle = self.sendline( cmdStr )
3089 assert handle is not None, "Error in sendline"
3090 assert "Command not found:" not in handle, handle
Siddesh713c4c52022-01-14 22:08:05 +00003091 # Check for error in cli response
3092 assert "Error executing command" not in handle, handle
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003093 return handle
3094 except AssertionError:
3095 main.log.exception( "" )
Siddesh713c4c52022-01-14 22:08:05 +00003096 return main.FALSE
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -08003097 except pexpect.EOF:
3098 main.log.error( self.name + ": EOF exception found" )
3099 main.log.error( self.name + ": " + self.handle.before )
3100 main.cleanAndExit()
3101 except Exception:
3102 main.log.exception( self.name + ": Uncaught exception!" )
3103 main.cleanAndExit()
3104
Siddesh713c4c52022-01-14 22:08:05 +00003105 def blackholeStaticRoute( self, subnet, addBlackhole=True ):
3106 """
3107 Manage black hole routes in onos.
3108 Params:
3109 subnet: The subnet to be blocked through this route
3110 addBlackhole: Boolean set to declare if we are adding or removing the blackhole route
3111 """
3112 if addBlackhole:
3113 addedBlackholeIP = self.sendOnosCliCommand('sr-blackhole add', subnet)
3114 else:
3115 removedBlackholeIP = self.sendOnosCliCommand('sr-blackhole remove', subnet)
3116 blackHoleList = self.sendOnosCliCommand('sr-blackhole list')
3117 if subnet in blackHoleList:
3118 exists = True
3119 else:
3120 exists = False
3121 if (addBlackhole and exists) or (not addBlackhole and not exists):
3122 return main.TRUE
3123 else:
3124 return main.FALSE
3125
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003126 def checkGroupAddedCount( self, deviceId, expectedGroupCount=0, core=False, comparison=0):
3127 """
3128 Description:
3129 Check whether the number of groups for the given device id that
3130 are in ADDED state is bigger than minGroupCount.
3131 Required:
3132 * deviceId: device id to check the number of added group rules
3133 Optional:
3134 * minGroupCount: the number of groups to compare
3135 * core: if True, only check the number of core groups added
3136 * comparison: if 0, compare with greater than minFlowCount
3137 * if 1, compare with equal to minFlowCount
3138 Return:
3139 Returns the number of groups if it is bigger than minGroupCount,
3140 returns main.FALSE otherwise.
3141 """
3142 count = self.groupAddedCount( deviceId, core )
3143 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003144 main.log.debug( "found {} groups".format( count ) )
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003145 return count if ((count > expectedGroupCount) if (comparison == 0) else (count == expectedGroupCount)) else main.FALSE
3146
You Wangc02f3be2018-05-18 12:14:23 -07003147 def getGroups( self, deviceId, groupType="any" ):
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003148 """
3149 Retrieve groups from a specific device.
You Wangc02f3be2018-05-18 12:14:23 -07003150 deviceId: Id of the device from which we retrieve groups
3151 groupType: Type of group
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003152 """
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003153 try:
You Wangc02f3be2018-05-18 12:14:23 -07003154 groupCmd = "groups -t {0} any {1}".format( groupType, deviceId )
3155 handle = self.sendline( groupCmd )
Andreas Pantelopoulosdf5061f2018-05-15 11:46:59 -07003156 assert handle is not None, "Error in sendline"
3157 assert "Command not found:" not in handle, handle
3158 return handle
3159 except AssertionError:
3160 main.log.exception( "" )
3161 return None
3162 except TypeError:
3163 main.log.exception( self.name + ": Object not as expected" )
3164 return None
3165 except pexpect.EOF:
3166 main.log.error( self.name + ": EOF exception found" )
3167 main.log.error( self.name + ": " + self.handle.before )
3168 main.cleanAndExit()
3169 except Exception:
3170 main.log.exception( self.name + ": Uncaught exception!" )
3171 main.cleanAndExit()
3172
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003173 def checkFlowAddedCount( self, deviceId, expectedFlowCount=0, core=False, comparison=0):
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003174 """
3175 Description:
3176 Check whether the number of flow rules for the given device id that
3177 are in ADDED state is bigger than minFlowCount.
3178 Required:
3179 * deviceId: device id to check the number of added flow rules
3180 Optional:
3181 * minFlowCount: the number of flow rules to compare
3182 * core: if True, only check the number of core flows added
Andreas Pantelopoulos9173d442018-03-01 17:07:37 -08003183 * comparison: if 0, compare with greater than minFlowCount
3184 * if 1, compare with equal to minFlowCount
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003185 Return:
3186 Returns the number of flow rules if it is bigger than minFlowCount,
3187 returns main.FALSE otherwise.
3188 """
3189 count = self.flowAddedCount( deviceId, core )
3190 count = int( count ) if count else 0
Jon Hall9677ed32018-04-24 11:16:23 -07003191 main.log.debug( "found {} flows".format( count ) )
Jon Hall39570262020-11-17 12:18:19 -08003192 return count if ((count >= expectedFlowCount) if (comparison == 0) else (count == expectedFlowCount)) else main.FALSE
Jonghwan Hyuncf2345c2018-02-26 11:07:54 -08003193
kelvin-onlabd3b64892015-01-20 13:26:24 -08003194 def getAllDevicesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003195 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003196 Use 'devices' function to obtain list of all devices
3197 and parse the result to obtain a list of all device
3198 id's. Returns this list. Returns empty list if no
3199 devices exist
kelvin8ec71442015-01-15 16:57:00 -08003200 List is ordered sequentially
3201
andrewonlab3e15ead2014-10-15 14:21:34 -04003202 This function may be useful if you are not sure of the
kelvin8ec71442015-01-15 16:57:00 -08003203 device id, and wish to execute other commands using
andrewonlab3e15ead2014-10-15 14:21:34 -04003204 the ids. By obtaining the list of device ids on the fly,
3205 you can iterate through the list to get mastership, etc.
kelvin8ec71442015-01-15 16:57:00 -08003206 """
andrewonlab7e4d2d32014-10-15 13:23:21 -04003207 try:
kelvin8ec71442015-01-15 16:57:00 -08003208 # Call devices and store result string
kelvin-onlabd3b64892015-01-20 13:26:24 -08003209 devicesStr = self.devices( jsonFormat=False )
3210 idList = []
kelvin8ec71442015-01-15 16:57:00 -08003211
kelvin-onlabd3b64892015-01-20 13:26:24 -08003212 if not devicesStr:
kelvin8ec71442015-01-15 16:57:00 -08003213 main.log.info( "There are no devices to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003214 return idList
kelvin8ec71442015-01-15 16:57:00 -08003215
3216 # Split the string into list by comma
kelvin-onlabd3b64892015-01-20 13:26:24 -08003217 deviceList = devicesStr.split( "," )
kelvin8ec71442015-01-15 16:57:00 -08003218 # Get temporary list of all arguments with string 'id='
kelvin-onlabd3b64892015-01-20 13:26:24 -08003219 tempList = [ dev for dev in deviceList if "id=" in dev ]
kelvin8ec71442015-01-15 16:57:00 -08003220 # Split list further into arguments before and after string
3221 # 'id='. Get the latter portion ( the actual device id ) and
kelvin-onlabd3b64892015-01-20 13:26:24 -08003222 # append to idList
3223 for arg in tempList:
3224 idList.append( arg.split( "id=" )[ 1 ] )
3225 return idList
andrewonlab7e4d2d32014-10-15 13:23:21 -04003226
Jon Halld4d4b372015-01-28 16:02:41 -08003227 except TypeError:
3228 main.log.exception( self.name + ": Object not as expected" )
3229 return None
andrewonlab7e4d2d32014-10-15 13:23:21 -04003230 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003231 main.log.error( self.name + ": EOF exception found" )
3232 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003233 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003234 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003235 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003236 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003237
kelvin-onlabd3b64892015-01-20 13:26:24 -08003238 def getAllNodesId( self ):
kelvin8ec71442015-01-15 16:57:00 -08003239 """
andrewonlab7c211572014-10-15 16:45:20 -04003240 Uses 'nodes' function to obtain list of all nodes
3241 and parse the result of nodes to obtain just the
kelvin8ec71442015-01-15 16:57:00 -08003242 node id's.
andrewonlab7c211572014-10-15 16:45:20 -04003243 Returns:
3244 list of node id's
kelvin8ec71442015-01-15 16:57:00 -08003245 """
andrewonlab7c211572014-10-15 16:45:20 -04003246 try:
Jon Hall5aa168b2015-03-23 14:23:09 -07003247 nodesStr = self.nodes( jsonFormat=True )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003248 idList = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003249 # Sample nodesStr output
Jon Hallbd182782016-03-28 16:42:22 -07003250 # id=local, address=127.0.0.1:9876, state=READY *
kelvin-onlabd3b64892015-01-20 13:26:24 -08003251 if not nodesStr:
kelvin8ec71442015-01-15 16:57:00 -08003252 main.log.info( "There are no nodes to get id from" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003253 return idList
Jon Hall5aa168b2015-03-23 14:23:09 -07003254 nodesJson = json.loads( nodesStr )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003255 idList = [ node.get( 'id' ) for node in nodesJson ]
kelvin-onlabd3b64892015-01-20 13:26:24 -08003256 return idList
Jon Hallc6793552016-01-19 14:18:37 -08003257 except ( TypeError, ValueError ):
3258 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, nodesStr ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003259 return None
andrewonlab7c211572014-10-15 16:45:20 -04003260 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003261 main.log.error( self.name + ": EOF exception found" )
3262 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003263 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003264 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003265 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003266 main.cleanAndExit()
andrewonlab7e4d2d32014-10-15 13:23:21 -04003267
kelvin-onlabd3b64892015-01-20 13:26:24 -08003268 def getDevice( self, dpid=None ):
kelvin8ec71442015-01-15 16:57:00 -08003269 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003270 Return the first device from the devices api whose 'id' contains 'dpid'
3271 Return None if there is no match
kelvin8ec71442015-01-15 16:57:00 -08003272 """
Jon Halla91c4dc2014-10-22 12:57:04 -04003273 try:
kelvin8ec71442015-01-15 16:57:00 -08003274 if dpid is None:
Jon Halla91c4dc2014-10-22 12:57:04 -04003275 return None
3276 else:
kelvin8ec71442015-01-15 16:57:00 -08003277 dpid = dpid.replace( ':', '' )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003278 rawDevices = self.devices()
3279 devicesJson = json.loads( rawDevices )
kelvin8ec71442015-01-15 16:57:00 -08003280 # search json for the device with dpid then return the device
kelvin-onlabd3b64892015-01-20 13:26:24 -08003281 for device in devicesJson:
kelvin8ec71442015-01-15 16:57:00 -08003282 # print "%s in %s?" % ( dpid, device[ 'id' ] )
3283 if dpid in device[ 'id' ]:
Jon Halla91c4dc2014-10-22 12:57:04 -04003284 return device
3285 return None
Jon Hallc6793552016-01-19 14:18:37 -08003286 except ( TypeError, ValueError ):
3287 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawDevices ) )
Jon Halld4d4b372015-01-28 16:02:41 -08003288 return None
Jon Halla91c4dc2014-10-22 12:57:04 -04003289 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003290 main.log.error( self.name + ": EOF exception found" )
3291 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003292 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003293 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003294 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003295 main.cleanAndExit()
Jon Halla91c4dc2014-10-22 12:57:04 -04003296
You Wang24139872016-05-03 11:48:47 -07003297 def getTopology( self, topologyOutput ):
3298 """
3299 Definition:
3300 Loads a json topology output
3301 Return:
3302 topology = current ONOS topology
3303 """
You Wang24139872016-05-03 11:48:47 -07003304 try:
3305 # either onos:topology or 'topology' will work in CLI
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003306 topology = json.loads( topologyOutput )
Jeremy Songsterbc2d8ac2016-05-04 11:25:42 -07003307 main.log.debug( topology )
You Wang24139872016-05-03 11:48:47 -07003308 return topology
You Wangd3cb2ce2016-05-16 14:01:24 -07003309 except ( TypeError, ValueError ):
3310 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, topologyOutput ) )
3311 return None
You Wang24139872016-05-03 11:48:47 -07003312 except pexpect.EOF:
3313 main.log.error( self.name + ": EOF exception found" )
3314 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003315 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003316 except Exception:
3317 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003318 main.cleanAndExit()
You Wang24139872016-05-03 11:48:47 -07003319
Jon Hall39570262020-11-17 12:18:19 -08003320 def checkStatus( self, numoswitch, numolink = -1, numoctrl = -1, numoSCCs=1, logLevel="info" ):
kelvin8ec71442015-01-15 16:57:00 -08003321 """
Jon Hallefbd9792015-03-05 16:11:36 -08003322 Checks the number of switches & links that ONOS sees against the
kelvin8ec71442015-01-15 16:57:00 -08003323 supplied values. By default this will report to main.log, but the
You Wang24139872016-05-03 11:48:47 -07003324 log level can be specific.
kelvin8ec71442015-01-15 16:57:00 -08003325
Flavio Castro82ee2f62016-06-07 15:04:12 -07003326 Params: numoswitch = expected number of switches
Jon Hallefbd9792015-03-05 16:11:36 -08003327 numolink = expected number of links
Flavio Castro82ee2f62016-06-07 15:04:12 -07003328 numoctrl = expected number of controllers
Jon Hall39570262020-11-17 12:18:19 -08003329 numoSCCs = Number of expected SCCs
You Wang24139872016-05-03 11:48:47 -07003330 logLevel = level to log to.
3331 Currently accepts 'info', 'warn' and 'report'
Jon Hall42db6dc2014-10-24 19:03:48 -04003332
Jon Hallefbd9792015-03-05 16:11:36 -08003333 Returns: main.TRUE if the number of switches and links are correct,
3334 main.FALSE if the number of switches and links is incorrect,
Jon Hall42db6dc2014-10-24 19:03:48 -04003335 and main.ERROR otherwise
kelvin8ec71442015-01-15 16:57:00 -08003336 """
Jon Hall42db6dc2014-10-24 19:03:48 -04003337 try:
You Wang13310252016-07-31 10:56:14 -07003338 summary = self.summary()
3339 summary = json.loads( summary )
Flavio Castrof5b3f872016-06-23 17:52:31 -07003340 except ( TypeError, ValueError ):
3341 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, summary ) )
3342 return main.ERROR
3343 try:
3344 topology = self.getTopology( self.topology() )
Jon Halle0f0b342017-04-18 11:43:47 -07003345 if topology == {} or topology is None or summary == {} or summary is None:
Jon Hall42db6dc2014-10-24 19:03:48 -04003346 return main.ERROR
3347 output = ""
kelvin8ec71442015-01-15 16:57:00 -08003348 # Is the number of switches is what we expected
3349 devices = topology.get( 'devices', False )
3350 links = topology.get( 'links', False )
Flavio Castro82ee2f62016-06-07 15:04:12 -07003351 nodes = summary.get( 'nodes', False )
Jon Hall39570262020-11-17 12:18:19 -08003352 SCCs = summary.get( 'SCC(s)', False )
3353 if devices is False or links is False or nodes is False or SCCs is False:
3354 main.log.warn( "Issues parsing topology and summary output" )
3355 main.log.debug( topology )
3356 main.log.debug( summary )
Jon Hall42db6dc2014-10-24 19:03:48 -04003357 return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -08003358 switchCheck = ( int( devices ) == int( numoswitch ) )
Jon Hall39570262020-11-17 12:18:19 -08003359 if not switchCheck:
3360 main.log.debug( "switch Check Failed" )
Pier6a0c4de2018-03-18 16:01:30 -07003361 linkCheck = ( int( links ) == int( numolink ) ) or int( numolink ) == -1
Jon Hall39570262020-11-17 12:18:19 -08003362 if not linkCheck:
3363 main.log.debug( "link Check Failed" )
Flavio Castro82ee2f62016-06-07 15:04:12 -07003364 nodeCheck = ( int( nodes ) == int( numoctrl ) ) or int( numoctrl ) == -1
Jon Hall39570262020-11-17 12:18:19 -08003365 if not nodeCheck:
3366 main.log.debug( "node Check Failed" )
3367 SCCsCheck = ( int( SCCs ) == int( numoSCCs ) ) or int( numoSCCs ) == -1
3368 if not SCCsCheck:
3369 main.log.debug( "SCCs Check Failed" )
3370 if switchCheck and linkCheck and nodeCheck and SCCsCheck:
kelvin8ec71442015-01-15 16:57:00 -08003371 # We expected the correct numbers
Jon Hall39570262020-11-17 12:18:19 -08003372 output = output + "The number of links, switches, nodes, and SCCs match "\
You Wang24139872016-05-03 11:48:47 -07003373 + "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003374 result = main.TRUE
3375 else:
You Wang24139872016-05-03 11:48:47 -07003376 output = output + \
Jon Hall627b1572020-12-01 12:01:15 -08003377 "The number of links, switches, nodes, and SCCs does not match " + \
You Wang24139872016-05-03 11:48:47 -07003378 "what was expected"
Jon Hall42db6dc2014-10-24 19:03:48 -04003379 result = main.FALSE
Jon Hall39570262020-11-17 12:18:19 -08003380 output = output + "\n ONOS sees %i devices " % int( devices )
3381 output = output + "(%i expected) " % int( numoswitch )
3382 if int( numolink ) >= 0:
Pier6a0c4de2018-03-18 16:01:30 -07003383 output = output + "and %i links " % int( links )
Jon Hall39570262020-11-17 12:18:19 -08003384 output = output + "(%i expected) " % int( numolink )
3385 if int( numoctrl ) >= 0:
Flavio Castro82ee2f62016-06-07 15:04:12 -07003386 output = output + "and %i controllers " % int( nodes )
Jon Hall39570262020-11-17 12:18:19 -08003387 output = output + "(%i expected) " % int( numoctrl )
3388 if int( numoSCCs ) >= 0:
3389 output = output + "and %i SCCs " % int( SCCs )
3390 output = output + "(%i expected)" % int( numoSCCs )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003391 if logLevel == "report":
kelvin8ec71442015-01-15 16:57:00 -08003392 main.log.report( output )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003393 elif logLevel == "warn":
kelvin8ec71442015-01-15 16:57:00 -08003394 main.log.warn( output )
Jon Hall42db6dc2014-10-24 19:03:48 -04003395 else:
You Wang24139872016-05-03 11:48:47 -07003396 main.log.info( output )
Jon Hall39570262020-11-17 12:18:19 -08003397 main.TOPOOUTPUT = output
kelvin8ec71442015-01-15 16:57:00 -08003398 return result
Jon Hall42db6dc2014-10-24 19:03:48 -04003399 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003400 main.log.error( self.name + ": EOF exception found" )
3401 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003402 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003403 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003404 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003405 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003406
kelvin-onlabd3b64892015-01-20 13:26:24 -08003407 def deviceRole( self, deviceId, onosNode, role="master" ):
kelvin8ec71442015-01-15 16:57:00 -08003408 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003409 Calls the device-role cli command.
kelvin-onlabd3b64892015-01-20 13:26:24 -08003410 deviceId must be the id of a device as seen in the onos devices command
3411 onosNode is the ip of one of the onos nodes in the cluster
Jon Hall1c9e8732014-10-27 19:29:27 -04003412 role must be either master, standby, or none
3413
Jon Halle3f39ff2015-01-13 11:50:53 -08003414 Returns:
3415 main.TRUE or main.FALSE based on argument verification and
3416 main.ERROR if command returns and error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003417 """
Jon Hall1c9e8732014-10-27 19:29:27 -04003418 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003419 if role.lower() == "master" or role.lower() == "standby" or\
Jon Hall1c9e8732014-10-27 19:29:27 -04003420 role.lower() == "none":
kelvin-onlabd3b64892015-01-20 13:26:24 -08003421 cmdStr = "device-role " +\
3422 str( deviceId ) + " " +\
3423 str( onosNode ) + " " +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003424 str( role )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003425 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003426 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003427 assert "Command not found:" not in handle, handle
kelvin-onlab898a6c62015-01-16 14:13:53 -08003428 if re.search( "Error", handle ):
3429 # end color output to escape any colours
3430 # from the cli
kelvin8ec71442015-01-15 16:57:00 -08003431 main.log.error( self.name + ": " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003432 handle + '\033[0m' )
kelvin8ec71442015-01-15 16:57:00 -08003433 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -08003434 return main.TRUE
Jon Hall1c9e8732014-10-27 19:29:27 -04003435 else:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003436 main.log.error( "Invalid 'role' given to device_role(). " +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003437 "Value was '" + str( role ) + "'." )
Jon Hall1c9e8732014-10-27 19:29:27 -04003438 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003439 except AssertionError:
3440 main.log.exception( "" )
3441 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003442 except TypeError:
3443 main.log.exception( self.name + ": Object not as expected" )
3444 return None
Jon Hall1c9e8732014-10-27 19:29:27 -04003445 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003446 main.log.error( self.name + ": EOF exception found" )
3447 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003448 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003449 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003450 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003451 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003452
kelvin-onlabd3b64892015-01-20 13:26:24 -08003453 def clusters( self, jsonFormat=True ):
kelvin8ec71442015-01-15 16:57:00 -08003454 """
Jon Hall0dd09952018-04-19 09:59:11 -07003455 Lists all topology clusters
Jon Hallffb386d2014-11-21 13:43:38 -08003456 Optional argument:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003457 * jsonFormat - boolean indicating if you want output in json
kelvin8ec71442015-01-15 16:57:00 -08003458 """
Jon Hall73cf9cc2014-11-20 22:28:38 -08003459 try:
Jon Hall0dd09952018-04-19 09:59:11 -07003460 cmdStr = "topo-clusters"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003461 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003462 cmdStr += " -j"
3463 handle = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003464 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003465 assert "Command not found:" not in handle, handle
Jon Hallc6358dd2015-04-10 12:44:28 -07003466 return handle
Jon Hallc6793552016-01-19 14:18:37 -08003467 except AssertionError:
3468 main.log.exception( "" )
3469 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003470 except TypeError:
3471 main.log.exception( self.name + ": Object not as expected" )
3472 return None
Jon Hall73cf9cc2014-11-20 22:28:38 -08003473 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003474 main.log.error( self.name + ": EOF exception found" )
3475 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003476 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003477 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003478 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003479 main.cleanAndExit()
Jon Hall73cf9cc2014-11-20 22:28:38 -08003480
kelvin-onlabd3b64892015-01-20 13:26:24 -08003481 def electionTestLeader( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003482 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003483 CLI command to get the current leader for the Election test application
3484 NOTE: Requires installation of the onos-app-election feature
3485 Returns: Node IP of the leader if one exists
3486 None if none exists
3487 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003488 """
Jon Hall94fd0472014-12-08 11:52:42 -08003489 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003490 cmdStr = "election-test-leader"
3491 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003492 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003493 assert "Command not found:" not in response, response
Jon Halle3f39ff2015-01-13 11:50:53 -08003494 # Leader
3495 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003496 "app\sis\s(?P<node>.+)\."
kelvin-onlabd3b64892015-01-20 13:26:24 -08003497 nodeSearch = re.search( leaderPattern, response )
3498 if nodeSearch:
3499 node = nodeSearch.group( 'node' )
Jon Halle3f39ff2015-01-13 11:50:53 -08003500 main.log.info( "Election-test-leader on " + str( self.name ) +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003501 " found " + node + " as the leader" )
Jon Hall94fd0472014-12-08 11:52:42 -08003502 return node
Jon Halle3f39ff2015-01-13 11:50:53 -08003503 # no leader
3504 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003505 "the\sElection\sapp"
kelvin-onlabd3b64892015-01-20 13:26:24 -08003506 nullSearch = re.search( nullPattern, response )
3507 if nullSearch:
Jon Halle3f39ff2015-01-13 11:50:53 -08003508 main.log.info( "Election-test-leader found no leader on " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003509 self.name )
Jon Hall94fd0472014-12-08 11:52:42 -08003510 return None
kelvin-onlab898a6c62015-01-16 14:13:53 -08003511 # error
Jon Hall0e240372018-05-02 11:21:57 -07003512 main.log.error( self.name + ": Error in electionTestLeader on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003513 ": " + "unexpected response" )
3514 main.log.error( repr( response ) )
3515 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003516 except AssertionError:
3517 main.log.exception( "" )
3518 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003519 except TypeError:
3520 main.log.exception( self.name + ": Object not as expected" )
3521 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003522 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003523 main.log.error( self.name + ": EOF exception found" )
3524 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003525 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003526 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003527 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003528 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003529
kelvin-onlabd3b64892015-01-20 13:26:24 -08003530 def electionTestRun( self ):
kelvin-onlab898a6c62015-01-16 14:13:53 -08003531 """
Jon Halle3f39ff2015-01-13 11:50:53 -08003532 CLI command to run for leadership of the Election test application.
3533 NOTE: Requires installation of the onos-app-election feature
3534 Returns: Main.TRUE on success
3535 Main.FALSE on error
kelvin-onlab898a6c62015-01-16 14:13:53 -08003536 """
Jon Hall94fd0472014-12-08 11:52:42 -08003537 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003538 cmdStr = "election-test-run"
3539 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003540 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003541 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003542 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003543 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003544 "Election\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003545 search = re.search( successPattern, response )
Jon Hall94fd0472014-12-08 11:52:42 -08003546 if search:
Jon Halle3f39ff2015-01-13 11:50:53 -08003547 main.log.info( self.name + " entering leadership elections " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003548 "for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003549 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003550 # error
Jon Hall0e240372018-05-02 11:21:57 -07003551 main.log.error( self.name + ": Error in electionTestRun on " + self.name +
Jon Hall97cf84a2016-06-20 13:35:58 -07003552 ": " + "unexpected response" )
3553 main.log.error( repr( response ) )
3554 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003555 except AssertionError:
3556 main.log.exception( "" )
3557 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003558 except TypeError:
3559 main.log.exception( self.name + ": Object not as expected" )
3560 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003561 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003562 main.log.error( self.name + ": EOF exception found" )
3563 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003564 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003565 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003566 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003567 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08003568
kelvin-onlabd3b64892015-01-20 13:26:24 -08003569 def electionTestWithdraw( self ):
kelvin8ec71442015-01-15 16:57:00 -08003570 """
Jon Hall94fd0472014-12-08 11:52:42 -08003571 * CLI command to withdraw the local node from leadership election for
3572 * the Election test application.
3573 #NOTE: Requires installation of the onos-app-election feature
3574 Returns: Main.TRUE on success
3575 Main.FALSE on error
kelvin8ec71442015-01-15 16:57:00 -08003576 """
Jon Hall94fd0472014-12-08 11:52:42 -08003577 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003578 cmdStr = "election-test-withdraw"
3579 response = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003580 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003581 assert "Command not found:" not in response, response
kelvin-onlab898a6c62015-01-16 14:13:53 -08003582 # success
Jon Halle3f39ff2015-01-13 11:50:53 -08003583 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\
kelvin-onlab898a6c62015-01-16 14:13:53 -08003584 "\sthe\sElection\sapp."
Jon Halle3f39ff2015-01-13 11:50:53 -08003585 if re.search( successPattern, response ):
3586 main.log.info( self.name + " withdrawing from leadership " +
kelvin-onlab898a6c62015-01-16 14:13:53 -08003587 "elections for the Election app." )
Jon Hall94fd0472014-12-08 11:52:42 -08003588 return main.TRUE
kelvin-onlab898a6c62015-01-16 14:13:53 -08003589 # error
Jon Hall0e240372018-05-02 11:21:57 -07003590 main.log.error( self.name + ": Error in electionTestWithdraw on " +
Jon Hall97cf84a2016-06-20 13:35:58 -07003591 self.name + ": " + "unexpected response" )
3592 main.log.error( repr( response ) )
3593 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08003594 except AssertionError:
3595 main.log.exception( "" )
3596 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003597 except TypeError:
3598 main.log.exception( self.name + ": Object not as expected" )
3599 return main.FALSE
Jon Hall94fd0472014-12-08 11:52:42 -08003600 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003601 main.log.error( self.name + ": EOF exception found" )
3602 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003603 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003604 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003605 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003606 main.cleanAndExit()
Jon Hall1c9e8732014-10-27 19:29:27 -04003607
kelvin8ec71442015-01-15 16:57:00 -08003608 def getDevicePortsEnabledCount( self, dpid ):
3609 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003610 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003611 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003612 try:
Jon Halle3f39ff2015-01-13 11:50:53 -08003613 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003614 cmdStr = "onos:ports -e " + dpid + " | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003615 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003616 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003617 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003618 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003619 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003620 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003621 return output
Jon Hallc6793552016-01-19 14:18:37 -08003622 except AssertionError:
3623 main.log.exception( "" )
3624 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003625 except TypeError:
3626 main.log.exception( self.name + ": Object not as expected" )
3627 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003628 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003629 main.log.error( self.name + ": EOF exception found" )
3630 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003631 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003632 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003633 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003634 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003635
kelvin8ec71442015-01-15 16:57:00 -08003636 def getDeviceLinksActiveCount( self, dpid ):
3637 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003638 Get the count of all enabled ports on a particular device/switch
kelvin8ec71442015-01-15 16:57:00 -08003639 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003640 try:
kelvin-onlab898a6c62015-01-16 14:13:53 -08003641 dpid = str( dpid )
kelvin-onlabd3b64892015-01-20 13:26:24 -08003642 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l"
Jon Halld5a94fb2018-11-13 14:32:23 -08003643 output = self.lineCount( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003644 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003645 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003646 if re.search( "No such device", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003647 main.log.error( self.name + ": Error in getting ports " )
kelvin-onlab898a6c62015-01-16 14:13:53 -08003648 return ( output, "Error " )
Jon Halla495f562016-05-16 18:03:26 -07003649 return output
Jon Hallc6793552016-01-19 14:18:37 -08003650 except AssertionError:
3651 main.log.exception( "" )
3652 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003653 except TypeError:
3654 main.log.exception( self.name + ": Object not as expected" )
3655 return ( output, "Error " )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003656 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003657 main.log.error( self.name + ": EOF exception found" )
3658 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003659 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003660 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003661 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003662 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003663
kelvin8ec71442015-01-15 16:57:00 -08003664 def getAllIntentIds( self ):
3665 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003666 Return a list of all Intent IDs
kelvin8ec71442015-01-15 16:57:00 -08003667 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003668 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08003669 cmdStr = "onos:intents | grep id="
3670 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003671 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003672 assert "Command not found:" not in output, output
Jon Halle3f39ff2015-01-13 11:50:53 -08003673 if re.search( "Error", output ):
Jon Hall0e240372018-05-02 11:21:57 -07003674 main.log.error( self.name + ": Error in getting ports" )
Jon Halle3f39ff2015-01-13 11:50:53 -08003675 return ( output, "Error" )
Jon Halla495f562016-05-16 18:03:26 -07003676 return output
Jon Hallc6793552016-01-19 14:18:37 -08003677 except AssertionError:
3678 main.log.exception( "" )
3679 return None
Jon Halld4d4b372015-01-28 16:02:41 -08003680 except TypeError:
3681 main.log.exception( self.name + ": Object not as expected" )
3682 return ( output, "Error" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003683 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08003684 main.log.error( self.name + ": EOF exception found" )
3685 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003686 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003687 except Exception:
Jon Halld4d4b372015-01-28 16:02:41 -08003688 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003689 main.cleanAndExit()
Jon Halld4d4b372015-01-28 16:02:41 -08003690
Jon Hall73509952015-02-24 16:42:56 -08003691 def intentSummary( self ):
3692 """
Jon Hallefbd9792015-03-05 16:11:36 -08003693 Returns a dictionary containing the current intent states and the count
Jon Hall73509952015-02-24 16:42:56 -08003694 """
3695 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003696 intents = self.intents( )
Jon Hall08f61bc2015-04-13 16:00:30 -07003697 states = []
Jon Hall5aa168b2015-03-23 14:23:09 -07003698 for intent in json.loads( intents ):
Jon Hall08f61bc2015-04-13 16:00:30 -07003699 states.append( intent.get( 'state', None ) )
3700 out = [ ( i, states.count( i ) ) for i in set( states ) ]
Jon Hall63604932015-02-26 17:09:50 -08003701 main.log.info( dict( out ) )
Jon Hall73509952015-02-24 16:42:56 -08003702 return dict( out )
Jon Hallc6793552016-01-19 14:18:37 -08003703 except ( TypeError, ValueError ):
3704 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, intents ) )
Jon Hall73509952015-02-24 16:42:56 -08003705 return None
3706 except pexpect.EOF:
3707 main.log.error( self.name + ": EOF exception found" )
3708 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003709 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08003710 except Exception:
Jon Hall73509952015-02-24 16:42:56 -08003711 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003712 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003713
Jon Hall61282e32015-03-19 11:34:11 -07003714 def leaders( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003715 """
3716 Returns the output of the leaders command.
Jon Hall61282e32015-03-19 11:34:11 -07003717 Optional argument:
3718 * jsonFormat - boolean indicating if you want output in json
Jon Hall63604932015-02-26 17:09:50 -08003719 """
Jon Hall63604932015-02-26 17:09:50 -08003720 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003721 cmdStr = "onos:leaders"
Jon Hall61282e32015-03-19 11:34:11 -07003722 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003723 cmdStr += " -j"
3724 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003725 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003726 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003727 return output
Jon Hallc6793552016-01-19 14:18:37 -08003728 except AssertionError:
3729 main.log.exception( "" )
3730 return None
Jon Hall63604932015-02-26 17:09:50 -08003731 except TypeError:
3732 main.log.exception( self.name + ": Object not as expected" )
3733 return None
Hari Krishnaa43d4e92014-12-19 13:22:40 -08003734 except pexpect.EOF:
3735 main.log.error( self.name + ": EOF exception found" )
3736 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003737 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003738 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003739 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003740 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003741
acsmarsa4a4d1e2015-07-10 16:01:24 -07003742 def leaderCandidates( self, jsonFormat=True ):
3743 """
3744 Returns the output of the leaders -c command.
3745 Optional argument:
3746 * jsonFormat - boolean indicating if you want output in json
3747 """
3748 try:
3749 cmdStr = "onos:leaders -c"
3750 if jsonFormat:
3751 cmdStr += " -j"
3752 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003753 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003754 assert "Command not found:" not in output, output
acsmarsa4a4d1e2015-07-10 16:01:24 -07003755 return output
Jon Hallc6793552016-01-19 14:18:37 -08003756 except AssertionError:
3757 main.log.exception( "" )
3758 return None
acsmarsa4a4d1e2015-07-10 16:01:24 -07003759 except TypeError:
3760 main.log.exception( self.name + ": Object not as expected" )
3761 return None
3762 except pexpect.EOF:
3763 main.log.error( self.name + ": EOF exception found" )
3764 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003765 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003766 except Exception:
3767 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003768 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003769
Jon Hallc6793552016-01-19 14:18:37 -08003770 def specificLeaderCandidate( self, topic ):
acsmarsa4a4d1e2015-07-10 16:01:24 -07003771 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003772 Returns a list in format [leader,candidate1,candidate2,...] for a given
acsmarsa4a4d1e2015-07-10 16:01:24 -07003773 topic parameter and an empty list if the topic doesn't exist
3774 If no leader is elected leader in the returned list will be "none"
3775 Returns None if there is a type error processing the json object
3776 """
3777 try:
Jon Hall6e709752016-02-01 13:38:46 -08003778 cmdStr = "onos:leaders -j"
Jon Hallc6793552016-01-19 14:18:37 -08003779 rawOutput = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003780 assert rawOutput is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003781 assert "Command not found:" not in rawOutput, rawOutput
3782 output = json.loads( rawOutput )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003783 results = []
3784 for dict in output:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003785 if dict[ "topic" ] == topic:
3786 leader = dict[ "leader" ]
3787 candidates = re.split( ", ", dict[ "candidates" ][ 1:-1 ] )
Jon Hallc6793552016-01-19 14:18:37 -08003788 results.append( leader )
3789 results.extend( candidates )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003790 return results
Jon Hallc6793552016-01-19 14:18:37 -08003791 except AssertionError:
3792 main.log.exception( "" )
3793 return None
3794 except ( TypeError, ValueError ):
3795 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawOutput ) )
acsmarsa4a4d1e2015-07-10 16:01:24 -07003796 return None
3797 except pexpect.EOF:
3798 main.log.error( self.name + ": EOF exception found" )
3799 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003800 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003801 except Exception:
3802 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003803 main.cleanAndExit()
acsmarsa4a4d1e2015-07-10 16:01:24 -07003804
Jon Hall61282e32015-03-19 11:34:11 -07003805 def pendingMap( self, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003806 """
3807 Returns the output of the intent Pending map.
3808 """
Jon Hall63604932015-02-26 17:09:50 -08003809 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003810 cmdStr = "onos:intents -p"
Jon Hall61282e32015-03-19 11:34:11 -07003811 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003812 cmdStr += " -j"
3813 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003814 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003815 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003816 return output
Jon Hallc6793552016-01-19 14:18:37 -08003817 except AssertionError:
3818 main.log.exception( "" )
3819 return None
Jon Hall63604932015-02-26 17:09:50 -08003820 except TypeError:
3821 main.log.exception( self.name + ": Object not as expected" )
3822 return None
3823 except pexpect.EOF:
3824 main.log.error( self.name + ": EOF exception found" )
3825 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003826 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003827 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003828 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003829 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003830
Jon Hall2c8959e2016-12-16 12:17:34 -08003831 def partitions( self, candidates=False, jsonFormat=True ):
Jon Hall63604932015-02-26 17:09:50 -08003832 """
3833 Returns the output of the raft partitions command for ONOS.
3834 """
Jon Hall61282e32015-03-19 11:34:11 -07003835 # Sample JSON
3836 # {
3837 # "leader": "tcp://10.128.30.11:7238",
3838 # "members": [
3839 # "tcp://10.128.30.11:7238",
3840 # "tcp://10.128.30.17:7238",
3841 # "tcp://10.128.30.13:7238",
3842 # ],
3843 # "name": "p1",
3844 # "term": 3
3845 # },
Jon Hall63604932015-02-26 17:09:50 -08003846 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003847 cmdStr = "onos:partitions"
Jon Hall2c8959e2016-12-16 12:17:34 -08003848 if candidates:
3849 cmdStr += " -c"
Jon Hall61282e32015-03-19 11:34:11 -07003850 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003851 cmdStr += " -j"
3852 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07003853 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003854 assert "Command not found:" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003855 return output
Jon Hallc6793552016-01-19 14:18:37 -08003856 except AssertionError:
3857 main.log.exception( "" )
3858 return None
Jon Hall63604932015-02-26 17:09:50 -08003859 except TypeError:
3860 main.log.exception( self.name + ": Object not as expected" )
3861 return None
3862 except pexpect.EOF:
3863 main.log.error( self.name + ": EOF exception found" )
3864 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003865 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003866 except Exception:
Jon Hall63604932015-02-26 17:09:50 -08003867 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003868 main.cleanAndExit()
Jon Hall63604932015-02-26 17:09:50 -08003869
Jon Halle9f909e2016-09-23 10:43:12 -07003870 def apps( self, summary=False, active=False, jsonFormat=True ):
Jon Hallbe379602015-03-24 13:39:32 -07003871 """
3872 Returns the output of the apps command for ONOS. This command lists
3873 information about installed ONOS applications
3874 """
3875 # Sample JSON object
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003876 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0",
Jon Hallbe379602015-03-24 13:39:32 -07003877 # "description":"ONOS OpenFlow protocol southbound providers",
3878 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"",
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00003879 # "features":"[onos-openflow]","state":"ACTIVE"}]
Jon Hallbe379602015-03-24 13:39:32 -07003880 try:
Jon Hallc6358dd2015-04-10 12:44:28 -07003881 cmdStr = "onos:apps"
Jon Hallf03ae762019-01-22 13:25:27 -08003882 expectJson = False
Jon Halle9f909e2016-09-23 10:43:12 -07003883 if summary:
3884 cmdStr += " -s"
3885 if active:
3886 cmdStr += " -a"
Jon Hallbe379602015-03-24 13:39:32 -07003887 if jsonFormat:
Jon Hallc6358dd2015-04-10 12:44:28 -07003888 cmdStr += " -j"
Jon Hallf03ae762019-01-22 13:25:27 -08003889 expectJson = True
3890 output = self.sendline( cmdStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07003891 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08003892 assert "Command not found:" not in output, output
3893 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07003894 return output
Jon Hallbe379602015-03-24 13:39:32 -07003895 # FIXME: look at specific exceptions/Errors
3896 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07003897 main.log.exception( self.name + ": Error in processing onos:app command." )
Jon Hallbe379602015-03-24 13:39:32 -07003898 return None
3899 except TypeError:
3900 main.log.exception( self.name + ": Object not as expected" )
3901 return None
3902 except pexpect.EOF:
3903 main.log.error( self.name + ": EOF exception found" )
3904 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003905 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003906 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07003907 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003908 main.cleanAndExit()
Jon Hallbe379602015-03-24 13:39:32 -07003909
You Wangcdc51fe2018-08-12 17:14:56 -07003910 def appStatus( self, appName ):
Jon Hall146f1522015-03-24 15:33:24 -07003911 """
3912 Uses the onos:apps cli command to return the status of an application.
3913 Returns:
3914 "ACTIVE" - If app is installed and activated
3915 "INSTALLED" - If app is installed and deactivated
3916 "UNINSTALLED" - If app is not installed
3917 None - on error
3918 """
Jon Hall146f1522015-03-24 15:33:24 -07003919 try:
3920 if not isinstance( appName, types.StringType ):
3921 main.log.error( self.name + ".appStatus(): appName must be" +
3922 " a string" )
3923 return None
3924 output = self.apps( jsonFormat=True )
3925 appsJson = json.loads( output )
3926 state = None
3927 for app in appsJson:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003928 if appName == app.get( 'name' ):
3929 state = app.get( 'state' )
Jon Hall146f1522015-03-24 15:33:24 -07003930 break
3931 if state == "ACTIVE" or state == "INSTALLED":
3932 return state
3933 elif state is None:
You Wang0d9f2c02018-08-10 14:56:32 -07003934 main.log.warn( "{} app not found".format( appName ) )
Jon Hall146f1522015-03-24 15:33:24 -07003935 return "UNINSTALLED"
3936 elif state:
3937 main.log.error( "Unexpected state from 'onos:apps': " +
3938 str( state ) )
3939 return state
Jon Hallc6793552016-01-19 14:18:37 -08003940 except ( TypeError, ValueError ):
3941 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003942 return None
3943 except pexpect.EOF:
3944 main.log.error( self.name + ": EOF exception found" )
3945 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07003946 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07003947 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07003948 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07003949 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07003950
Jon Hallbe379602015-03-24 13:39:32 -07003951 def app( self, appName, option ):
3952 """
3953 Interacts with the app command for ONOS. This command manages
3954 application inventory.
3955 """
Jon Hallbe379602015-03-24 13:39:32 -07003956 try:
Jon Hallbd16b922015-03-26 17:53:15 -07003957 # Validate argument types
3958 valid = True
3959 if not isinstance( appName, types.StringType ):
3960 main.log.error( self.name + ".app(): appName must be a " +
3961 "string" )
3962 valid = False
3963 if not isinstance( option, types.StringType ):
3964 main.log.error( self.name + ".app(): option must be a string" )
3965 valid = False
3966 if not valid:
3967 return main.FALSE
3968 # Validate Option
3969 option = option.lower()
3970 # NOTE: Install may become a valid option
3971 if option == "activate":
3972 pass
3973 elif option == "deactivate":
3974 pass
3975 elif option == "uninstall":
3976 pass
3977 else:
3978 # Invalid option
3979 main.log.error( "The ONOS app command argument only takes " +
3980 "the values: (activate|deactivate|uninstall)" +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07003981 "; was given '" + option + "'" )
Jon Hallbd16b922015-03-26 17:53:15 -07003982 return main.FALSE
Jon Hall146f1522015-03-24 15:33:24 -07003983 cmdStr = "onos:app " + option + " " + appName
Jon Hallbe379602015-03-24 13:39:32 -07003984 output = self.sendline( cmdStr )
You Wangb5a55f72017-03-03 12:51:05 -08003985 assert output is not None, "Error in sendline"
3986 assert "Command not found:" not in output, output
Jon Hallbe379602015-03-24 13:39:32 -07003987 if "Error executing command" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003988 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hallbe379602015-03-24 13:39:32 -07003989 str( output ) )
Jon Hall146f1522015-03-24 15:33:24 -07003990 return main.FALSE
Jon Hallbe379602015-03-24 13:39:32 -07003991 elif "No such application" in output:
3992 main.log.error( "The application '" + appName +
3993 "' is not installed in ONOS" )
Jon Hall146f1522015-03-24 15:33:24 -07003994 return main.FALSE
3995 elif "Command not found:" in output:
Jon Hall0e240372018-05-02 11:21:57 -07003996 main.log.error( self.name + ": Error in processing onos:app command: " +
Jon Hall146f1522015-03-24 15:33:24 -07003997 str( output ) )
3998 return main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07003999 elif "Unsupported command:" in output:
4000 main.log.error( "Incorrect command given to 'app': " +
4001 str( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07004002 # NOTE: we may need to add more checks here
Jon Hallbd16b922015-03-26 17:53:15 -07004003 # else: Command was successful
Jon Hall08f61bc2015-04-13 16:00:30 -07004004 # main.log.debug( "app response: " + repr( output ) )
Jon Hallbe379602015-03-24 13:39:32 -07004005 return main.TRUE
You Wangb5a55f72017-03-03 12:51:05 -08004006 except AssertionError:
4007 main.log.exception( self.name + ": AssertionError exception found" )
4008 return main.ERROR
Jon Hallbe379602015-03-24 13:39:32 -07004009 except TypeError:
4010 main.log.exception( self.name + ": Object not as expected" )
4011 return main.ERROR
4012 except pexpect.EOF:
4013 main.log.error( self.name + ": EOF exception found" )
4014 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004015 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004016 except Exception:
Jon Hallbe379602015-03-24 13:39:32 -07004017 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004018 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004019
Jon Hallbd16b922015-03-26 17:53:15 -07004020 def activateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004021 """
4022 Activate an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004023 appName is the hierarchical app name, not the feature name
4024 If check is True, method will check the status of the app after the
4025 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004026 Returns main.TRUE if the command was successfully sent
4027 main.FALSE if the cli responded with an error or given
4028 incorrect input
4029 """
4030 try:
4031 if not isinstance( appName, types.StringType ):
4032 main.log.error( self.name + ".activateApp(): appName must be" +
4033 " a string" )
4034 return main.FALSE
4035 status = self.appStatus( appName )
4036 if status == "INSTALLED":
4037 response = self.app( appName, "activate" )
Jon Hallbd16b922015-03-26 17:53:15 -07004038 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004039 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004040 status = self.appStatus( appName )
4041 if status == "ACTIVE":
4042 return main.TRUE
4043 else:
Jon Hall050e1bd2015-03-30 13:33:02 -07004044 main.log.debug( "The state of application " +
4045 appName + " is " + status )
Jon Hallbd16b922015-03-26 17:53:15 -07004046 time.sleep( 1 )
4047 return main.FALSE
4048 else: # not 'check' or command didn't succeed
4049 return response
Jon Hall146f1522015-03-24 15:33:24 -07004050 elif status == "ACTIVE":
4051 return main.TRUE
4052 elif status == "UNINSTALLED":
4053 main.log.error( self.name + ": Tried to activate the " +
4054 "application '" + appName + "' which is not " +
4055 "installed." )
4056 else:
4057 main.log.error( "Unexpected return value from appStatus: " +
4058 str( status ) )
4059 return main.ERROR
4060 except TypeError:
4061 main.log.exception( self.name + ": Object not as expected" )
4062 return main.ERROR
4063 except pexpect.EOF:
4064 main.log.error( self.name + ": EOF exception found" )
4065 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004066 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004067 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004068 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004069 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004070
Jon Hallbd16b922015-03-26 17:53:15 -07004071 def deactivateApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004072 """
4073 Deactivate an app that is already activated in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004074 appName is the hierarchical app name, not the feature name
4075 If check is True, method will check the status of the app after the
4076 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004077 Returns main.TRUE if the command was successfully sent
4078 main.FALSE if the cli responded with an error or given
4079 incorrect input
4080 """
4081 try:
4082 if not isinstance( appName, types.StringType ):
4083 main.log.error( self.name + ".deactivateApp(): appName must " +
4084 "be a string" )
4085 return main.FALSE
4086 status = self.appStatus( appName )
4087 if status == "INSTALLED":
4088 return main.TRUE
4089 elif status == "ACTIVE":
4090 response = self.app( appName, "deactivate" )
Jon Hallbd16b922015-03-26 17:53:15 -07004091 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004092 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004093 status = self.appStatus( appName )
4094 if status == "INSTALLED":
4095 return main.TRUE
4096 else:
4097 time.sleep( 1 )
4098 return main.FALSE
4099 else: # not check or command didn't succeed
4100 return response
Jon Hall146f1522015-03-24 15:33:24 -07004101 elif status == "UNINSTALLED":
4102 main.log.warn( self.name + ": Tried to deactivate the " +
4103 "application '" + appName + "' which is not " +
4104 "installed." )
4105 return main.TRUE
4106 else:
4107 main.log.error( "Unexpected return value from appStatus: " +
4108 str( status ) )
4109 return main.ERROR
4110 except TypeError:
4111 main.log.exception( self.name + ": Object not as expected" )
4112 return main.ERROR
4113 except pexpect.EOF:
4114 main.log.error( self.name + ": EOF exception found" )
4115 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004116 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004117 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004118 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004119 main.cleanAndExit()
Jon Hall146f1522015-03-24 15:33:24 -07004120
Jon Hallbd16b922015-03-26 17:53:15 -07004121 def uninstallApp( self, appName, check=True ):
Jon Hall146f1522015-03-24 15:33:24 -07004122 """
4123 Uninstall an app that is already installed in ONOS
Jon Hallbd16b922015-03-26 17:53:15 -07004124 appName is the hierarchical app name, not the feature name
4125 If check is True, method will check the status of the app after the
4126 command is issued
Jon Hall146f1522015-03-24 15:33:24 -07004127 Returns main.TRUE if the command was successfully sent
4128 main.FALSE if the cli responded with an error or given
4129 incorrect input
4130 """
4131 # TODO: check with Thomas about the state machine for apps
4132 try:
4133 if not isinstance( appName, types.StringType ):
4134 main.log.error( self.name + ".uninstallApp(): appName must " +
4135 "be a string" )
4136 return main.FALSE
4137 status = self.appStatus( appName )
4138 if status == "INSTALLED":
4139 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004140 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004141 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004142 status = self.appStatus( appName )
4143 if status == "UNINSTALLED":
4144 return main.TRUE
4145 else:
4146 time.sleep( 1 )
4147 return main.FALSE
4148 else: # not check or command didn't succeed
4149 return response
Jon Hall146f1522015-03-24 15:33:24 -07004150 elif status == "ACTIVE":
4151 main.log.warn( self.name + ": Tried to uninstall the " +
4152 "application '" + appName + "' which is " +
4153 "currently active." )
4154 response = self.app( appName, "uninstall" )
Jon Hallbd16b922015-03-26 17:53:15 -07004155 if check and response == main.TRUE:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004156 for i in range( 10 ): # try 10 times then give up
Jon Hallbd16b922015-03-26 17:53:15 -07004157 status = self.appStatus( appName )
4158 if status == "UNINSTALLED":
4159 return main.TRUE
4160 else:
4161 time.sleep( 1 )
4162 return main.FALSE
4163 else: # not check or command didn't succeed
4164 return response
Jon Hall146f1522015-03-24 15:33:24 -07004165 elif status == "UNINSTALLED":
4166 return main.TRUE
4167 else:
4168 main.log.error( "Unexpected return value from appStatus: " +
4169 str( status ) )
4170 return main.ERROR
4171 except TypeError:
4172 main.log.exception( self.name + ": Object not as expected" )
4173 return main.ERROR
4174 except pexpect.EOF:
4175 main.log.error( self.name + ": EOF exception found" )
4176 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004177 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004178 except Exception:
Jon Hall146f1522015-03-24 15:33:24 -07004179 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004180 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004181
4182 def appIDs( self, jsonFormat=True ):
4183 """
4184 Show the mappings between app id and app names given by the 'app-ids'
4185 cli command
4186 """
4187 try:
4188 cmdStr = "app-ids"
4189 if jsonFormat:
4190 cmdStr += " -j"
Jon Hallc6358dd2015-04-10 12:44:28 -07004191 output = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004192 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004193 assert "Command not found:" not in output, output
4194 assert "Error executing command" not in output, output
Jon Hallc6358dd2015-04-10 12:44:28 -07004195 return output
Jon Hallbd16b922015-03-26 17:53:15 -07004196 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004197 main.log.exception( self.name + ": Error in processing onos:app-ids command." )
Jon Hallbd16b922015-03-26 17:53:15 -07004198 return None
4199 except TypeError:
4200 main.log.exception( self.name + ": Object not as expected" )
4201 return None
4202 except pexpect.EOF:
4203 main.log.error( self.name + ": EOF exception found" )
4204 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004205 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004206 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004207 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004208 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004209
4210 def appToIDCheck( self ):
4211 """
4212 This method will check that each application's ID listed in 'apps' is
4213 the same as the ID listed in 'app-ids'. The check will also check that
4214 there are no duplicate IDs issued. Note that an app ID should be
4215 a globaly unique numerical identifier for app/app-like features. Once
4216 an ID is registered, the ID is never freed up so that if an app is
4217 reinstalled it will have the same ID.
4218
4219 Returns: main.TRUE if the check passes and
4220 main.FALSE if the check fails or
4221 main.ERROR if there is some error in processing the test
4222 """
4223 try:
Jon Hall0e240372018-05-02 11:21:57 -07004224 # Grab IDs
Jon Hallc6793552016-01-19 14:18:37 -08004225 rawJson = self.appIDs( jsonFormat=True )
4226 if rawJson:
4227 ids = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004228 else:
Jon Hall0e240372018-05-02 11:21:57 -07004229 main.log.error( "app-ids returned nothing: " + repr( rawJson ) )
4230 return main.FALSE
4231
4232 # Grab Apps
Jon Hallc6793552016-01-19 14:18:37 -08004233 rawJson = self.apps( jsonFormat=True )
4234 if rawJson:
4235 apps = json.loads( rawJson )
Jon Hall390696c2015-05-05 17:13:41 -07004236 else:
Jon Hallc6793552016-01-19 14:18:37 -08004237 main.log.error( "apps returned nothing:" + repr( rawJson ) )
Jon Hall390696c2015-05-05 17:13:41 -07004238 return main.FALSE
Jon Hall0e240372018-05-02 11:21:57 -07004239
Jon Hallbd16b922015-03-26 17:53:15 -07004240 result = main.TRUE
4241 for app in apps:
4242 appID = app.get( 'id' )
4243 if appID is None:
4244 main.log.error( "Error parsing app: " + str( app ) )
4245 result = main.FALSE
4246 appName = app.get( 'name' )
4247 if appName is None:
4248 main.log.error( "Error parsing app: " + str( app ) )
4249 result = main.FALSE
4250 # get the entry in ids that has the same appID
Jon Hall390696c2015-05-05 17:13:41 -07004251 current = filter( lambda item: item[ 'id' ] == appID, ids )
Jon Hallbd16b922015-03-26 17:53:15 -07004252 if not current: # if ids doesn't have this id
4253 result = main.FALSE
4254 main.log.error( "'app-ids' does not have the ID for " +
4255 str( appName ) + " that apps does." )
Jon Hallb9d381e2018-02-05 12:02:10 -08004256 main.log.debug( "apps command returned: " + str( app ) +
4257 "; app-ids has: " + str( ids ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004258 elif len( current ) > 1:
4259 # there is more than one app with this ID
4260 result = main.FALSE
4261 # We will log this later in the method
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004262 elif not current[ 0 ][ 'name' ] == appName:
4263 currentName = current[ 0 ][ 'name' ]
Jon Hallbd16b922015-03-26 17:53:15 -07004264 result = main.FALSE
4265 main.log.error( "'app-ids' has " + str( currentName ) +
4266 " registered under id:" + str( appID ) +
4267 " but 'apps' has " + str( appName ) )
4268 else:
4269 pass # id and name match!
Jon Hall0e240372018-05-02 11:21:57 -07004270
Jon Hallbd16b922015-03-26 17:53:15 -07004271 # now make sure that app-ids has no duplicates
4272 idsList = []
4273 namesList = []
4274 for item in ids:
4275 idsList.append( item[ 'id' ] )
4276 namesList.append( item[ 'name' ] )
4277 if len( idsList ) != len( set( idsList ) ) or\
4278 len( namesList ) != len( set( namesList ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004279 main.log.error( "'app-ids' has some duplicate entries: \n"
4280 + json.dumps( ids,
4281 sort_keys=True,
4282 indent=4,
4283 separators=( ',', ': ' ) ) )
4284 result = main.FALSE
Jon Hallbd16b922015-03-26 17:53:15 -07004285 return result
Jon Hallc6793552016-01-19 14:18:37 -08004286 except ( TypeError, ValueError ):
4287 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawJson ) )
Jon Hallbd16b922015-03-26 17:53:15 -07004288 return main.ERROR
4289 except pexpect.EOF:
4290 main.log.error( self.name + ": EOF exception found" )
4291 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004292 main.cleanAndExit()
Jon Hall77ba41c2015-04-06 10:25:40 -07004293 except Exception:
Jon Hallbd16b922015-03-26 17:53:15 -07004294 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004295 main.cleanAndExit()
Jon Hallbd16b922015-03-26 17:53:15 -07004296
Jon Hallfb760a02015-04-13 15:35:03 -07004297 def getCfg( self, component=None, propName=None, short=False,
4298 jsonFormat=True ):
4299 """
4300 Get configuration settings from onos cli
4301 Optional arguments:
4302 component - Optionally only list configurations for a specific
4303 component. If None, all components with configurations
4304 are displayed. Case Sensitive string.
4305 propName - If component is specified, propName option will show
4306 only this specific configuration from that component.
4307 Case Sensitive string.
4308 jsonFormat - Returns output as json. Note that this will override
4309 the short option
4310 short - Short, less verbose, version of configurations.
4311 This is overridden by the json option
4312 returns:
4313 Output from cli as a string or None on error
4314 """
4315 try:
4316 baseStr = "cfg"
4317 cmdStr = " get"
4318 componentStr = ""
4319 if component:
4320 componentStr += " " + component
4321 if propName:
4322 componentStr += " " + propName
4323 if jsonFormat:
4324 baseStr += " -j"
Jon Hall22e94ce2019-01-15 14:52:17 -08004325 expectJson = True
Jon Hallfb760a02015-04-13 15:35:03 -07004326 elif short:
4327 baseStr += " -s"
Jon Hall22e94ce2019-01-15 14:52:17 -08004328 expectJson = False
4329 output = self.sendline( baseStr + cmdStr + componentStr, expectJson=expectJson )
Jon Halla495f562016-05-16 18:03:26 -07004330 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004331 assert "Command not found:" not in output, output
4332 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004333 return output
4334 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004335 main.log.exception( self.name + ": Error in processing 'cfg get' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004336 return None
4337 except TypeError:
4338 main.log.exception( self.name + ": Object not as expected" )
4339 return None
4340 except pexpect.EOF:
4341 main.log.error( self.name + ": EOF exception found" )
4342 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004343 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004344 except Exception:
4345 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004346 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004347
4348 def setCfg( self, component, propName, value=None, check=True ):
4349 """
4350 Set/Unset configuration settings from ONOS cli
Jon Hall390696c2015-05-05 17:13:41 -07004351 Required arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004352 component - The case sensitive name of the component whose
4353 property is to be set
4354 propName - The case sensitive name of the property to be set/unset
Jon Hall390696c2015-05-05 17:13:41 -07004355 Optional arguments:
Jon Hallfb760a02015-04-13 15:35:03 -07004356 value - The value to set the property to. If None, will unset the
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004357 property and revert it to it's default value(if applicable)
Jon Hallfb760a02015-04-13 15:35:03 -07004358 check - Boolean, Check whether the option was successfully set this
4359 only applies when a value is given.
4360 returns:
4361 main.TRUE on success or main.FALSE on failure. If check is False,
4362 will return main.TRUE unless there is an error
4363 """
4364 try:
4365 baseStr = "cfg"
4366 cmdStr = " set " + str( component ) + " " + str( propName )
4367 if value is not None:
4368 cmdStr += " " + str( value )
4369 output = self.sendline( baseStr + cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07004370 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004371 assert "Command not found:" not in output, output
4372 assert "Error executing command" not in output, output
Jon Hallfb760a02015-04-13 15:35:03 -07004373 if value and check:
4374 results = self.getCfg( component=str( component ),
4375 propName=str( propName ),
4376 jsonFormat=True )
4377 # Check if current value is what we just set
4378 try:
4379 jsonOutput = json.loads( results )
4380 current = jsonOutput[ 'value' ]
Jon Hallc6793552016-01-19 14:18:37 -08004381 except ( TypeError, ValueError ):
Jon Hallfb760a02015-04-13 15:35:03 -07004382 main.log.exception( "Error parsing cfg output" )
4383 main.log.error( "output:" + repr( results ) )
4384 return main.FALSE
4385 if current == str( value ):
4386 return main.TRUE
4387 return main.FALSE
4388 return main.TRUE
4389 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004390 main.log.exception( self.name + ": Error in processing 'cfg set' command." )
Jon Hallfb760a02015-04-13 15:35:03 -07004391 return main.FALSE
Jon Hallc6793552016-01-19 14:18:37 -08004392 except ( TypeError, ValueError ):
4393 main.log.exception( "{}: Object not as expected: {!r}".format( self.name, results ) )
Jon Hallfb760a02015-04-13 15:35:03 -07004394 return main.FALSE
4395 except pexpect.EOF:
4396 main.log.error( self.name + ": EOF exception found" )
4397 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004398 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004399 except Exception:
4400 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004401 main.cleanAndExit()
Jon Hallfb760a02015-04-13 15:35:03 -07004402
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004403 def distPrimitivesSend( self, cmd ):
4404 """
4405 Function to handle sending cli commands for the distributed primitives test app
4406
4407 This command will catch some exceptions and retry the command on some
4408 specific store exceptions.
4409
4410 Required arguments:
4411 cmd - The command to send to the cli
4412 returns:
4413 string containing the cli output
4414 None on Error
4415 """
4416 try:
4417 output = self.sendline( cmd )
4418 try:
4419 assert output is not None, "Error in sendline"
4420 # TODO: Maybe make this less hardcoded
4421 # ConsistentMap Exceptions
4422 assert "org.onosproject.store.service" not in output
4423 # Node not leader
4424 assert "java.lang.IllegalStateException" not in output
4425 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004426 main.log.error( self.name + ": Error in processing '" + cmd + "' " +
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004427 "command: " + str( output ) )
4428 retryTime = 30 # Conservative time, given by Madan
4429 main.log.info( "Waiting " + str( retryTime ) +
4430 "seconds before retrying." )
4431 time.sleep( retryTime ) # Due to change in mastership
4432 output = self.sendline( cmd )
4433 assert output is not None, "Error in sendline"
4434 assert "Command not found:" not in output, output
4435 assert "Error executing command" not in output, output
4436 main.log.info( self.name + ": " + output )
4437 return output
4438 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004439 main.log.exception( self.name + ": Error in processing '" + cmd + "' command." )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004440 return None
4441 except TypeError:
4442 main.log.exception( self.name + ": Object not as expected" )
4443 return None
4444 except pexpect.EOF:
4445 main.log.error( self.name + ": EOF exception found" )
4446 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004447 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004448 except Exception:
4449 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004450 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004451
Jon Hall390696c2015-05-05 17:13:41 -07004452 def setTestAdd( self, setName, values ):
4453 """
4454 CLI command to add elements to a distributed set.
4455 Arguments:
4456 setName - The name of the set to add to.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004457 values - The value(s) to add to the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004458 Example usages:
4459 setTestAdd( "set1", "a b c" )
4460 setTestAdd( "set2", "1" )
4461 returns:
4462 main.TRUE on success OR
4463 main.FALSE if elements were already in the set OR
4464 main.ERROR on error
4465 """
4466 try:
4467 cmdStr = "set-test-add " + str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004468 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004469 positiveMatch = "\[(.*)\] was added to the set " + str( setName )
4470 negativeMatch = "\[(.*)\] was already in set " + str( setName )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004471 if re.search( positiveMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004472 return main.TRUE
Jeremy Ronquillo82705492017-10-18 14:19:55 -07004473 elif re.search( negativeMatch, output ):
Jon Hall390696c2015-05-05 17:13:41 -07004474 return main.FALSE
4475 else:
4476 main.log.error( self.name + ": setTestAdd did not" +
4477 " match expected output" )
Jon Hall390696c2015-05-05 17:13:41 -07004478 main.log.debug( self.name + " actual: " + repr( output ) )
4479 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004480 except TypeError:
4481 main.log.exception( self.name + ": Object not as expected" )
4482 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004483 except Exception:
4484 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004485 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004486
4487 def setTestRemove( self, setName, values, clear=False, retain=False ):
4488 """
4489 CLI command to remove elements from a distributed set.
4490 Required arguments:
4491 setName - The name of the set to remove from.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004492 values - The value(s) to remove from the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004493 Optional arguments:
4494 clear - Clear all elements from the set
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004495 retain - Retain only the given values. (intersection of the
4496 original set and the given set)
Jon Hall390696c2015-05-05 17:13:41 -07004497 returns:
4498 main.TRUE on success OR
4499 main.FALSE if the set was not changed OR
4500 main.ERROR on error
4501 """
4502 try:
4503 cmdStr = "set-test-remove "
4504 if clear:
4505 cmdStr += "-c " + str( setName )
4506 elif retain:
4507 cmdStr += "-r " + str( setName ) + " " + str( values )
4508 else:
4509 cmdStr += str( setName ) + " " + str( values )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004510 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004511 if clear:
4512 pattern = "Set " + str( setName ) + " cleared"
4513 if re.search( pattern, output ):
4514 return main.TRUE
4515 elif retain:
4516 positivePattern = str( setName ) + " was pruned to contain " +\
4517 "only elements of set \[(.*)\]"
4518 negativePattern = str( setName ) + " was not changed by " +\
4519 "retaining only elements of the set " +\
4520 "\[(.*)\]"
4521 if re.search( positivePattern, output ):
4522 return main.TRUE
4523 elif re.search( negativePattern, output ):
4524 return main.FALSE
4525 else:
4526 positivePattern = "\[(.*)\] was removed from the set " +\
4527 str( setName )
4528 if ( len( values.split() ) == 1 ):
4529 negativePattern = "\[(.*)\] was not in set " +\
4530 str( setName )
4531 else:
4532 negativePattern = "No element of \[(.*)\] was in set " +\
4533 str( setName )
4534 if re.search( positivePattern, output ):
4535 return main.TRUE
4536 elif re.search( negativePattern, output ):
4537 return main.FALSE
4538 main.log.error( self.name + ": setTestRemove did not" +
4539 " match expected output" )
4540 main.log.debug( self.name + " expected: " + pattern )
4541 main.log.debug( self.name + " actual: " + repr( output ) )
4542 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004543 except TypeError:
4544 main.log.exception( self.name + ": Object not as expected" )
4545 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004546 except Exception:
4547 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004548 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004549
4550 def setTestGet( self, setName, values="" ):
4551 """
4552 CLI command to get the elements in a distributed set.
4553 Required arguments:
4554 setName - The name of the set to remove from.
4555 Optional arguments:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004556 values - The value(s) to check if in the set, space seperated.
Jon Hall390696c2015-05-05 17:13:41 -07004557 returns:
4558 main.ERROR on error OR
4559 A list of elements in the set if no optional arguments are
4560 supplied OR
4561 A tuple containing the list then:
4562 main.FALSE if the given values are not in the set OR
4563 main.TRUE if the given values are in the set OR
4564 """
4565 try:
4566 values = str( values ).strip()
4567 setName = str( setName ).strip()
4568 length = len( values.split() )
4569 containsCheck = None
4570 # Patterns to match
4571 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004572 pattern = "Items in set " + setName + ":\r\n" + setPattern
Jon Hall390696c2015-05-05 17:13:41 -07004573 containsTrue = "Set " + setName + " contains the value " + values
4574 containsFalse = "Set " + setName + " did not contain the value " +\
4575 values
4576 containsAllTrue = "Set " + setName + " contains the the subset " +\
4577 setPattern
4578 containsAllFalse = "Set " + setName + " did not contain the the" +\
4579 " subset " + setPattern
4580
4581 cmdStr = "set-test-get "
4582 cmdStr += setName + " " + values
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004583 output = self.distPrimitivesSend( cmdStr )
Jon Hall390696c2015-05-05 17:13:41 -07004584 if length == 0:
4585 match = re.search( pattern, output )
4586 else: # if given values
4587 if length == 1: # Contains output
Jon Hall54b994f2016-12-05 10:48:59 -08004588 patternTrue = pattern + "\r\n" + containsTrue
4589 patternFalse = pattern + "\r\n" + containsFalse
Jon Hall390696c2015-05-05 17:13:41 -07004590 else: # ContainsAll output
Jon Hall54b994f2016-12-05 10:48:59 -08004591 patternTrue = pattern + "\r\n" + containsAllTrue
4592 patternFalse = pattern + "\r\n" + containsAllFalse
Jon Hall390696c2015-05-05 17:13:41 -07004593 matchTrue = re.search( patternTrue, output )
4594 matchFalse = re.search( patternFalse, output )
4595 if matchTrue:
4596 containsCheck = main.TRUE
4597 match = matchTrue
4598 elif matchFalse:
4599 containsCheck = main.FALSE
4600 match = matchFalse
4601 else:
Jon Halle0f0b342017-04-18 11:43:47 -07004602 main.log.error( self.name + " setTestGet did not match " +
Jon Hall390696c2015-05-05 17:13:41 -07004603 "expected output" )
4604 main.log.debug( self.name + " expected: " + pattern )
4605 main.log.debug( self.name + " actual: " + repr( output ) )
4606 match = None
4607 if match:
4608 setMatch = match.group( 1 )
4609 if setMatch == '':
4610 setList = []
4611 else:
4612 setList = setMatch.split( ", " )
4613 if length > 0:
4614 return ( setList, containsCheck )
4615 else:
4616 return setList
4617 else: # no match
4618 main.log.error( self.name + ": setTestGet did not" +
4619 " match expected output" )
4620 main.log.debug( self.name + " expected: " + pattern )
4621 main.log.debug( self.name + " actual: " + repr( output ) )
4622 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004623 except TypeError:
4624 main.log.exception( self.name + ": Object not as expected" )
4625 return main.ERROR
Jon Hall390696c2015-05-05 17:13:41 -07004626 except Exception:
4627 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004628 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004629
4630 def setTestSize( self, setName ):
4631 """
4632 CLI command to get the elements in a distributed set.
4633 Required arguments:
4634 setName - The name of the set to remove from.
4635 returns:
Jon Hallfeff3082015-05-19 10:23:26 -07004636 The integer value of the size returned or
Jon Hall390696c2015-05-05 17:13:41 -07004637 None on error
4638 """
4639 try:
4640 # TODO: Should this check against the number of elements returned
4641 # and then return true/false based on that?
4642 setName = str( setName ).strip()
4643 # Patterns to match
4644 setPattern = "\[(.*)\]"
Jon Hall67253832016-12-05 09:47:13 -08004645 pattern = "There are (\d+) items in set " + setName + ":\r\n" +\
Jon Hall390696c2015-05-05 17:13:41 -07004646 setPattern
4647 cmdStr = "set-test-get -s "
4648 cmdStr += setName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004649 output = self.distPrimitivesSend( cmdStr )
Jon Hall0e240372018-05-02 11:21:57 -07004650 if output:
4651 match = re.search( pattern, output )
4652 if match:
4653 setSize = int( match.group( 1 ) )
4654 setMatch = match.group( 2 )
4655 if len( setMatch.split() ) == setSize:
4656 main.log.info( "The size returned by " + self.name +
4657 " matches the number of elements in " +
4658 "the returned set" )
4659 else:
4660 main.log.error( "The size returned by " + self.name +
4661 " does not match the number of " +
4662 "elements in the returned set." )
4663 return setSize
Jon Hall390696c2015-05-05 17:13:41 -07004664 else: # no match
4665 main.log.error( self.name + ": setTestGet did not" +
4666 " match expected output" )
4667 main.log.debug( self.name + " expected: " + pattern )
4668 main.log.debug( self.name + " actual: " + repr( output ) )
4669 return None
Jon Hall390696c2015-05-05 17:13:41 -07004670 except TypeError:
4671 main.log.exception( self.name + ": Object not as expected" )
4672 return None
Jon Hall390696c2015-05-05 17:13:41 -07004673 except Exception:
4674 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004675 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004676
Jon Hall80daded2015-05-27 16:07:00 -07004677 def counters( self, jsonFormat=True ):
Jon Hall390696c2015-05-05 17:13:41 -07004678 """
4679 Command to list the various counters in the system.
4680 returns:
Jon Hall80daded2015-05-27 16:07:00 -07004681 if jsonFormat, a string of the json object returned by the cli
4682 command
4683 if not jsonFormat, the normal string output of the cli command
Jon Hall390696c2015-05-05 17:13:41 -07004684 None on error
4685 """
Jon Hall390696c2015-05-05 17:13:41 -07004686 try:
Jon Hall390696c2015-05-05 17:13:41 -07004687 cmdStr = "counters"
Jon Hall80daded2015-05-27 16:07:00 -07004688 if jsonFormat:
4689 cmdStr += " -j"
Jon Hall390696c2015-05-05 17:13:41 -07004690 output = self.sendline( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004691 main.log.debug( self.name + ": Counters unparsed: " + output )
4692 output = output.split( "\r\n" )[ -1 ]
4693 main.log.debug( self.name + ": Counters parsed: " + output )
Jon Halla495f562016-05-16 18:03:26 -07004694 assert output is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004695 assert "Command not found:" not in output, output
4696 assert "Error executing command" not in output, output
Jon Hall390696c2015-05-05 17:13:41 -07004697 main.log.info( self.name + ": " + output )
Jon Hall80daded2015-05-27 16:07:00 -07004698 return output
Jon Hall390696c2015-05-05 17:13:41 -07004699 except AssertionError:
Jon Hall0e240372018-05-02 11:21:57 -07004700 main.log.exception( self.name + ": Error in processing 'counters' command." )
Jon Hall80daded2015-05-27 16:07:00 -07004701 return None
Jon Hall390696c2015-05-05 17:13:41 -07004702 except TypeError:
4703 main.log.exception( self.name + ": Object not as expected" )
Jon Hall80daded2015-05-27 16:07:00 -07004704 return None
Jon Hall390696c2015-05-05 17:13:41 -07004705 except pexpect.EOF:
4706 main.log.error( self.name + ": EOF exception found" )
4707 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004708 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004709 except Exception:
4710 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004711 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004712
Jon Hall935db192016-04-19 00:22:04 -07004713 def counterTestAddAndGet( self, counter, delta=1 ):
Jon Hall390696c2015-05-05 17:13:41 -07004714 """
Jon Halle1a3b752015-07-22 13:02:46 -07004715 CLI command to add a delta to then get a distributed counter.
Jon Hall390696c2015-05-05 17:13:41 -07004716 Required arguments:
4717 counter - The name of the counter to increment.
4718 Optional arguments:
Jon Halle1a3b752015-07-22 13:02:46 -07004719 delta - The long to add to the counter
Jon Hall390696c2015-05-05 17:13:41 -07004720 returns:
4721 integer value of the counter or
4722 None on Error
4723 """
4724 try:
4725 counter = str( counter )
Jon Halle1a3b752015-07-22 13:02:46 -07004726 delta = int( delta )
Jon Hall390696c2015-05-05 17:13:41 -07004727 cmdStr = "counter-test-increment "
Jon Hall390696c2015-05-05 17:13:41 -07004728 cmdStr += counter
Jon Halle1a3b752015-07-22 13:02:46 -07004729 if delta != 1:
4730 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004731 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004732 pattern = counter + " was updated to (-?\d+)"
Jon Hall390696c2015-05-05 17:13:41 -07004733 match = re.search( pattern, output )
4734 if match:
4735 return int( match.group( 1 ) )
4736 else:
Jon Halle1a3b752015-07-22 13:02:46 -07004737 main.log.error( self.name + ": counterTestAddAndGet did not" +
Jon Hall390696c2015-05-05 17:13:41 -07004738 " match expected output." )
4739 main.log.debug( self.name + " expected: " + pattern )
4740 main.log.debug( self.name + " actual: " + repr( output ) )
4741 return None
Jon Hall390696c2015-05-05 17:13:41 -07004742 except TypeError:
4743 main.log.exception( self.name + ": Object not as expected" )
4744 return None
Jon Hall390696c2015-05-05 17:13:41 -07004745 except Exception:
4746 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004747 main.cleanAndExit()
Jon Hall390696c2015-05-05 17:13:41 -07004748
Jon Hall935db192016-04-19 00:22:04 -07004749 def counterTestGetAndAdd( self, counter, delta=1 ):
Jon Halle1a3b752015-07-22 13:02:46 -07004750 """
4751 CLI command to get a distributed counter then add a delta to it.
4752 Required arguments:
4753 counter - The name of the counter to increment.
4754 Optional arguments:
4755 delta - The long to add to the counter
Jon Halle1a3b752015-07-22 13:02:46 -07004756 returns:
4757 integer value of the counter or
4758 None on Error
4759 """
4760 try:
4761 counter = str( counter )
4762 delta = int( delta )
4763 cmdStr = "counter-test-increment -g "
Jon Halle1a3b752015-07-22 13:02:46 -07004764 cmdStr += counter
4765 if delta != 1:
4766 cmdStr += " " + str( delta )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004767 output = self.distPrimitivesSend( cmdStr )
Jon Halle1a3b752015-07-22 13:02:46 -07004768 pattern = counter + " was updated to (-?\d+)"
4769 match = re.search( pattern, output )
4770 if match:
4771 return int( match.group( 1 ) )
4772 else:
4773 main.log.error( self.name + ": counterTestGetAndAdd did not" +
4774 " match expected output." )
4775 main.log.debug( self.name + " expected: " + pattern )
4776 main.log.debug( self.name + " actual: " + repr( output ) )
4777 return None
Jon Halle1a3b752015-07-22 13:02:46 -07004778 except TypeError:
4779 main.log.exception( self.name + ": Object not as expected" )
4780 return None
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004781 except Exception:
4782 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004783 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004784
4785 def valueTestGet( self, valueName ):
4786 """
4787 CLI command to get the value of an atomic value.
4788 Required arguments:
4789 valueName - The name of the value to get.
4790 returns:
4791 string value of the value or
4792 None on Error
4793 """
4794 try:
4795 valueName = str( valueName )
4796 cmdStr = "value-test "
4797 operation = "get"
4798 cmdStr = "value-test {} {}".format( valueName,
4799 operation )
4800 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08004801 main.log.debug( self.name + ": value test unparsed: " + output )
4802 output = output.split( "\r\n" )[ -1 ]
4803 main.log.debug( self.name + ": value test parsed: " + output )
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004804 pattern = "(\w+)"
4805 match = re.search( pattern, output )
4806 if match:
4807 return match.group( 1 )
4808 else:
4809 main.log.error( self.name + ": valueTestGet did not" +
4810 " match expected output." )
4811 main.log.debug( self.name + " expected: " + pattern )
4812 main.log.debug( self.name + " actual: " + repr( output ) )
4813 return None
4814 except TypeError:
4815 main.log.exception( self.name + ": Object not as expected" )
4816 return None
4817 except Exception:
4818 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004819 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004820
4821 def valueTestSet( self, valueName, newValue ):
4822 """
4823 CLI command to set the value of an atomic value.
4824 Required arguments:
4825 valueName - The name of the value to set.
4826 newValue - The value to assign to the given value.
4827 returns:
4828 main.TRUE on success or
4829 main.ERROR on Error
4830 """
4831 try:
4832 valueName = str( valueName )
4833 newValue = str( newValue )
4834 operation = "set"
4835 cmdStr = "value-test {} {} {}".format( valueName,
4836 operation,
4837 newValue )
4838 output = self.distPrimitivesSend( cmdStr )
4839 if output is not None:
4840 return main.TRUE
4841 else:
4842 return main.ERROR
4843 except TypeError:
4844 main.log.exception( self.name + ": Object not as expected" )
4845 return main.ERROR
4846 except Exception:
4847 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004848 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004849
4850 def valueTestCompareAndSet( self, valueName, oldValue, newValue ):
4851 """
4852 CLI command to compareAndSet the value of an atomic value.
4853 Required arguments:
4854 valueName - The name of the value.
4855 oldValue - Compare the current value of the atomic value to this
4856 newValue - If the value equals oldValue, set the value to newValue
4857 returns:
4858 main.TRUE on success or
4859 main.FALSE on failure or
4860 main.ERROR on Error
4861 """
4862 try:
4863 valueName = str( valueName )
4864 oldValue = str( oldValue )
4865 newValue = str( newValue )
4866 operation = "compareAndSet"
4867 cmdStr = "value-test {} {} {} {}".format( valueName,
4868 operation,
4869 oldValue,
4870 newValue )
4871 output = self.distPrimitivesSend( cmdStr )
4872 pattern = "(\w+)"
4873 match = re.search( pattern, output )
4874 if match:
4875 result = match.group( 1 )
4876 if result == "true":
4877 return main.TRUE
4878 elif result == "false":
4879 return main.FALSE
4880 else:
4881 main.log.error( self.name + ": valueTestCompareAndSet did not" +
4882 " match expected output." )
4883 main.log.debug( self.name + " expected: " + pattern )
4884 main.log.debug( self.name + " actual: " + repr( output ) )
4885 return main.ERROR
4886 except TypeError:
4887 main.log.exception( self.name + ": Object not as expected" )
4888 return main.ERROR
4889 except Exception:
4890 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004891 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004892
4893 def valueTestGetAndSet( self, valueName, newValue ):
4894 """
4895 CLI command to getAndSet the value of an atomic value.
4896 Required arguments:
4897 valueName - The name of the value to get.
4898 newValue - The value to assign to the given value
4899 returns:
4900 string value of the value or
4901 None on Error
4902 """
4903 try:
4904 valueName = str( valueName )
4905 cmdStr = "value-test "
4906 operation = "getAndSet"
4907 cmdStr += valueName + " " + operation
4908 cmdStr = "value-test {} {} {}".format( valueName,
4909 operation,
4910 newValue )
4911 output = self.distPrimitivesSend( cmdStr )
4912 pattern = "(\w+)"
4913 match = re.search( pattern, output )
4914 if match:
4915 return match.group( 1 )
4916 else:
4917 main.log.error( self.name + ": valueTestGetAndSet did not" +
4918 " match expected output." )
4919 main.log.debug( self.name + " expected: " + pattern )
4920 main.log.debug( self.name + " actual: " + repr( output ) )
4921 return None
4922 except TypeError:
4923 main.log.exception( self.name + ": Object not as expected" )
4924 return None
4925 except Exception:
4926 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004927 main.cleanAndExit()
Jon Hall7a6ebfd2017-03-13 10:58:58 -07004928
4929 def valueTestDestroy( self, valueName ):
4930 """
4931 CLI command to destroy an atomic value.
4932 Required arguments:
4933 valueName - The name of the value to destroy.
4934 returns:
4935 main.TRUE on success or
4936 main.ERROR on Error
4937 """
4938 try:
4939 valueName = str( valueName )
4940 cmdStr = "value-test "
4941 operation = "destroy"
4942 cmdStr += valueName + " " + operation
4943 output = self.distPrimitivesSend( cmdStr )
4944 if output is not None:
4945 return main.TRUE
4946 else:
4947 return main.ERROR
4948 except TypeError:
4949 main.log.exception( self.name + ": Object not as expected" )
4950 return main.ERROR
Jon Halle1a3b752015-07-22 13:02:46 -07004951 except Exception:
4952 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004953 main.cleanAndExit()
Jon Halle1a3b752015-07-22 13:02:46 -07004954
YPZhangfebf7302016-05-24 16:45:56 -07004955 def summary( self, jsonFormat=True, timeout=30 ):
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004956 """
4957 Description: Execute summary command in onos
4958 Returns: json object ( summary -j ), returns main.FALSE if there is
4959 no output
4960
4961 """
4962 try:
4963 cmdStr = "summary"
4964 if jsonFormat:
4965 cmdStr += " -j"
YPZhangfebf7302016-05-24 16:45:56 -07004966 handle = self.sendline( cmdStr, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07004967 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08004968 assert "Command not found:" not in handle, handle
Jon Hall6e709752016-02-01 13:38:46 -08004969 assert "Error:" not in handle, handle
Devin Lima7cfdbd2017-09-29 15:02:22 -07004970 assert "Error executing" not in handle, handle
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004971 if not handle:
4972 main.log.error( self.name + ": There is no output in " +
4973 "summary command" )
4974 return main.FALSE
4975 return handle
Jon Hallc6793552016-01-19 14:18:37 -08004976 except AssertionError:
Jon Hall6e709752016-02-01 13:38:46 -08004977 main.log.exception( "{} Error in summary output:".format( self.name ) )
Jon Hallc6793552016-01-19 14:18:37 -08004978 return None
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004979 except TypeError:
4980 main.log.exception( self.name + ": Object not as expected" )
4981 return None
4982 except pexpect.EOF:
4983 main.log.error( self.name + ": EOF exception found" )
4984 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07004985 main.cleanAndExit()
kelvin-onlaba297c4d2015-06-01 13:53:55 -07004986 except Exception:
4987 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07004988 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07004989
Jon Hall06fd0df2021-01-25 15:50:06 -08004990 def getAddress( self):
4991 """
4992 Get the onos ip address from the cli. This is usefull when connecting using
4993 a container manager such as kubernetes. This function also sets self.address
4994 the value from ONOS.
4995
4996 Returns:
4997 The string value of the key or
4998 None on Error
4999 """
5000 try:
5001 output = self.summary()
5002 address = json.loads( output ).get( 'node' )
5003 self.address = address
5004 return address
You Wang327bad42021-03-24 14:19:58 -07005005 except ( TypeError, ValueError ):
Jon Hall06fd0df2021-01-25 15:50:06 -08005006 main.log.exception( self.name + ": Object not as expected" )
5007 return None
5008 except Exception:
5009 main.log.exception( self.name + ": Uncaught exception!" )
5010 main.cleanAndExit()
5011
Jon Hall935db192016-04-19 00:22:04 -07005012 def transactionalMapGet( self, keyName ):
Jon Hall2a5002c2015-08-21 16:49:11 -07005013 """
5014 CLI command to get the value of a key in a consistent map using
5015 transactions. This a test function and can only get keys from the
5016 test map hard coded into the cli command
5017 Required arguments:
5018 keyName - The name of the key to get
Jon Hall2a5002c2015-08-21 16:49:11 -07005019 returns:
5020 The string value of the key or
5021 None on Error
5022 """
5023 try:
5024 keyName = str( keyName )
5025 cmdStr = "transactional-map-test-get "
Jon Hall2a5002c2015-08-21 16:49:11 -07005026 cmdStr += keyName
Jon Hall7a6ebfd2017-03-13 10:58:58 -07005027 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07005028 pattern = "Key-value pair \(" + keyName + ", (?P<value>.+)\) found."
5029 if "Key " + keyName + " not found." in output:
Jon Hall9bfadd22016-05-11 14:48:07 -07005030 main.log.warn( output )
Jon Hall2a5002c2015-08-21 16:49:11 -07005031 return None
5032 else:
5033 match = re.search( pattern, output )
5034 if match:
5035 return match.groupdict()[ 'value' ]
5036 else:
5037 main.log.error( self.name + ": transactionlMapGet did not" +
5038 " match expected output." )
5039 main.log.debug( self.name + " expected: " + pattern )
5040 main.log.debug( self.name + " actual: " + repr( output ) )
5041 return None
5042 except TypeError:
5043 main.log.exception( self.name + ": Object not as expected" )
5044 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07005045 except Exception:
5046 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005047 main.cleanAndExit()
Jon Hall2a5002c2015-08-21 16:49:11 -07005048
Jon Hall935db192016-04-19 00:22:04 -07005049 def transactionalMapPut( self, numKeys, value ):
Jon Hall2a5002c2015-08-21 16:49:11 -07005050 """
5051 CLI command to put a value into 'numKeys' number of keys in a
5052 consistent map using transactions. This a test function and can only
5053 put into keys named 'Key#' of the test map hard coded into the cli command
5054 Required arguments:
5055 numKeys - Number of keys to add the value to
5056 value - The string value to put into the keys
Jon Hall2a5002c2015-08-21 16:49:11 -07005057 returns:
5058 A dictionary whose keys are the name of the keys put into the map
5059 and the values of the keys are dictionaries whose key-values are
5060 'value': value put into map and optionaly
5061 'oldValue': Previous value in the key or
5062 None on Error
5063
5064 Example output
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005065 { 'Key1': {'oldValue': 'oldTestValue', 'value': 'Testing'},
5066 'Key2': {'value': 'Testing'} }
Jon Hall2a5002c2015-08-21 16:49:11 -07005067 """
5068 try:
5069 numKeys = str( numKeys )
5070 value = str( value )
5071 cmdStr = "transactional-map-test-put "
Jon Hall2a5002c2015-08-21 16:49:11 -07005072 cmdStr += numKeys + " " + value
Jon Hall7a6ebfd2017-03-13 10:58:58 -07005073 output = self.distPrimitivesSend( cmdStr )
Jon Hall2a5002c2015-08-21 16:49:11 -07005074 newPattern = 'Created Key (?P<key>(\w)+) with value (?P<value>(.)+)\.'
5075 updatedPattern = "Put (?P<value>(.)+) into key (?P<key>(\w)+)\. The old value was (?P<oldValue>(.)+)\."
5076 results = {}
5077 for line in output.splitlines():
5078 new = re.search( newPattern, line )
5079 updated = re.search( updatedPattern, line )
5080 if new:
5081 results[ new.groupdict()[ 'key' ] ] = { 'value': new.groupdict()[ 'value' ] }
5082 elif updated:
5083 results[ updated.groupdict()[ 'key' ] ] = { 'value': updated.groupdict()[ 'value' ],
Jon Hallc6793552016-01-19 14:18:37 -08005084 'oldValue': updated.groupdict()[ 'oldValue' ] }
Jon Hall2a5002c2015-08-21 16:49:11 -07005085 else:
5086 main.log.error( self.name + ": transactionlMapGet did not" +
5087 " match expected output." )
Jon Hallc6793552016-01-19 14:18:37 -08005088 main.log.debug( "{} expected: {!r} or {!r}".format( self.name,
5089 newPattern,
5090 updatedPattern ) )
Jon Hall2a5002c2015-08-21 16:49:11 -07005091 main.log.debug( self.name + " actual: " + repr( output ) )
5092 return results
Jon Hall0e240372018-05-02 11:21:57 -07005093 except ( TypeError, AttributeError ):
Jon Hall2a5002c2015-08-21 16:49:11 -07005094 main.log.exception( self.name + ": Object not as expected" )
5095 return None
Jon Hall2a5002c2015-08-21 16:49:11 -07005096 except Exception:
5097 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005098 main.cleanAndExit()
Jon Hallc6793552016-01-19 14:18:37 -08005099
acsmarsdaea66c2015-09-03 11:44:06 -07005100 def maps( self, jsonFormat=True ):
5101 """
5102 Description: Returns result of onos:maps
5103 Optional:
5104 * jsonFormat: enable json formatting of output
5105 """
5106 try:
5107 cmdStr = "maps"
5108 if jsonFormat:
5109 cmdStr += " -j"
5110 handle = self.sendline( cmdStr )
Jon Halla495f562016-05-16 18:03:26 -07005111 assert handle is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005112 assert "Command not found:" not in handle, handle
acsmarsdaea66c2015-09-03 11:44:06 -07005113 return handle
Jon Hallc6793552016-01-19 14:18:37 -08005114 except AssertionError:
5115 main.log.exception( "" )
5116 return None
acsmarsdaea66c2015-09-03 11:44:06 -07005117 except TypeError:
5118 main.log.exception( self.name + ": Object not as expected" )
5119 return None
5120 except pexpect.EOF:
5121 main.log.error( self.name + ": EOF exception found" )
5122 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005123 main.cleanAndExit()
acsmarsdaea66c2015-09-03 11:44:06 -07005124 except Exception:
5125 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005126 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005127
5128 def getSwController( self, uri, jsonFormat=True ):
5129 """
5130 Descrition: Gets the controller information from the device
5131 """
5132 try:
5133 cmd = "device-controllers "
5134 if jsonFormat:
5135 cmd += "-j "
5136 response = self.sendline( cmd + uri )
Jon Halla495f562016-05-16 18:03:26 -07005137 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005138 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005139 return response
Jon Hallc6793552016-01-19 14:18:37 -08005140 except AssertionError:
5141 main.log.exception( "" )
5142 return None
GlennRC050596c2015-11-18 17:06:41 -08005143 except TypeError:
5144 main.log.exception( self.name + ": Object not as expected" )
5145 return None
5146 except pexpect.EOF:
5147 main.log.error( self.name + ": EOF exception found" )
5148 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005149 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005150 except Exception:
5151 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005152 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005153
5154 def setSwController( self, uri, ip, proto="tcp", port="6653", jsonFormat=True ):
5155 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005156 Descrition: sets the controller(s) for the specified device
GlennRC050596c2015-11-18 17:06:41 -08005157
5158 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005159 Required: uri - String: The uri of the device(switch).
GlennRC050596c2015-11-18 17:06:41 -08005160 ip - String or List: The ip address of the controller.
5161 This parameter can be formed in a couple of different ways.
5162 VALID:
5163 10.0.0.1 - just the ip address
5164 tcp:10.0.0.1 - the protocol and the ip address
5165 tcp:10.0.0.1:6653 - the protocol and port can be specified,
5166 so that you can add controllers with different
5167 protocols and ports
5168 INVALID:
5169 10.0.0.1:6653 - this is not supported by ONOS
5170
5171 Optional: proto - The type of connection e.g. tcp, ssl. If a list of ips are given
5172 port - The port number.
5173 jsonFormat - If set ONOS will output in json NOTE: This is currently not supported
5174
5175 Returns: main.TRUE if ONOS returns without any errors, otherwise returns main.FALSE
5176 """
5177 try:
5178 cmd = "device-setcontrollers"
5179
5180 if jsonFormat:
5181 cmd += " -j"
5182 cmd += " " + uri
5183 if isinstance( ip, str ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005184 ip = [ ip ]
GlennRC050596c2015-11-18 17:06:41 -08005185 for item in ip:
5186 if ":" in item:
5187 sitem = item.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005188 if len( sitem ) == 3:
GlennRC050596c2015-11-18 17:06:41 -08005189 cmd += " " + item
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005190 elif "." in sitem[ 1 ]:
5191 cmd += " {}:{}".format( item, port )
GlennRC050596c2015-11-18 17:06:41 -08005192 else:
5193 main.log.error( "Malformed entry: " + item )
5194 raise TypeError
5195 else:
5196 cmd += " {}:{}:{}".format( proto, item, port )
GlennRC050596c2015-11-18 17:06:41 -08005197 response = self.sendline( cmd )
Jon Halla495f562016-05-16 18:03:26 -07005198 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005199 assert "Command not found:" not in response, response
GlennRC050596c2015-11-18 17:06:41 -08005200 if "Error" in response:
5201 main.log.error( response )
5202 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005203 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005204 except AssertionError:
5205 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005206 return main.FALSE
GlennRC050596c2015-11-18 17:06:41 -08005207 except TypeError:
5208 main.log.exception( self.name + ": Object not as expected" )
5209 return main.FALSE
5210 except pexpect.EOF:
5211 main.log.error( self.name + ": EOF exception found" )
5212 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005213 main.cleanAndExit()
GlennRC050596c2015-11-18 17:06:41 -08005214 except Exception:
5215 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005216 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005217
5218 def removeDevice( self, device ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005219 '''
GlennRC20fc6522015-12-23 23:26:57 -08005220 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005221 Remove a device from ONOS by passing the uri of the device(s).
GlennRC20fc6522015-12-23 23:26:57 -08005222 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005223 device - (str or list) the id or uri of the device ex. "of:0000000000000001"
GlennRC20fc6522015-12-23 23:26:57 -08005224 Returns:
5225 Returns main.FALSE if an exception is thrown or an error is present
5226 in the response. Otherwise, returns main.TRUE.
5227 NOTE:
5228 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005229 '''
GlennRC20fc6522015-12-23 23:26:57 -08005230 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005231 if isinstance( device, str ):
You Wang823f5022016-08-18 15:24:41 -07005232 deviceStr = device
5233 device = []
5234 device.append( deviceStr )
GlennRC20fc6522015-12-23 23:26:57 -08005235
5236 for d in device:
5237 time.sleep( 1 )
5238 response = self.sendline( "device-remove {}".format( d ) )
Jon Halla495f562016-05-16 18:03:26 -07005239 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005240 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005241 if "Error" in response:
5242 main.log.warn( "Error for device: {}\nResponse: {}".format( d, response ) )
5243 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005244 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005245 except AssertionError:
5246 main.log.exception( "" )
5247 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005248 except TypeError:
5249 main.log.exception( self.name + ": Object not as expected" )
5250 return main.FALSE
5251 except pexpect.EOF:
5252 main.log.error( self.name + ": EOF exception found" )
5253 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005254 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005255 except Exception:
5256 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005257 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005258
5259 def removeHost( self, host ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005260 '''
GlennRC20fc6522015-12-23 23:26:57 -08005261 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005262 Remove a host from ONOS by passing the id of the host(s)
GlennRC20fc6522015-12-23 23:26:57 -08005263 Parameters:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005264 hostId - (str or list) the id or mac of the host ex. "00:00:00:00:00:01"
GlennRC20fc6522015-12-23 23:26:57 -08005265 Returns:
5266 Returns main.FALSE if an exception is thrown or an error is present
5267 in the response. Otherwise, returns main.TRUE.
5268 NOTE:
5269 If a host cannot be removed, then this function will return main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005270 '''
GlennRC20fc6522015-12-23 23:26:57 -08005271 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005272 if isinstance( host, str ):
GlennRC20fc6522015-12-23 23:26:57 -08005273 host = list( host )
5274
5275 for h in host:
5276 time.sleep( 1 )
5277 response = self.sendline( "host-remove {}".format( h ) )
Jon Halla495f562016-05-16 18:03:26 -07005278 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005279 assert "Command not found:" not in response, response
GlennRC20fc6522015-12-23 23:26:57 -08005280 if "Error" in response:
5281 main.log.warn( "Error for host: {}\nResponse: {}".format( h, response ) )
5282 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005283 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005284 except AssertionError:
5285 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005286 return main.FALSE
GlennRC20fc6522015-12-23 23:26:57 -08005287 except TypeError:
5288 main.log.exception( self.name + ": Object not as expected" )
5289 return main.FALSE
5290 except pexpect.EOF:
5291 main.log.error( self.name + ": EOF exception found" )
5292 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005293 main.cleanAndExit()
GlennRC20fc6522015-12-23 23:26:57 -08005294 except Exception:
5295 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005296 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005297
YPZhangfebf7302016-05-24 16:45:56 -07005298 def link( self, begin, end, state, timeout=30, showResponse=True ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005299 '''
GlennRCed771242016-01-13 17:02:47 -08005300 Description:
5301 Bring link down or up in the null-provider.
5302 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005303 begin - (string) One end of a device or switch.
5304 end - (string) the other end of the device or switch
GlennRCed771242016-01-13 17:02:47 -08005305 returns:
5306 main.TRUE if no exceptions were thrown and no Errors are
5307 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005308 '''
GlennRCed771242016-01-13 17:02:47 -08005309 try:
Jon Halle0f0b342017-04-18 11:43:47 -07005310 cmd = "null-link null:{} null:{} {}".format( begin, end, state )
YPZhangfebf7302016-05-24 16:45:56 -07005311 response = self.sendline( cmd, showResponse=showResponse, timeout=timeout )
Jon Halla495f562016-05-16 18:03:26 -07005312 assert response is not None, "Error in sendline"
Jon Hallc6793552016-01-19 14:18:37 -08005313 assert "Command not found:" not in response, response
GlennRCed771242016-01-13 17:02:47 -08005314 if "Error" in response or "Failure" in response:
5315 main.log.error( response )
5316 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005317 return main.TRUE
Jon Hallc6793552016-01-19 14:18:37 -08005318 except AssertionError:
5319 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005320 return main.FALSE
GlennRCed771242016-01-13 17:02:47 -08005321 except TypeError:
5322 main.log.exception( self.name + ": Object not as expected" )
5323 return main.FALSE
5324 except pexpect.EOF:
5325 main.log.error( self.name + ": EOF exception found" )
5326 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005327 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005328 except Exception:
5329 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005330 main.cleanAndExit()
GlennRCed771242016-01-13 17:02:47 -08005331
Jon Hall2c8959e2016-12-16 12:17:34 -08005332 def portstate( self, dpid, port, state ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005333 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005334 Description:
5335 Changes the state of port in an OF switch by means of the
5336 PORTSTATUS OF messages.
5337 params:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005338 dpid - (string) Datapath ID of the device. Ex: 'of:0000000000000102'
5339 port - (string) target port in the device. Ex: '2'
5340 state - (string) target state (enable or disable)
Flavio Castro82ee2f62016-06-07 15:04:12 -07005341 returns:
5342 main.TRUE if no exceptions were thrown and no Errors are
5343 present in the resoponse. Otherwise, returns main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005344 '''
Flavio Castro82ee2f62016-06-07 15:04:12 -07005345 try:
Jon Hall2c8959e2016-12-16 12:17:34 -08005346 state = state.lower()
5347 assert state == 'enable' or state == 'disable', "Unknown state"
Jon Halle0f0b342017-04-18 11:43:47 -07005348 cmd = "portstate {} {} {}".format( dpid, port, state )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005349 response = self.sendline( cmd, showResponse=True )
5350 assert response is not None, "Error in sendline"
5351 assert "Command not found:" not in response, response
5352 if "Error" in response or "Failure" in response:
5353 main.log.error( response )
5354 return main.FALSE
5355 return main.TRUE
5356 except AssertionError:
5357 main.log.exception( "" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005358 return main.FALSE
Flavio Castro82ee2f62016-06-07 15:04:12 -07005359 except TypeError:
5360 main.log.exception( self.name + ": Object not as expected" )
5361 return main.FALSE
5362 except pexpect.EOF:
5363 main.log.error( self.name + ": EOF exception found" )
5364 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005365 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005366 except Exception:
5367 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005368 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005369
5370 def logSet( self, level="INFO", app="org.onosproject" ):
5371 """
5372 Set the logging level to lvl for a specific app
5373 returns main.TRUE on success
5374 returns main.FALSE if Error occurred
5375 if noExit is True, TestON will not exit, but clean up
5376 Available level: DEBUG, TRACE, INFO, WARN, ERROR
5377 Level defaults to INFO
5378 """
5379 try:
You Wang22e807e2021-03-29 10:53:38 -07005380 handle = self.sendline( "log:set %s %s" % ( level, app ) )
5381 assert handle is not None, "Error in sendline"
5382 assert "Command not found:" not in handle, handle
5383 if re.search( "Error", handle ):
5384 main.log.error( self.name + ": Error in setting log level" )
5385 main.log.error( handle )
Flavio Castro82ee2f62016-06-07 15:04:12 -07005386 return main.FALSE
You Wang22e807e2021-03-29 10:53:38 -07005387 else:
5388 return main.TRUE
5389 except AssertionError:
5390 main.log.exception( "" )
5391 return None
5392 except TypeError:
5393 main.log.exception( self.name + ": Object not as expected" )
5394 return None
Flavio Castro82ee2f62016-06-07 15:04:12 -07005395 except pexpect.EOF:
5396 main.log.error( self.name + ": EOF exception found" )
5397 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005398 main.cleanAndExit()
Flavio Castro82ee2f62016-06-07 15:04:12 -07005399 except Exception:
5400 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005401 main.cleanAndExit()
You Wangdb8cd0a2016-05-26 15:19:45 -07005402
Jon Hall06fd0df2021-01-25 15:50:06 -08005403 def logList( self, saveValues=True ):
5404 """
5405 Gets the current log levels and optionally saves them
5406 returns a dict of the log levels or
5407 returns main.FALSE if Error occurred
5408 """
5409 try:
5410 self.handle.sendline( "log:list" )
5411 self.handle.expect( self.karafPrompt )
5412
5413 response = self.handle.before
5414 logLevels = {}
5415 for line in response.splitlines():
5416 parsed = line.split('│')
5417 logger = parsed[0].strip()
5418 if len( parsed ) != 2 or 'Level' in parsed[1] or logger[0] == '─':
5419 continue
5420 level = parsed[1].strip()
5421 logLevels[ logger ] = level
5422 if saveValues:
5423 self.logLevels = logLevels
5424 return logLevels
5425 except pexpect.TIMEOUT:
5426 main.log.exception( self.name + ": TIMEOUT exception found" )
5427 main.cleanAndExit()
5428 except pexpect.EOF:
5429 main.log.error( self.name + ": EOF exception found" )
5430 main.log.error( self.name + ": " + self.handle.before )
5431 main.cleanAndExit()
5432 except Exception:
5433 main.log.exception( self.name + ": Uncaught exception!" )
5434 main.cleanAndExit()
5435
You Wangdb8cd0a2016-05-26 15:19:45 -07005436 def getGraphDict( self, timeout=60, includeHost=False ):
5437 """
5438 Return a dictionary which describes the latest network topology data as a
5439 graph.
5440 An example of the dictionary:
5441 { vertex1: { 'edges': ..., 'name': ..., 'protocol': ... },
5442 vertex2: { 'edges': ..., 'name': ..., 'protocol': ... } }
5443 Each vertex should at least have an 'edges' attribute which describes the
5444 adjacency information. The value of 'edges' attribute is also represented by
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005445 a dictionary, which maps each edge (identified by the neighbor vertex) to a
You Wangdb8cd0a2016-05-26 15:19:45 -07005446 list of attributes.
5447 An example of the edges dictionary:
5448 'edges': { vertex2: { 'port': ..., 'weight': ... },
5449 vertex3: { 'port': ..., 'weight': ... } }
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005450 If includeHost == True, all hosts (and host-switch links) will be included
You Wangdb8cd0a2016-05-26 15:19:45 -07005451 in topology data.
5452 """
5453 graphDict = {}
5454 try:
5455 links = self.links()
5456 links = json.loads( links )
5457 devices = self.devices()
5458 devices = json.loads( devices )
5459 idToDevice = {}
5460 for device in devices:
5461 idToDevice[ device[ 'id' ] ] = device
5462 if includeHost:
5463 hosts = self.hosts()
5464 # FIXME: support 'includeHost' argument
5465 for link in links:
5466 nodeA = link[ 'src' ][ 'device' ]
5467 nodeB = link[ 'dst' ][ 'device' ]
5468 assert idToDevice[ nodeA ][ 'available' ] and idToDevice[ nodeB ][ 'available' ]
Jon Halle0f0b342017-04-18 11:43:47 -07005469 if nodeA not in graphDict.keys():
5470 graphDict[ nodeA ] = { 'edges': {},
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005471 'dpid': idToDevice[ nodeA ][ 'id' ][ 3: ],
Jon Halle0f0b342017-04-18 11:43:47 -07005472 'type': idToDevice[ nodeA ][ 'type' ],
5473 'available': idToDevice[ nodeA ][ 'available' ],
5474 'role': idToDevice[ nodeA ][ 'role' ],
5475 'mfr': idToDevice[ nodeA ][ 'mfr' ],
5476 'hw': idToDevice[ nodeA ][ 'hw' ],
5477 'sw': idToDevice[ nodeA ][ 'sw' ],
5478 'serial': idToDevice[ nodeA ][ 'serial' ],
5479 'chassisId': idToDevice[ nodeA ][ 'chassisId' ],
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005480 'annotations': idToDevice[ nodeA ][ 'annotations' ]}
You Wangdb8cd0a2016-05-26 15:19:45 -07005481 else:
5482 # Assert nodeB is not connected to any current links of nodeA
You Wang7d14d642019-01-23 15:10:08 -08005483 # assert nodeB not in graphDict[ nodeA ][ 'edges' ].keys()
5484 pass
Jon Halle0f0b342017-04-18 11:43:47 -07005485 graphDict[ nodeA ][ 'edges' ][ nodeB ] = { 'port': link[ 'src' ][ 'port' ],
5486 'type': link[ 'type' ],
5487 'state': link[ 'state' ] }
You Wangdb8cd0a2016-05-26 15:19:45 -07005488 return graphDict
5489 except ( TypeError, ValueError ):
5490 main.log.exception( self.name + ": Object not as expected" )
5491 return None
5492 except KeyError:
5493 main.log.exception( self.name + ": KeyError exception found" )
5494 return None
5495 except AssertionError:
5496 main.log.exception( self.name + ": AssertionError exception found" )
5497 return None
5498 except pexpect.EOF:
5499 main.log.error( self.name + ": EOF exception found" )
5500 main.log.error( self.name + ": " + self.handle.before )
5501 return None
5502 except Exception:
5503 main.log.exception( self.name + ": Uncaught exception!" )
5504 return None
YPZhangcbc2a062016-07-11 10:55:44 -07005505
5506 def getIntentPerfSummary( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005507 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005508 Send command to check intent-perf summary
5509 Returns: dictionary for intent-perf summary
5510 if something wrong, function will return None
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005511 '''
YPZhangcbc2a062016-07-11 10:55:44 -07005512 cmd = "intent-perf -s"
5513 respDic = {}
5514 resp = self.sendline( cmd )
You Wangb5a55f72017-03-03 12:51:05 -08005515 assert resp is not None, "Error in sendline"
5516 assert "Command not found:" not in resp, resp
YPZhangcbc2a062016-07-11 10:55:44 -07005517 try:
5518 # Generate the dictionary to return
5519 for l in resp.split( "\n" ):
5520 # Delete any white space in line
5521 temp = re.sub( r'\s+', '', l )
5522 temp = temp.split( ":" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005523 respDic[ temp[ 0 ] ] = temp[ 1 ]
YPZhangcbc2a062016-07-11 10:55:44 -07005524
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005525 except ( TypeError, ValueError ):
YPZhangcbc2a062016-07-11 10:55:44 -07005526 main.log.exception( self.name + ": Object not as expected" )
5527 return None
5528 except KeyError:
5529 main.log.exception( self.name + ": KeyError exception found" )
5530 return None
5531 except AssertionError:
5532 main.log.exception( self.name + ": AssertionError exception found" )
5533 return None
5534 except pexpect.EOF:
5535 main.log.error( self.name + ": EOF exception found" )
5536 main.log.error( self.name + ": " + self.handle.before )
5537 return None
5538 except Exception:
5539 main.log.exception( self.name + ": Uncaught exception!" )
5540 return None
5541 return respDic
5542
Chiyu Chengec63bde2016-11-17 18:11:36 -08005543 def logSearch( self, mode='all', searchTerm='', startLine='', logNum=1 ):
chengchiyu08303a02016-09-08 17:40:26 -07005544 """
5545 Searches the latest ONOS log file for the given search term and
5546 return a list that contains all the lines that have the search term.
YPZhangcbc2a062016-07-11 10:55:44 -07005547
chengchiyu08303a02016-09-08 17:40:26 -07005548 Arguments:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005549 searchTerm:
5550 The string to grep from the ONOS log.
5551 startLine:
5552 The term that decides which line is the start to search the searchTerm in
5553 the karaf log. For now, startTerm only works in 'first' mode.
5554 logNum:
5555 In some extreme cases, one karaf log is not big enough to contain all the
5556 information.Because of this, search mutiply logs is necessary to capture
5557 the right result. logNum is the number of karaf logs that we need to search
5558 the searchTerm.
chengchiyu08303a02016-09-08 17:40:26 -07005559 mode:
5560 all: return all the strings that contain the search term
5561 last: return the last string that contains the search term
5562 first: return the first string that contains the search term
Chiyu Chengec63bde2016-11-17 18:11:36 -08005563 num: return the number of times that the searchTerm appears in the log
5564 total: return how many lines in karaf log
chengchiyu08303a02016-09-08 17:40:26 -07005565 """
5566 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005567 assert isinstance( searchTerm, str )
Jon Halle0f0b342017-04-18 11:43:47 -07005568 # Build the log paths string
Chiyu Chengec63bde2016-11-17 18:11:36 -08005569 logPath = '/opt/onos/log/karaf.log.'
5570 logPaths = '/opt/onos/log/karaf.log'
5571 for i in range( 1, logNum ):
5572 logPaths = logPath + str( i ) + " " + logPaths
5573 cmd = "cat " + logPaths
You Wang6d301d42017-04-21 10:49:33 -07005574 if startLine:
Jon Halla478b852017-12-04 15:00:15 -08005575 # 100000000 is just a extreme large number to make sure this function can
5576 # grep all the lines after startLine
You Wang6d301d42017-04-21 10:49:33 -07005577 cmd = cmd + " | grep -A 100000000 \'" + startLine + "\'"
Chiyu Chengec63bde2016-11-17 18:11:36 -08005578 if mode == 'all':
5579 cmd = cmd + " | grep \'" + searchTerm + "\'"
You Wang6d301d42017-04-21 10:49:33 -07005580 elif mode == 'last':
Chiyu Chengec63bde2016-11-17 18:11:36 -08005581 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | tail -n 1"
You Wang6d301d42017-04-21 10:49:33 -07005582 elif mode == 'first':
5583 cmd = cmd + " | grep \'" + searchTerm + "\'" + " | head -n 1"
5584 elif mode == 'num':
You Wangd91a70f2019-01-03 15:28:10 -08005585 cmd = cmd + " | grep \'" + searchTerm + "\' | wc -l"
5586 num = self.lineCount( cmd )
Chiyu Chengb8c2c842016-10-05 12:40:49 -07005587 return num
You Wang6d301d42017-04-21 10:49:33 -07005588 elif mode == 'total':
Jon Halld5a94fb2018-11-13 14:32:23 -08005589 totalLines = self.lineCount( "cat /opt/onos/log/karaf.log | wc -l" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005590 return int( totalLines )
You Wang6d301d42017-04-21 10:49:33 -07005591 else:
5592 main.log.error( self.name + " unsupported mode" )
5593 return main.ERROR
chengchiyu08303a02016-09-08 17:40:26 -07005594 before = self.sendline( cmd )
5595 before = before.splitlines()
5596 # make sure the returned list only contains the search term
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005597 returnLines = [ line for line in before if searchTerm in line ]
chengchiyu08303a02016-09-08 17:40:26 -07005598 return returnLines
5599 except AssertionError:
5600 main.log.error( self.name + " searchTerm is not string type" )
5601 return None
5602 except pexpect.EOF:
5603 main.log.error( self.name + ": EOF exception found" )
5604 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005605 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005606 except pexpect.TIMEOUT:
5607 main.log.error( self.name + ": TIMEOUT exception found" )
5608 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005609 main.cleanAndExit()
chengchiyu08303a02016-09-08 17:40:26 -07005610 except Exception:
5611 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005612 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005613
5614 def vplsShow( self, jsonFormat=True ):
5615 """
5616 Description: Returns result of onos:vpls show, which should list the
5617 configured VPLS networks and the assigned interfaces.
5618 Optional:
5619 * jsonFormat: enable json formatting of output
5620 Returns:
5621 The output of the command or None on error.
5622 """
5623 try:
5624 cmdStr = "vpls show"
5625 if jsonFormat:
5626 raise NotImplementedError
5627 cmdStr += " -j"
5628 handle = self.sendline( cmdStr )
5629 assert handle is not None, "Error in sendline"
5630 assert "Command not found:" not in handle, handle
5631 return handle
5632 except AssertionError:
5633 main.log.exception( "" )
5634 return None
5635 except TypeError:
5636 main.log.exception( self.name + ": Object not as expected" )
5637 return None
5638 except pexpect.EOF:
5639 main.log.error( self.name + ": EOF exception found" )
5640 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005641 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005642 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005643 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005644 return None
5645 except Exception:
5646 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005647 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005648
5649 def parseVplsShow( self ):
5650 """
5651 Parse the cli output of 'vpls show' into json output. This is required
5652 as there is currently no json output available.
5653 """
5654 try:
5655 output = []
5656 raw = self.vplsShow( jsonFormat=False )
5657 namePat = "VPLS name: (?P<name>\w+)"
5658 interfacesPat = "Associated interfaces: \[(?P<interfaces>.*)\]"
5659 encapPat = "Encapsulation: (?P<encap>\w+)"
5660 pattern = "\s+".join( [ namePat, interfacesPat, encapPat ] )
5661 mIter = re.finditer( pattern, raw )
5662 for match in mIter:
5663 item = {}
5664 item[ 'name' ] = match.group( 'name' )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005665 ifaces = match.group( 'interfaces' ).split( ', ' )
Jon Hall2c8959e2016-12-16 12:17:34 -08005666 if ifaces == [ "" ]:
5667 ifaces = []
5668 item[ 'interfaces' ] = ifaces
5669 encap = match.group( 'encap' )
5670 if encap != 'NONE':
5671 item[ 'encapsulation' ] = encap.lower()
5672 output.append( item )
5673 return output
5674 except Exception:
5675 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005676 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005677
5678 def vplsList( self, jsonFormat=True ):
5679 """
5680 Description: Returns result of onos:vpls list, which should list the
5681 configured VPLS networks.
5682 Optional:
5683 * jsonFormat: enable json formatting of output
5684 """
5685 try:
5686 cmdStr = "vpls list"
5687 if jsonFormat:
5688 raise NotImplementedError
5689 cmdStr += " -j"
5690 handle = self.sendline( cmdStr )
5691 assert handle is not None, "Error in sendline"
5692 assert "Command not found:" not in handle, handle
5693 return handle
5694 except AssertionError:
5695 main.log.exception( "" )
5696 return None
5697 except TypeError:
5698 main.log.exception( self.name + ": Object not as expected" )
5699 return None
5700 except pexpect.EOF:
5701 main.log.error( self.name + ": EOF exception found" )
5702 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005703 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005704 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005705 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005706 return None
5707 except Exception:
5708 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005709 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005710
5711 def vplsCreate( self, network ):
5712 """
5713 CLI command to create a new VPLS network.
5714 Required arguments:
5715 network - String name of the network to create.
5716 returns:
5717 main.TRUE on success and main.FALSE on failure
5718 """
5719 try:
5720 network = str( network )
5721 cmdStr = "vpls create "
5722 cmdStr += network
5723 output = self.sendline( cmdStr )
5724 assert output is not None, "Error in sendline"
5725 assert "Command not found:" not in output, output
5726 assert "Error executing command" not in output, output
5727 assert "VPLS already exists:" not in output, output
5728 return main.TRUE
5729 except AssertionError:
5730 main.log.exception( "" )
5731 return main.FALSE
5732 except TypeError:
5733 main.log.exception( self.name + ": Object not as expected" )
5734 return main.FALSE
5735 except pexpect.EOF:
5736 main.log.error( self.name + ": EOF exception found" )
5737 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005738 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005739 except Exception:
5740 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005741 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005742
5743 def vplsDelete( self, network ):
5744 """
5745 CLI command to delete a VPLS network.
5746 Required arguments:
5747 network - Name of the network to delete.
5748 returns:
5749 main.TRUE on success and main.FALSE on failure
5750 """
5751 try:
5752 network = str( network )
5753 cmdStr = "vpls delete "
5754 cmdStr += network
5755 output = self.sendline( cmdStr )
5756 assert output is not None, "Error in sendline"
5757 assert "Command not found:" not in output, output
5758 assert "Error executing command" not in output, output
5759 assert " not found" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005760 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005761 return main.TRUE
5762 except AssertionError:
5763 main.log.exception( "" )
5764 return main.FALSE
5765 except TypeError:
5766 main.log.exception( self.name + ": Object not as expected" )
5767 return main.FALSE
5768 except pexpect.EOF:
5769 main.log.error( self.name + ": EOF exception found" )
5770 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005771 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005772 except Exception:
5773 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005774 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005775
5776 def vplsAddIface( self, network, iface ):
5777 """
5778 CLI command to add an interface to a VPLS network.
5779 Required arguments:
5780 network - Name of the network to add the interface to.
5781 iface - The ONOS name for an interface.
5782 returns:
5783 main.TRUE on success and main.FALSE on failure
5784 """
5785 try:
5786 network = str( network )
5787 iface = str( iface )
5788 cmdStr = "vpls add-if "
5789 cmdStr += network + " " + iface
5790 output = self.sendline( cmdStr )
5791 assert output is not None, "Error in sendline"
5792 assert "Command not found:" not in output, output
5793 assert "Error executing command" not in output, output
5794 assert "already associated to network" not in output, output
5795 assert "Interface cannot be added." not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005796 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005797 return main.TRUE
5798 except AssertionError:
5799 main.log.exception( "" )
5800 return main.FALSE
5801 except TypeError:
5802 main.log.exception( self.name + ": Object not as expected" )
5803 return main.FALSE
5804 except pexpect.EOF:
5805 main.log.error( self.name + ": EOF exception found" )
5806 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005807 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005808 except Exception:
5809 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005810 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005811
5812 def vplsRemIface( self, network, iface ):
5813 """
5814 CLI command to remove an interface from a VPLS network.
5815 Required arguments:
5816 network - Name of the network to remove the interface from.
5817 iface - Name of the interface to remove.
5818 returns:
5819 main.TRUE on success and main.FALSE on failure
5820 """
5821 try:
5822 iface = str( iface )
5823 cmdStr = "vpls rem-if "
5824 cmdStr += network + " " + iface
5825 output = self.sendline( cmdStr )
5826 assert output is not None, "Error in sendline"
5827 assert "Command not found:" not in output, output
5828 assert "Error executing command" not in output, output
5829 assert "is not configured" not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005830 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005831 return main.TRUE
5832 except AssertionError:
5833 main.log.exception( "" )
5834 return main.FALSE
5835 except TypeError:
5836 main.log.exception( self.name + ": Object not as expected" )
5837 return main.FALSE
5838 except pexpect.EOF:
5839 main.log.error( self.name + ": EOF exception found" )
5840 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005841 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005842 except Exception:
5843 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005844 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005845
5846 def vplsClean( self ):
5847 """
5848 Description: Clears the VPLS app configuration.
5849 Returns: main.TRUE on success and main.FALSE on failure
5850 """
5851 try:
5852 cmdStr = "vpls clean"
5853 handle = self.sendline( cmdStr )
5854 assert handle is not None, "Error in sendline"
5855 assert "Command not found:" not in handle, handle
Jon Hallcf97cf12017-06-06 09:37:51 -07005856 assert "still updating" not in handle, handle
Jon Hall2c8959e2016-12-16 12:17:34 -08005857 return handle
5858 except AssertionError:
5859 main.log.exception( "" )
5860 return main.FALSE
5861 except TypeError:
5862 main.log.exception( self.name + ": Object not as expected" )
5863 return main.FALSE
5864 except pexpect.EOF:
5865 main.log.error( self.name + ": EOF exception found" )
5866 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005867 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005868 except Exception:
5869 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005870 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005871
5872 def vplsSetEncap( self, network, encapType ):
5873 """
5874 CLI command to add an interface to a VPLS network.
5875 Required arguments:
5876 network - Name of the network to create.
5877 encapType - Type of encapsulation.
5878 returns:
5879 main.TRUE on success and main.FALSE on failure
5880 """
5881 try:
5882 network = str( network )
5883 encapType = str( encapType ).upper()
5884 assert encapType in [ "MPLS", "VLAN", "NONE" ], "Incorrect type"
5885 cmdStr = "vpls set-encap "
5886 cmdStr += network + " " + encapType
5887 output = self.sendline( cmdStr )
5888 assert output is not None, "Error in sendline"
5889 assert "Command not found:" not in output, output
5890 assert "Error executing command" not in output, output
5891 assert "already associated to network" not in output, output
5892 assert "Encapsulation type " not in output, output
Jon Hallcf97cf12017-06-06 09:37:51 -07005893 assert "still updating" not in output, output
Jon Hall2c8959e2016-12-16 12:17:34 -08005894 return main.TRUE
5895 except AssertionError:
5896 main.log.exception( "" )
5897 return main.FALSE
5898 except TypeError:
5899 main.log.exception( self.name + ": Object not as expected" )
5900 return main.FALSE
5901 except pexpect.EOF:
5902 main.log.error( self.name + ": EOF exception found" )
5903 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005904 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005905 except Exception:
5906 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005907 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005908
5909 def interfaces( self, jsonFormat=True ):
5910 """
5911 Description: Returns result of interfaces command.
5912 Optional:
5913 * jsonFormat: enable json formatting of output
5914 Returns:
5915 The output of the command or None on error.
5916 """
5917 try:
5918 cmdStr = "interfaces"
5919 if jsonFormat:
Jon Halle0f0b342017-04-18 11:43:47 -07005920 raise NotImplementedError
Jon Hall2c8959e2016-12-16 12:17:34 -08005921 cmdStr += " -j"
5922 handle = self.sendline( cmdStr )
5923 assert handle is not None, "Error in sendline"
5924 assert "Command not found:" not in handle, handle
5925 return handle
5926 except AssertionError:
5927 main.log.exception( "" )
5928 return None
5929 except TypeError:
5930 main.log.exception( self.name + ": Object not as expected" )
5931 return None
5932 except pexpect.EOF:
5933 main.log.error( self.name + ": EOF exception found" )
5934 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07005935 main.cleanAndExit()
Jon Hall2c8959e2016-12-16 12:17:34 -08005936 except NotImplementedError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005937 main.log.exception( self.name + ": Json output not supported" )
Jon Hall2c8959e2016-12-16 12:17:34 -08005938 return None
5939 except Exception:
5940 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07005941 main.cleanAndExit()
Chiyu Chengec63bde2016-11-17 18:11:36 -08005942
5943 def getTimeStampFromLog( self, mode, searchTerm, splitTerm_before, splitTerm_after, startLine='', logNum=1 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005944 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005945 Get the timestamp of searchTerm from karaf log.
5946
5947 Arguments:
5948 splitTerm_before and splitTerm_after:
5949
5950 The terms that split the string that contains the timeStamp of
5951 searchTerm. For example, if that string is "xxxxxxxcreationTime =
5952 1419510501xxxxxx", then the splitTerm_before is "CreationTime = "
5953 and the splitTerm_after is "x"
5954
5955 others:
Jon Halle0f0b342017-04-18 11:43:47 -07005956 Please look at the "logsearch" Function in onosclidriver.py
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00005957 '''
Chiyu Chengec63bde2016-11-17 18:11:36 -08005958 if logNum < 0:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005959 main.log.error( "Get wrong log number ")
Chiyu Chengec63bde2016-11-17 18:11:36 -08005960 return main.ERROR
5961 lines = self.logSearch( mode=mode, searchTerm=searchTerm, startLine=startLine, logNum=logNum )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005962 if len( lines ) == 0:
Chiyu Chengec63bde2016-11-17 18:11:36 -08005963 main.log.warn( "Captured timestamp string is empty" )
5964 return main.ERROR
5965 lines = lines[ 0 ]
5966 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07005967 assert isinstance( lines, str )
Chiyu Chengec63bde2016-11-17 18:11:36 -08005968 # get the target value
5969 line = lines.split( splitTerm_before )
5970 key = line[ 1 ].split( splitTerm_after )
5971 return int( key[ 0 ] )
5972 except IndexError:
5973 main.log.warn( "Index Error!" )
5974 return main.ERROR
5975 except AssertionError:
5976 main.log.warn( "Search Term Not Found " )
5977 return main.ERROR
Jon Halle0f0b342017-04-18 11:43:47 -07005978
5979 def workQueueAdd( self, queueName, value ):
5980 """
5981 CLI command to add a string to the specified Work Queue.
5982 This function uses the distributed primitives test app, which
5983 gives some cli access to distributed primitives for testing
5984 purposes only.
5985
5986 Required arguments:
5987 queueName - The name of the queue to add to
5988 value - The value to add to the queue
5989 returns:
5990 main.TRUE on success, main.FALSE on failure and
5991 main.ERROR on error.
5992 """
5993 try:
5994 queueName = str( queueName )
5995 value = str( value )
5996 prefix = "work-queue-test"
5997 operation = "add"
5998 cmdStr = " ".join( [ prefix, queueName, operation, value ] )
5999 output = self.distPrimitivesSend( cmdStr )
6000 if "Invalid operation name" in output:
6001 main.log.warn( output )
6002 return main.ERROR
6003 elif "Done" in output:
6004 return main.TRUE
6005 except TypeError:
6006 main.log.exception( self.name + ": Object not as expected" )
6007 return main.ERROR
6008 except Exception:
6009 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006010 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006011
6012 def workQueueAddMultiple( self, queueName, value1, value2 ):
6013 """
6014 CLI command to add two strings to the specified Work Queue.
6015 This function uses the distributed primitives test app, which
6016 gives some cli access to distributed primitives for testing
6017 purposes only.
6018
6019 Required arguments:
6020 queueName - The name of the queue to add to
6021 value1 - The first value to add to the queue
6022 value2 - The second value to add to the queue
6023 returns:
6024 main.TRUE on success, main.FALSE on failure and
6025 main.ERROR on error.
6026 """
6027 try:
6028 queueName = str( queueName )
6029 value1 = str( value1 )
6030 value2 = str( value2 )
6031 prefix = "work-queue-test"
6032 operation = "addMultiple"
6033 cmdStr = " ".join( [ prefix, queueName, operation, value1, value2 ] )
6034 output = self.distPrimitivesSend( cmdStr )
6035 if "Invalid operation name" in output:
6036 main.log.warn( output )
6037 return main.ERROR
6038 elif "Done" in output:
6039 return main.TRUE
6040 except TypeError:
6041 main.log.exception( self.name + ": Object not as expected" )
6042 return main.ERROR
6043 except Exception:
6044 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006045 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006046
6047 def workQueueTakeAndComplete( self, queueName, number=1 ):
6048 """
6049 CLI command to take a value from the specified Work Queue and compelte it.
6050 This function uses the distributed primitives test app, which
6051 gives some cli access to distributed primitives for testing
6052 purposes only.
6053
6054 Required arguments:
6055 queueName - The name of the queue to add to
6056 number - The number of items to take and complete
6057 returns:
6058 main.TRUE on success, main.FALSE on failure and
6059 main.ERROR on error.
6060 """
6061 try:
6062 queueName = str( queueName )
6063 number = str( int( number ) )
6064 prefix = "work-queue-test"
6065 operation = "takeAndComplete"
6066 cmdStr = " ".join( [ prefix, queueName, operation, number ] )
6067 output = self.distPrimitivesSend( cmdStr )
6068 if "Invalid operation name" in output:
6069 main.log.warn( output )
6070 return main.ERROR
6071 elif "Done" in output:
6072 return main.TRUE
6073 except TypeError:
6074 main.log.exception( self.name + ": Object not as expected" )
6075 return main.ERROR
6076 except Exception:
6077 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006078 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006079
6080 def workQueueDestroy( self, queueName ):
6081 """
6082 CLI command to destroy the specified Work Queue.
6083 This function uses the distributed primitives test app, which
6084 gives some cli access to distributed primitives for testing
6085 purposes only.
6086
6087 Required arguments:
6088 queueName - The name of the queue to add to
6089 returns:
6090 main.TRUE on success, main.FALSE on failure and
6091 main.ERROR on error.
6092 """
6093 try:
6094 queueName = str( queueName )
6095 prefix = "work-queue-test"
6096 operation = "destroy"
6097 cmdStr = " ".join( [ prefix, queueName, operation ] )
6098 output = self.distPrimitivesSend( cmdStr )
6099 if "Invalid operation name" in output:
6100 main.log.warn( output )
6101 return main.ERROR
6102 return main.TRUE
6103 except TypeError:
6104 main.log.exception( self.name + ": Object not as expected" )
6105 return main.ERROR
6106 except Exception:
6107 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006108 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006109
6110 def workQueueTotalPending( self, queueName ):
6111 """
6112 CLI command to get the Total Pending items of the specified Work Queue.
6113 This function uses the distributed primitives test app, which
6114 gives some cli access to distributed primitives for testing
6115 purposes only.
6116
6117 Required arguments:
6118 queueName - The name of the queue to add to
6119 returns:
6120 The number of Pending items in the specified work queue or
6121 None on error
6122 """
6123 try:
6124 queueName = str( queueName )
6125 prefix = "work-queue-test"
6126 operation = "totalPending"
6127 cmdStr = " ".join( [ prefix, queueName, operation ] )
6128 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006129 main.log.debug( self.name + ": work queue unparsed: " + output )
6130 output = output.split( "\r\n" )[ -1 ]
6131 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006132 pattern = r'\d+'
6133 if "Invalid operation name" in output:
6134 main.log.warn( output )
6135 return None
6136 else:
6137 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006138 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006139 except ( AttributeError, TypeError ):
6140 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6141 return None
6142 except Exception:
6143 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006144 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006145
6146 def workQueueTotalCompleted( self, queueName ):
6147 """
6148 CLI command to get the Total Completed items of the specified Work Queue.
6149 This function uses the distributed primitives test app, which
6150 gives some cli access to distributed primitives for testing
6151 purposes only.
6152
6153 Required arguments:
6154 queueName - The name of the queue to add to
6155 returns:
6156 The number of complete items in the specified work queue or
6157 None on error
6158 """
6159 try:
6160 queueName = str( queueName )
6161 prefix = "work-queue-test"
6162 operation = "totalCompleted"
6163 cmdStr = " ".join( [ prefix, queueName, operation ] )
6164 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006165 main.log.debug( self.name + ": work queue unparsed: " + output )
6166 output = output.split( "\r\n" )[ -1 ]
6167 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006168 pattern = r'\d+'
6169 if "Invalid operation name" in output:
6170 main.log.warn( output )
6171 return None
6172 else:
6173 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006174 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006175 except ( AttributeError, TypeError ):
6176 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6177 return None
6178 except Exception:
6179 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006180 main.cleanAndExit()
Jon Halle0f0b342017-04-18 11:43:47 -07006181
6182 def workQueueTotalInProgress( self, queueName ):
6183 """
6184 CLI command to get the Total In Progress items of the specified Work Queue.
6185 This function uses the distributed primitives test app, which
6186 gives some cli access to distributed primitives for testing
6187 purposes only.
6188
6189 Required arguments:
6190 queueName - The name of the queue to add to
6191 returns:
6192 The number of In Progress items in the specified work queue or
6193 None on error
6194 """
6195 try:
6196 queueName = str( queueName )
6197 prefix = "work-queue-test"
6198 operation = "totalInProgress"
6199 cmdStr = " ".join( [ prefix, queueName, operation ] )
6200 output = self.distPrimitivesSend( cmdStr )
Jon Hall22e94ce2019-01-15 14:52:17 -08006201 main.log.debug( self.name + ": work queue unparsed: " + output )
6202 output = output.split( "\r\n" )[ -1 ]
6203 main.log.debug( self.name + ": work queue parsed: " + output )
Jon Halle0f0b342017-04-18 11:43:47 -07006204 pattern = r'\d+'
6205 if "Invalid operation name" in output:
6206 main.log.warn( output )
6207 return None
6208 else:
6209 match = re.search( pattern, output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07006210 return match.group( 0 )
Jon Halle0f0b342017-04-18 11:43:47 -07006211 except ( AttributeError, TypeError ):
6212 main.log.exception( self.name + ": Object not as expected; " + str( output ) )
6213 return None
6214 except Exception:
6215 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07006216 main.cleanAndExit()
Jeremy Ronquillo818bc7c2017-08-09 17:14:53 +00006217
6218 def events( self, args='-a' ):
6219 """
6220 Description: Returns events -a command output
6221 Optional:
6222 add other arguments
6223 """
6224 try:
6225 cmdStr = "events"
6226 if args:
6227 cmdStr += " " + args
6228 handle = self.sendline( cmdStr )
6229 assert handle is not None, "Error in sendline"
6230 assert "Command not found:" not in handle, handle
6231 return handle
6232 except AssertionError:
6233 main.log.exception( "" )
6234 return None
6235 except TypeError:
6236 main.log.exception( self.name + ": Object not as expected" )
6237 return None
6238 except pexpect.EOF:
6239 main.log.error( self.name + ": EOF exception found" )
6240 main.log.error( self.name + ": " + self.handle.before )
6241 main.cleanAndExit()
6242 except Exception:
6243 main.log.exception( self.name + ": Uncaught exception!" )
6244 main.cleanAndExit()
6245
6246 def getMaster( self, deviceID ):
6247 """
6248 Description: Obtains current master using "roles" command for a specific deviceID
6249 """
6250 try:
6251 return str( self.getRole( deviceID )[ 'master' ] )
6252 except AssertionError:
6253 main.log.exception( "" )
6254 return None
6255 except TypeError:
6256 main.log.exception( self.name + ": Object not as expected" )
6257 return None
6258 except pexpect.EOF:
6259 main.log.error( self.name + ": EOF exception found" )
6260 main.log.error( self.name + ": " + self.handle.before )
6261 main.cleanAndExit()
6262 except Exception:
6263 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lime6fe3c42017-10-18 16:28:40 -07006264 main.cleanAndExit()
Jon Halla478b852017-12-04 15:00:15 -08006265
6266 def issu( self ):
6267 """
6268 Short summary of In-Service Software Upgrade status
6269
6270 Returns the output of the cli command or None on Error
6271 """
6272 try:
6273 cmdStr = "issu"
6274 handle = self.sendline( cmdStr )
6275 assert handle is not None, "Error in sendline"
6276 assert "Command not found:" not in handle, handle
6277 assert "Unsupported command:" not in handle, handle
6278 return handle
6279 except AssertionError:
6280 main.log.exception( "" )
6281 return None
6282 except TypeError:
6283 main.log.exception( self.name + ": Object not as expected" )
6284 return None
6285 except pexpect.EOF:
6286 main.log.error( self.name + ": EOF exception found" )
6287 main.log.error( self.name + ": " + self.handle.before )
6288 main.cleanAndExit()
6289 except Exception:
6290 main.log.exception( self.name + ": Uncaught exception!" )
6291 main.cleanAndExit()
6292
6293 def issuInit( self ):
6294 """
6295 Initiates an In-Service Software Upgrade
6296
6297 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6298 """
6299 try:
6300 cmdStr = "issu init"
6301 handle = self.sendline( cmdStr )
6302 assert handle is not None, "Error in sendline"
6303 assert "Command not found:" not in handle, handle
6304 assert "Unsupported command:" not in handle, handle
6305 if "Initialized" in handle:
6306 return main.TRUE
6307 else:
6308 return main.FALSE
6309 except AssertionError:
6310 main.log.exception( "" )
6311 return main.ERROR
6312 except TypeError:
6313 main.log.exception( self.name + ": Object not as expected" )
6314 return main.ERROR
6315 except pexpect.EOF:
6316 main.log.error( self.name + ": EOF exception found" )
6317 main.log.error( self.name + ": " + self.handle.before )
6318 main.cleanAndExit()
6319 except Exception:
6320 main.log.exception( self.name + ": Uncaught exception!" )
6321 main.cleanAndExit()
6322
6323 def issuUpgrade( self ):
6324 """
6325 Transitions stores to upgraded nodes
6326
6327 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6328 """
6329 try:
6330 cmdStr = "issu upgrade"
6331 handle = self.sendline( cmdStr )
6332 assert handle is not None, "Error in sendline"
6333 assert "Command not found:" not in handle, handle
6334 assert "Unsupported command:" not in handle, handle
6335 if "Upgraded" in handle:
6336 return main.TRUE
6337 else:
6338 return main.FALSE
6339 except AssertionError:
6340 main.log.exception( "" )
6341 return main.ERROR
6342 except TypeError:
6343 main.log.exception( self.name + ": Object not as expected" )
6344 return main.ERROR
6345 except pexpect.EOF:
6346 main.log.error( self.name + ": EOF exception found" )
6347 main.log.error( self.name + ": " + self.handle.before )
6348 main.cleanAndExit()
6349 except Exception:
6350 main.log.exception( self.name + ": Uncaught exception!" )
6351 main.cleanAndExit()
6352
6353 def issuCommit( self ):
6354 """
6355 Finalizes an In-Service Software Upgrade
6356
6357 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6358 """
6359 try:
6360 cmdStr = "issu commit"
6361 handle = self.sendline( cmdStr )
6362 assert handle is not None, "Error in sendline"
6363 assert "Command not found:" not in handle, handle
6364 assert "Unsupported command:" not in handle, handle
6365 # TODO: Check the version returned by this command
6366 if "Committed version" in handle:
6367 return main.TRUE
6368 else:
6369 return main.FALSE
6370 except AssertionError:
6371 main.log.exception( "" )
6372 return main.ERROR
6373 except TypeError:
6374 main.log.exception( self.name + ": Object not as expected" )
6375 return main.ERROR
6376 except pexpect.EOF:
6377 main.log.error( self.name + ": EOF exception found" )
6378 main.log.error( self.name + ": " + self.handle.before )
6379 main.cleanAndExit()
6380 except Exception:
6381 main.log.exception( self.name + ": Uncaught exception!" )
6382 main.cleanAndExit()
6383
6384 def issuRollback( self ):
6385 """
6386 Rolls back an In-Service Software Upgrade
6387
6388 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6389 """
6390 try:
6391 cmdStr = "issu rollback"
6392 handle = self.sendline( cmdStr )
6393 assert handle is not None, "Error in sendline"
6394 assert "Command not found:" not in handle, handle
6395 assert "Unsupported command:" not in handle, handle
6396 # TODO: Check the version returned by this command
6397 if "Rolled back to version" in handle:
6398 return main.TRUE
6399 else:
6400 return main.FALSE
6401 except AssertionError:
6402 main.log.exception( "" )
6403 return main.ERROR
6404 except TypeError:
6405 main.log.exception( self.name + ": Object not as expected" )
6406 return main.ERROR
6407 except pexpect.EOF:
6408 main.log.error( self.name + ": EOF exception found" )
6409 main.log.error( self.name + ": " + self.handle.before )
6410 main.cleanAndExit()
6411 except Exception:
6412 main.log.exception( self.name + ": Uncaught exception!" )
6413 main.cleanAndExit()
6414
6415 def issuReset( self ):
6416 """
6417 Resets the In-Service Software Upgrade status after a rollback
6418
6419 Returns main.TRUE on success, main.ERROR on error, else main.FALSE
6420 """
6421 try:
6422 cmdStr = "issu reset"
6423 handle = self.sendline( cmdStr )
6424 assert handle is not None, "Error in sendline"
6425 assert "Command not found:" not in handle, handle
6426 assert "Unsupported command:" not in handle, handle
6427 # TODO: Check the version returned by this command
6428 if "Reset version" in handle:
6429 return main.TRUE
6430 else:
6431 return main.FALSE
6432 except AssertionError:
6433 main.log.exception( "" )
6434 return main.ERROR
6435 except TypeError:
6436 main.log.exception( self.name + ": Object not as expected" )
6437 return main.ERROR
6438 except pexpect.EOF:
6439 main.log.error( self.name + ": EOF exception found" )
6440 main.log.error( self.name + ": " + self.handle.before )
6441 main.cleanAndExit()
6442 except Exception:
6443 main.log.exception( self.name + ": Uncaught exception!" )
6444 main.cleanAndExit()
6445
6446 def issuStatus( self ):
6447 """
6448 Status of an In-Service Software Upgrade
6449
6450 Returns the output of the cli command or None on Error
6451 """
6452 try:
6453 cmdStr = "issu status"
6454 handle = self.sendline( cmdStr )
6455 assert handle is not None, "Error in sendline"
6456 assert "Command not found:" not in handle, handle
6457 assert "Unsupported command:" not in handle, handle
6458 return handle
6459 except AssertionError:
6460 main.log.exception( "" )
6461 return None
6462 except TypeError:
6463 main.log.exception( self.name + ": Object not as expected" )
6464 return None
6465 except pexpect.EOF:
6466 main.log.error( self.name + ": EOF exception found" )
6467 main.log.error( self.name + ": " + self.handle.before )
6468 main.cleanAndExit()
6469 except Exception:
6470 main.log.exception( self.name + ": Uncaught exception!" )
6471 main.cleanAndExit()
6472
6473 def issuVersion( self ):
6474 """
6475 Get the version of an In-Service Software Upgrade
6476
6477 Returns the output of the cli command or None on Error
6478 """
6479 try:
6480 cmdStr = "issu version"
6481 handle = self.sendline( cmdStr )
6482 assert handle is not None, "Error in sendline"
6483 assert "Command not found:" not in handle, handle
6484 assert "Unsupported command:" not in handle, handle
6485 return handle
6486 except AssertionError:
6487 main.log.exception( "" )
6488 return None
6489 except TypeError:
6490 main.log.exception( self.name + ": Object not as expected" )
6491 return None
6492 except pexpect.EOF:
6493 main.log.error( self.name + ": EOF exception found" )
6494 main.log.error( self.name + ": " + self.handle.before )
6495 main.cleanAndExit()
6496 except Exception:
6497 main.log.exception( self.name + ": Uncaught exception!" )
6498 main.cleanAndExit()
You Wange24d6272018-03-27 21:18:50 -07006499
6500 def mcastJoin( self, sIP, groupIP, sPort, dPorts ):
6501 """
6502 Create a multicast route by calling 'mcast-join' command
6503 sIP: source IP of the multicast route
6504 groupIP: group IP of the multicast route
6505 sPort: source port (e.g. of:0000000000000001/3 ) of the multicast route
6506 dPorts: a list of destination ports of the multicast route
6507 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6508 """
6509 try:
6510 cmdStr = "mcast-join"
6511 cmdStr += " " + str( sIP )
6512 cmdStr += " " + str( groupIP )
6513 cmdStr += " " + str( sPort )
6514 assert isinstance( dPorts, list )
6515 for dPort in dPorts:
6516 cmdStr += " " + str( dPort )
6517 handle = self.sendline( cmdStr )
6518 assert handle is not None, "Error in sendline"
6519 assert "Command not found:" not in handle, handle
6520 assert "Unsupported command:" not in handle, handle
6521 assert "Error executing command" not in handle, handle
6522 if "Added the mcast route" in handle:
6523 return main.TRUE
6524 else:
6525 return main.FALSE
6526 except AssertionError:
6527 main.log.exception( "" )
6528 return None
6529 except TypeError:
6530 main.log.exception( self.name + ": Object not as expected" )
6531 return None
6532 except pexpect.EOF:
6533 main.log.error( self.name + ": EOF exception found" )
6534 main.log.error( self.name + ": " + self.handle.before )
6535 main.cleanAndExit()
6536 except Exception:
6537 main.log.exception( self.name + ": Uncaught exception!" )
6538 main.cleanAndExit()
6539
6540 def mcastDelete( self, sIP, groupIP, dPorts ):
6541 """
6542 Delete a multicast route by calling 'mcast-delete' command
6543 sIP: source IP of the multicast route
6544 groupIP: group IP of the multicast route
6545 dPorts: a list of destination ports of the multicast route
6546 Returns main.TRUE if mcast route is deleted; Otherwise main.FALSE
6547 """
6548 try:
6549 cmdStr = "mcast-delete"
6550 cmdStr += " " + str( sIP )
6551 cmdStr += " " + str( groupIP )
6552 assert isinstance( dPorts, list )
6553 for dPort in dPorts:
6554 cmdStr += " " + str( dPort )
6555 handle = self.sendline( cmdStr )
6556 assert handle is not None, "Error in sendline"
6557 assert "Command not found:" not in handle, handle
6558 assert "Unsupported command:" not in handle, handle
6559 assert "Error executing command" not in handle, handle
6560 if "Updated the mcast route" in handle:
6561 return main.TRUE
6562 else:
6563 return main.FALSE
6564 except AssertionError:
6565 main.log.exception( "" )
6566 return None
6567 except TypeError:
6568 main.log.exception( self.name + ": Object not as expected" )
6569 return None
6570 except pexpect.EOF:
6571 main.log.error( self.name + ": EOF exception found" )
6572 main.log.error( self.name + ": " + self.handle.before )
6573 main.cleanAndExit()
6574 except Exception:
6575 main.log.exception( self.name + ": Uncaught exception!" )
6576 main.cleanAndExit()
6577
6578 def mcastHostJoin( self, sAddr, gAddr, srcs, sinks ):
6579 """
6580 Create a multicast route by calling 'mcast-host-join' command
6581 sAddr: we can provide * for ASM or a specific address for SSM
6582 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006583 srcs: a list of HostId of the sources e.g. ["00:AA:00:00:00:01/None"]
You Wange24d6272018-03-27 21:18:50 -07006584 sinks: a list of HostId of the sinks e.g. ["00:AA:00:00:01:05/40"]
6585 Returns main.TRUE if mcast route is added; Otherwise main.FALSE
6586 """
6587 try:
6588 cmdStr = "mcast-host-join"
6589 cmdStr += " -sAddr " + str( sAddr )
6590 cmdStr += " -gAddr " + str( gAddr )
6591 assert isinstance( srcs, list )
6592 for src in srcs:
6593 cmdStr += " -srcs " + str( src )
6594 assert isinstance( sinks, list )
6595 for sink in sinks:
6596 cmdStr += " -sinks " + str( sink )
6597 handle = self.sendline( cmdStr )
6598 assert handle is not None, "Error in sendline"
6599 assert "Command not found:" not in handle, handle
6600 assert "Unsupported command:" not in handle, handle
6601 assert "Error executing command" not in handle, handle
6602 if "Added the mcast route" in handle:
6603 return main.TRUE
6604 else:
6605 return main.FALSE
6606 except AssertionError:
6607 main.log.exception( "" )
6608 return None
6609 except TypeError:
6610 main.log.exception( self.name + ": Object not as expected" )
6611 return None
6612 except pexpect.EOF:
6613 main.log.error( self.name + ": EOF exception found" )
6614 main.log.error( self.name + ": " + self.handle.before )
6615 main.cleanAndExit()
6616 except Exception:
6617 main.log.exception( self.name + ": Uncaught exception!" )
6618 main.cleanAndExit()
6619
6620 def mcastHostDelete( self, sAddr, gAddr, host=None ):
6621 """
6622 Delete multicast sink(s) by calling 'mcast-host-delete' command
6623 sAddr: we can provide * for ASM or a specific address for SSM
6624 gAddr: specifies multicast group address
You Wangc02d8352018-04-17 16:42:10 -07006625 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
You Wange24d6272018-03-27 21:18:50 -07006626 will delete the route if not specified
6627 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6628 """
6629 try:
6630 cmdStr = "mcast-host-delete"
6631 cmdStr += " -sAddr " + str( sAddr )
6632 cmdStr += " -gAddr " + str( gAddr )
6633 if host:
6634 cmdStr += " -h " + str( host )
6635 handle = self.sendline( cmdStr )
6636 assert handle is not None, "Error in sendline"
6637 assert "Command not found:" not in handle, handle
6638 assert "Unsupported command:" not in handle, handle
6639 assert "Error executing command" not in handle, handle
6640 if "Updated the mcast route" in handle:
6641 return main.TRUE
6642 elif "Deleted the mcast route" in handle:
6643 return main.TRUE
6644 else:
6645 return main.FALSE
6646 except AssertionError:
6647 main.log.exception( "" )
6648 return None
6649 except TypeError:
6650 main.log.exception( self.name + ": Object not as expected" )
6651 return None
6652 except pexpect.EOF:
6653 main.log.error( self.name + ": EOF exception found" )
6654 main.log.error( self.name + ": " + self.handle.before )
6655 main.cleanAndExit()
6656 except Exception:
6657 main.log.exception( self.name + ": Uncaught exception!" )
6658 main.cleanAndExit()
6659
You Wang547893e2018-05-08 13:34:59 -07006660 def mcastSinkDelete( self, sAddr, gAddr, sink=None ):
6661 """
6662 Delete multicast sink(s) by calling 'mcast-sink-delete' command
6663 sAddr: we can provide * for ASM or a specific address for SSM
6664 gAddr: specifies multicast group address
6665 host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
6666 will delete the route if not specified
6667 Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
6668 """
6669 try:
6670 cmdStr = "mcast-sink-delete"
6671 cmdStr += " -sAddr " + str( sAddr )
6672 cmdStr += " -gAddr " + str( gAddr )
6673 if sink:
6674 cmdStr += " -s " + str( sink )
6675 handle = self.sendline( cmdStr )
6676 assert handle is not None, "Error in sendline"
6677 assert "Command not found:" not in handle, handle
6678 assert "Unsupported command:" not in handle, handle
6679 assert "Error executing command" not in handle, handle
6680 if "Updated the mcast route" in handle:
6681 return main.TRUE
6682 elif "Deleted the mcast route" in handle:
6683 return main.TRUE
6684 else:
6685 return main.FALSE
6686 except AssertionError:
6687 main.log.exception( "" )
6688 return None
6689 except TypeError:
6690 main.log.exception( self.name + ": Object not as expected" )
6691 return None
6692 except pexpect.EOF:
6693 main.log.error( self.name + ": EOF exception found" )
6694 main.log.error( self.name + ": " + self.handle.before )
6695 main.cleanAndExit()
6696 except Exception:
6697 main.log.exception( self.name + ": Uncaught exception!" )
6698 main.cleanAndExit()
6699
You Wange24d6272018-03-27 21:18:50 -07006700 def mcastSourceDelete( self, sAddr, gAddr, srcs=None ):
6701 """
6702 Delete multicast src(s) by calling 'mcast-source-delete' command
6703 sAddr: we can provide * for ASM or a specific address for SSM
6704 gAddr: specifies multicast group address
You Wang547893e2018-05-08 13:34:59 -07006705 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 -07006706 will delete the route if not specified
6707 Returns main.TRUE if mcast sink is deleted; Otherwise main.FALSE
6708 """
6709 try:
6710 cmdStr = "mcast-source-delete"
6711 cmdStr += " -sAddr " + str( sAddr )
6712 cmdStr += " -gAddr " + str( gAddr )
6713 if srcs:
6714 assert isinstance( srcs, list )
6715 for src in srcs:
6716 cmdStr += " -src " + str( src )
6717 handle = self.sendline( cmdStr )
6718 assert handle is not None, "Error in sendline"
6719 assert "Command not found:" not in handle, handle
6720 assert "Unsupported command:" not in handle, handle
6721 assert "Error executing command" not in handle, handle
6722 if "Updated the mcast route" in handle:
6723 return main.TRUE
6724 elif "Deleted the mcast route" in handle:
6725 return main.TRUE
6726 else:
6727 return main.FALSE
6728 except AssertionError:
6729 main.log.exception( "" )
6730 return None
6731 except TypeError:
6732 main.log.exception( self.name + ": Object not as expected" )
6733 return None
6734 except pexpect.EOF:
6735 main.log.error( self.name + ": EOF exception found" )
6736 main.log.error( self.name + ": " + self.handle.before )
6737 main.cleanAndExit()
6738 except Exception:
6739 main.log.exception( self.name + ": Uncaught exception!" )
6740 main.cleanAndExit()
You Wang5da39c82018-04-26 22:55:08 -07006741
6742 def netcfg( self, jsonFormat=True, args="" ):
6743 """
6744 Run netcfg cli command with given args
6745 """
6746 try:
6747 cmdStr = "netcfg"
6748 if jsonFormat:
6749 cmdStr = cmdStr + " -j"
6750 if args:
6751 cmdStr = cmdStr + " " + str( args )
6752 handle = self.sendline( cmdStr )
6753 assert handle is not None, "Error in sendline"
6754 assert "Command not found:" not in handle, handle
6755 assert "Unsupported command:" not in handle, handle
6756 assert "Error executing command" not in handle, handle
6757 return handle
6758 except AssertionError:
6759 main.log.exception( "" )
6760 return None
6761 except TypeError:
6762 main.log.exception( self.name + ": Object not as expected" )
6763 return None
6764 except pexpect.EOF:
6765 main.log.error( self.name + ": EOF exception found" )
6766 main.log.error( self.name + ": " + self.handle.before )
6767 main.cleanAndExit()
6768 except Exception:
6769 main.log.exception( self.name + ": Uncaught exception!" )
6770 main.cleanAndExit()
6771
You Wang0fa76e72018-05-18 11:33:25 -07006772 def composeT3Command( self, sAddr, dAddr, ipv6=False, verbose=True, simple=False ):
You Wang5da39c82018-04-26 22:55:08 -07006773 """
You Wang54b1d672018-06-11 16:44:13 -07006774 Compose and return a list of t3-troubleshoot cli commands for given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006775 Options:
6776 sAddr: IP address of the source host
6777 dAddr: IP address of the destination host
You Wang0fa76e72018-05-18 11:33:25 -07006778 ipv6: True if hosts are IPv6
6779 verbose: return verbose t3 output if True
6780 simple: compose command for t3-troubleshoot-simple if True
You Wang5da39c82018-04-26 22:55:08 -07006781 """
6782 try:
6783 # Collect information of both hosts from onos
6784 hosts = self.hosts()
6785 hosts = json.loads( hosts )
6786 sHost = None
6787 dHost = None
6788 for host in hosts:
6789 if sAddr in host[ "ipAddresses" ]:
6790 sHost = host
6791 elif dAddr in host[ "ipAddresses" ]:
6792 dHost = host
6793 if sHost and dHost:
6794 break
6795 assert sHost, "Not able to find host with IP {}".format( sAddr )
You Wang54b1d672018-06-11 16:44:13 -07006796 cmdList = []
You Wang5d9527b2018-05-29 17:08:54 -07006797 if simple:
6798 assert dHost, "Not able to find host with IP {}".format( dAddr )
You Wang54b1d672018-06-11 16:44:13 -07006799 cmdStr = "t3-troubleshoot-simple"
6800 if verbose:
6801 cmdStr += " -vv"
6802 if ipv6:
6803 cmdStr += " -et ipv6"
You Wang0fa76e72018-05-18 11:33:25 -07006804 cmdStr += " {}/{} {}/{}".format( sHost[ "mac" ], sHost[ "vlan" ], dHost[ "mac" ], dHost[ "vlan" ] )
You Wang54b1d672018-06-11 16:44:13 -07006805 cmdList.append( cmdStr )
You Wang0fa76e72018-05-18 11:33:25 -07006806 else:
You Wang54b1d672018-06-11 16:44:13 -07006807 for location in sHost[ "locations" ]:
6808 cmdStr = "t3-troubleshoot"
6809 if verbose:
6810 cmdStr += " -vv"
6811 if ipv6:
6812 cmdStr += " -et ipv6"
6813 cmdStr += " -s " + str( sAddr )
6814 cmdStr += " -sp " + str( location[ "elementId" ] ) + "/" + str( location[ "port" ] )
6815 cmdStr += " -sm " + str( sHost[ "mac" ] )
6816 if sHost[ "vlan" ] != "None":
6817 cmdStr += " -vid " + sHost[ "vlan" ]
6818 cmdStr += " -d " + str( dAddr )
6819 netcfg = self.netcfg( args="devices {}".format( location[ "elementId" ] ) )
6820 netcfg = json.loads( netcfg )
6821 assert netcfg, "Failed to get netcfg"
6822 cmdStr += " -dm " + str( netcfg[ "segmentrouting" ][ "routerMac" ] )
6823 cmdList.append( cmdStr )
6824 return cmdList
You Wang5da39c82018-04-26 22:55:08 -07006825 except AssertionError:
6826 main.log.exception( "" )
6827 return None
6828 except ( KeyError, TypeError ):
6829 main.log.exception( self.name + ": Object not as expected" )
6830 return None
6831 except Exception:
6832 main.log.exception( self.name + ": Uncaught exception!" )
6833 main.cleanAndExit()
6834
6835 def t3( self, sAddr, dAddr, ipv6=False ):
6836 """
You Wang54b1d672018-06-11 16:44:13 -07006837 Run t3-troubleshoot cli commands for all posible routes given source and destination addresses
You Wang5da39c82018-04-26 22:55:08 -07006838 Options:
6839 sAddr: IP address of the source host
6840 dAddr: IP address of the destination host
6841 """
6842 try:
You Wang54b1d672018-06-11 16:44:13 -07006843 cmdList = self.composeT3Command( sAddr, dAddr, ipv6 )
6844 assert cmdList is not None, "composeT3Command returned None"
6845 t3Output = ""
6846 for cmdStr in cmdList:
6847 handle = self.sendline( cmdStr )
6848 assert handle is not None, "Error in sendline"
6849 assert "Command not found:" not in handle, handle
6850 assert "Unsupported command:" not in handle, handle
6851 assert "Error executing command" not in handle, handle
6852 assert "Tracing packet" in handle
6853 t3Output += handle
6854 return t3Output
You Wang5da39c82018-04-26 22:55:08 -07006855 except AssertionError:
6856 main.log.exception( "" )
6857 return None
6858 except pexpect.EOF:
6859 main.log.error( self.name + ": EOF exception found" )
6860 main.log.error( self.name + ": " + self.handle.before )
6861 main.cleanAndExit()
6862 except Exception:
6863 main.log.exception( self.name + ": Uncaught exception!" )
6864 main.cleanAndExit()
Jon Hall3c0114c2020-08-11 15:07:42 -07006865
6866 def prepareForCLI( self, debug=True, maxRetries=120 ):
6867 """
6868 Prepare docker container to connect to onos cli
6869 """
6870 try:
6871 # Wait for log files to be created
6872 ready = 0
6873 retries = 0
6874 while not ready and retries < maxRetries:
6875 retries += 1
6876 self.handle.sendline( "ls -al /root/onos/apache-karaf-*/data/log" )
6877 ready = self.handle.expect( [ "No such file or directory", self.dockerPrompt ] )
6878 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6879 if not ready:
6880 self.handle.expect( self.dockerPrompt )
6881 time.sleep( 1 )
Jon Hall3c0114c2020-08-11 15:07:42 -07006882
6883 cmdList = []
6884 cmdList.append( "apt-get update" )
6885 cmdList.append( "apt-get install -y openssh-server" )
6886 # Some built in scripts are hardcoded
6887 cmdList.append( "ln -s /root/onos /opt/onos" )
6888 cmdList.append( "ln -s /root/onos/apache-karaf-*/data/log /opt/onos/log" )
6889 cmdList.append( "ls -al /opt/onos" )
6890 output = ""
6891 for cmdStr in cmdList:
6892 self.handle.sendline( cmdStr )
Jon Hall627b1572020-12-01 12:01:15 -08006893 self.handle.expect( self.dockerPrompt, timeout=420 )
Jon Hall3c0114c2020-08-11 15:07:42 -07006894 self.handle.sendline( "" )
6895 self.handle.expect( self.dockerPrompt )
6896 handle = self.handle.before
6897 assert "command not found" not in handle, handle
6898 assert "No such file or directory" not in handle, handle
6899 output += handle
6900 if debug:
6901 main.log.debug( "%s: %s" % ( self.name, output ) )
6902 return output
6903 except AssertionError:
6904 main.log.exception( "" )
6905 return None
6906 except pexpect.EOF:
6907 main.log.error( self.name + ": EOF exception found" )
6908 main.log.error( self.name + ": " + self.handle.before )
6909 main.cleanAndExit()
6910 except Exception:
6911 main.log.exception( self.name + ": Uncaught exception!" )
6912 main.cleanAndExit()
6913
6914 def onosSecureSSH( self, userName="onos", userPWD="rocks" ):
6915 """
6916 Enables secure access to ONOS console
6917 by removing default users & keys.
6918
6919 bin/onos-user-password onos rocks
6920
6921 Returns: main.TRUE on success and main.FALSE on failure
6922 """
6923
6924 try:
6925 self.handle.sendline( "" )
6926 self.handle.expect( self.dockerPrompt )
6927
6928 self.handle.sendline( "[ ! -f ~/.ssh/id_rsa.pub ] && ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' -q" )
6929 self.handle.expect( self.dockerPrompt )
6930 main.log.debug( "%s: %s%s" % ( self.name, self.handle.before, self.handle.after ) )
6931
6932 self.handle.sendline( "bin/onos-user-key $(id -un) $(cut -d\\\\ -f2 ~/.ssh/id_rsa.pub)" )
6933 self.handle.expect( pexpect.TIMEOUT, timeout=10 )
6934 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6935
6936 self.handle.sendline( "bin/onos-user-password %s %s" % ( userName, userPWD ) )
6937 i = self.handle.expect( [ "usage",
6938 self.dockerPrompt,
6939 pexpect.TIMEOUT ] )
6940 if i == 0:
6941 # malformed command
6942 main.log.warn( self.name + ": Could not parse onos-user-password command" )
6943 self.handle.expect( self.dockerPrompt )
6944 return main.FALSE
6945 elif i == 1:
6946 # Process started
6947 main.log.info( self.name + ": SSH password added for user " + userName )
6948 return main.TRUE
6949 elif i == 2:
6950 # timeout
6951 main.log.error( self.name + ": Failed to secure onos ssh " )
6952 main.log.debug( "%s: %s" % ( self.name, self.handle.before ) )
6953 except pexpect.EOF:
6954 main.log.error( self.name + ": EOF exception found" )
6955 main.log.error( self.name + ": " + self.handle.before )
6956 main.cleanAndExit()
6957 except Exception:
6958 main.log.exception( self.name + ": Uncaught exception!" )
6959 main.cleanAndExit()
Jon Hall62ab6752021-08-22 16:47:43 -07006960
6961 def routeAdd( self, prefix, nextHop, jsonFormat=True ):
6962 """
6963 Add a route with the given prefix and nextHop
6964 """
6965 try:
6966 cmdStr = "route-add %s %s %s" % ( "-j" if jsonFormat else "", prefix, nextHop )
6967 handle = self.sendline( cmdStr )
6968 assert handle is not None, "Error in sendline"
6969 assert "Command not found:" not in handle, handle
6970 assert "Unsupported command:" not in handle, handle
6971 assert "Error executing command" not in handle, handle
6972 return handle
6973 except AssertionError:
6974 main.log.exception( "" )
6975 return None
6976 except TypeError:
6977 main.log.exception( self.name + ": Object not as expected" )
6978 return None
6979 except pexpect.EOF:
6980 main.log.error( self.name + ": EOF exception found" )
6981 main.log.error( self.name + ": " + self.handle.before )
6982 main.cleanAndExit()
6983 except Exception:
6984 main.log.exception( self.name + ": Uncaught exception!" )
6985 main.cleanAndExit()
6986
6987 def routeRemove( self, prefix, nextHop, source=None, jsonFormat=True ):
6988 """
6989 Remove a route with the given prefix and nextHop
6990 """
6991 try:
6992 if source:
6993 raise NotImplemented
6994 cmdStr = "route-remove %s %s %s" % ( "-j" if jsonFormat else "", prefix, nextHop )
6995 handle = self.sendline( cmdStr )
6996 assert handle is not None, "Error in sendline"
6997 assert "Command not found:" not in handle, handle
6998 assert "Unsupported command:" not in handle, handle
6999 assert "Error executing command" not in handle, handle
7000 return handle
7001 except AssertionError:
7002 main.log.exception( "" )
7003 return None
7004 except TypeError:
7005 main.log.exception( self.name + ": Object not as expected" )
7006 return None
7007 except pexpect.EOF:
7008 main.log.error( self.name + ": EOF exception found" )
7009 main.log.error( self.name + ": " + self.handle.before )
7010 main.cleanAndExit()
7011 except Exception:
7012 main.log.exception( self.name + ": Uncaught exception!" )
7013 main.cleanAndExit()
7014
7015 def routes( self, jsonFormat=True, args="" ):
7016 """
7017 Get routes from ONOS
7018 """
7019 try:
7020 cmdStr = "routes"
7021 if jsonFormat:
7022 cmdStr = cmdStr + " -j"
7023 handle = self.sendline( cmdStr )
7024 assert handle is not None, "Error in sendline"
7025 assert "Command not found:" not in handle, handle
7026 assert "Unsupported command:" not in handle, handle
7027 assert "Error executing command" not in handle, handle
7028 return handle
7029 except AssertionError:
7030 main.log.exception( "" )
7031 return None
7032 except TypeError:
7033 main.log.exception( self.name + ": Object not as expected" )
7034 return None
7035 except pexpect.EOF:
7036 main.log.error( self.name + ": EOF exception found" )
7037 main.log.error( self.name + ": " + self.handle.before )
7038 main.cleanAndExit()
7039 except Exception:
7040 main.log.exception( self.name + ": Uncaught exception!" )
7041 main.cleanAndExit()