blob: 73b17558eddc762f8fbf5d69773128d7cf11710a [file] [log] [blame]
Jon Hall05b2b432014-10-08 19:53:25 -04001#!/usr/bin/env python
andrewonlabe8e56fd2014-10-09 17:12:44 -04002
kelvin8ec71442015-01-15 16:57:00 -08003"""
4This driver interacts with ONOS bench, the OSGi platform
5that configures the ONOS nodes. ( aka ONOS-next )
andrewonlabe8e56fd2014-10-09 17:12:44 -04006
kelvin8ec71442015-01-15 16:57:00 -08007Please follow the coding style demonstrated by existing
andrewonlabe8e56fd2014-10-09 17:12:44 -04008functions and document properly.
9
10If you are a contributor to the driver, please
11list your email here for future contact:
12
13jhall@onlab.us
14andrew@onlab.us
15
16OCT 9 2014
Jeremy Songsterae01bba2016-07-11 15:39:17 -070017Modified 2016 by ON.Lab
18
19Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
20the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
21or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
andrewonlabe8e56fd2014-10-09 17:12:44 -040022
kelvin8ec71442015-01-15 16:57:00 -080023"""
Jon Hall05b2b432014-10-08 19:53:25 -040024import time
Jon Hall6801cda2015-07-15 14:13:45 -070025import types
Jon Hall05b2b432014-10-08 19:53:25 -040026import pexpect
kelvin-onlaba4074292015-07-09 15:19:49 -070027import os
Jon Hall6c44c0b2016-04-20 15:21:00 -070028import re
29import subprocess
pingping-lin6d23d9e2015-02-02 16:54:24 -080030from requests.models import Response
Jon Hall05b2b432014-10-08 19:53:25 -040031from drivers.common.clidriver import CLI
32
kelvin8ec71442015-01-15 16:57:00 -080033class OnosDriver( CLI ):
Jon Hall05b2b432014-10-08 19:53:25 -040034
kelvin8ec71442015-01-15 16:57:00 -080035 def __init__( self ):
36 """
37 Initialize client
38 """
Jon Hallefbd9792015-03-05 16:11:36 -080039 self.name = None
40 self.home = None
41 self.handle = None
Jon Hall6c44c0b2016-04-20 15:21:00 -070042 self.nicAddr = None
Devin Limdc78e202017-06-09 18:30:07 -070043 super( OnosDriver, self ).__init__()
kelvin8ec71442015-01-15 16:57:00 -080044
45 def connect( self, **connectargs ):
46 """
Jon Hall05b2b432014-10-08 19:53:25 -040047 Creates ssh handle for ONOS "bench".
kelvin-onlaba4074292015-07-09 15:19:49 -070048 NOTE:
49 The ip_address would come from the topo file using the host tag, the
50 value can be an environment variable as well as a "localhost" to get
51 the ip address needed to ssh to the "bench"
kelvin8ec71442015-01-15 16:57:00 -080052 """
Jon Hall05b2b432014-10-08 19:53:25 -040053 try:
Devin Limdc78e202017-06-09 18:30:07 -070054
Jon Hall05b2b432014-10-08 19:53:25 -040055 for key in connectargs:
kelvin8ec71442015-01-15 16:57:00 -080056 vars( self )[ key ] = connectargs[ key ]
andrew@onlab.us3b087132015-03-11 15:00:08 -070057 self.home = "~/onos"
Jon Hall05b2b432014-10-08 19:53:25 -040058 for key in self.options:
59 if key == "home":
kelvin8ec71442015-01-15 16:57:00 -080060 self.home = self.options[ 'home' ]
Jon Hall05b2b432014-10-08 19:53:25 -040061 break
Jon Hall274b6642015-02-17 11:57:17 -080062 if self.home is None or self.home == "":
Jon Halle94919c2015-03-23 11:42:57 -070063 self.home = "~/onos"
Jon Hall21270ac2015-02-16 17:59:55 -080064
kelvin8ec71442015-01-15 16:57:00 -080065 self.name = self.options[ 'name' ]
kelvin-onlaba4074292015-07-09 15:19:49 -070066
kelvin-onlabc2b79102015-07-14 11:41:20 -070067 # The 'nodes' tag is optional and it is not required in .topo file
kelvin-onlaba4074292015-07-09 15:19:49 -070068 for key in self.options:
69 if key == "nodes":
kelvin-onlabc2b79102015-07-14 11:41:20 -070070 # Maximum number of ONOS nodes to run, if there is any
kelvin-onlaba4074292015-07-09 15:19:49 -070071 self.maxNodes = int( self.options[ 'nodes' ] )
72 break
73 self.maxNodes = None
74
Jeremy Ronquillo82705492017-10-18 14:19:55 -070075 if self.maxNodes is None or self.maxNodes == "":
kelvin-onlabc2b79102015-07-14 11:41:20 -070076 self.maxNodes = 100
kelvin-onlaba4074292015-07-09 15:19:49 -070077
kelvin-onlabc2b79102015-07-14 11:41:20 -070078 # Grabs all OC environment variables based on max number of nodes
kelvin-onlaba4074292015-07-09 15:19:49 -070079 self.onosIps = {} # Dictionary of all possible ONOS ip
80
81 try:
82 if self.maxNodes:
kelvin-onlaba4074292015-07-09 15:19:49 -070083 for i in range( self.maxNodes ):
84 envString = "OC" + str( i + 1 )
kelvin-onlabc2b79102015-07-14 11:41:20 -070085 # If there is no more OC# then break the loop
86 if os.getenv( envString ):
87 self.onosIps[ envString ] = os.getenv( envString )
88 else:
89 self.maxNodes = len( self.onosIps )
90 main.log.info( self.name +
91 ": Created cluster data with " +
92 str( self.maxNodes ) +
93 " maximum number" +
94 " of nodes" )
95 break
kelvin-onlaba4074292015-07-09 15:19:49 -070096
97 if not self.onosIps:
98 main.log.info( "Could not read any environment variable"
99 + " please load a cell file with all" +
100 " onos IP" )
Jon Hall5cf14d52015-07-16 12:15:19 -0700101 self.maxNodes = None
kelvin-onlaba4074292015-07-09 15:19:49 -0700102 else:
103 main.log.info( self.name + ": Found " +
104 str( self.onosIps.values() ) +
105 " ONOS IPs" )
kelvin-onlaba4074292015-07-09 15:19:49 -0700106 except KeyError:
107 main.log.info( "Invalid environment variable" )
108 except Exception as inst:
109 main.log.error( "Uncaught exception: " + str( inst ) )
110
111 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700112 if os.getenv( str( self.ip_address ) ) is not None:
kelvin-onlaba4074292015-07-09 15:19:49 -0700113 self.ip_address = os.getenv( str( self.ip_address ) )
114 else:
115 main.log.info( self.name +
116 ": Trying to connect to " +
117 self.ip_address )
kelvin-onlaba4074292015-07-09 15:19:49 -0700118 except KeyError:
119 main.log.info( "Invalid host name," +
120 " connecting to local host instead" )
121 self.ip_address = 'localhost'
122 except Exception as inst:
123 main.log.error( "Uncaught exception: " + str( inst ) )
124
kelvin8ec71442015-01-15 16:57:00 -0800125 self.handle = super( OnosDriver, self ).connect(
126 user_name=self.user_name,
kelvin-onlab08679eb2015-01-21 16:11:48 -0800127 ip_address=self.ip_address,
kelvin-onlabd3b64892015-01-20 13:26:24 -0800128 port=self.port,
129 pwd=self.pwd,
130 home=self.home )
Jon Hall05b2b432014-10-08 19:53:25 -0400131
Jon Hall05b2b432014-10-08 19:53:25 -0400132 if self.handle:
Jon Hall0fc0d452015-07-14 09:49:58 -0700133 self.handle.sendline( "cd " + self.home )
Devin Limc20e79a2017-06-07 10:29:57 -0700134 self.handle.expect( self.prompt )
Jon Hall05b2b432014-10-08 19:53:25 -0400135 return self.handle
kelvin8ec71442015-01-15 16:57:00 -0800136 else:
Jon Hall0fc0d452015-07-14 09:49:58 -0700137 main.log.info( "Failed to create ONOS handle" )
Jon Hall05b2b432014-10-08 19:53:25 -0400138 return main.FALSE
139 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800140 main.log.error( self.name + ": EOF exception found" )
141 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700142 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800143 except Exception:
144 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700145 main.cleanAndExit()
Jon Hall05b2b432014-10-08 19:53:25 -0400146
kelvin8ec71442015-01-15 16:57:00 -0800147 def disconnect( self ):
148 """
Jon Hall05b2b432014-10-08 19:53:25 -0400149 Called when Test is complete to disconnect the ONOS handle.
kelvin8ec71442015-01-15 16:57:00 -0800150 """
Jon Halld61331b2015-02-17 16:35:47 -0800151 response = main.TRUE
Jon Hall05b2b432014-10-08 19:53:25 -0400152 try:
Jon Hall61282e32015-03-19 11:34:11 -0700153 if self.handle:
154 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -0700155 self.handle.expect( self.prompt )
Jon Hall61282e32015-03-19 11:34:11 -0700156 self.handle.sendline( "exit" )
157 self.handle.expect( "closed" )
Jon Hall05b2b432014-10-08 19:53:25 -0400158 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800159 main.log.error( self.name + ": EOF exception found" )
160 main.log.error( self.name + ": " + self.handle.before )
Jon Hall61282e32015-03-19 11:34:11 -0700161 except ValueError:
Jon Hall1a77a1e2015-04-06 10:41:13 -0700162 main.log.exception( "Exception in disconnect of " + self.name )
Jon Hall61282e32015-03-19 11:34:11 -0700163 response = main.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -0800164 except Exception:
165 main.log.exception( self.name + ": Connection failed to the host" )
Jon Hall05b2b432014-10-08 19:53:25 -0400166 response = main.FALSE
167 return response
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400168
andrew@onlab.usaee415a2015-06-05 14:38:58 -0400169 def getEpochMs( self ):
170 """
171 Returns milliseconds since epoch
Jon Hall4ba53f02015-07-29 13:07:41 -0700172
173 When checking multiple nodes in a for loop,
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000174 around a hundred milliseconds of difference (ascending) is
Jon Hall4ba53f02015-07-29 13:07:41 -0700175 generally acceptable due to calltime of the function.
176 Few seconds, however, is not and it means clocks
177 are off sync.
andrew@onlab.usaee415a2015-06-05 14:38:58 -0400178 """
179 try:
180 self.handle.sendline( 'date +%s.%N' )
181 self.handle.expect( 'date \+\%s\.\%N' )
Devin Limdc78e202017-06-09 18:30:07 -0700182 self.handle.expect( self.prompt )
andrew@onlab.usaee415a2015-06-05 14:38:58 -0400183 epochMs = self.handle.before
184 return epochMs
185 except Exception:
186 main.log.exception( 'Uncaught exception getting epoch time' )
Devin Lim44075962017-08-11 10:56:37 -0700187 main.cleanAndExit()
andrew@onlab.usaee415a2015-06-05 14:38:58 -0400188
Jon Hall6c44c0b2016-04-20 15:21:00 -0700189 def onosPackage( self, opTimeout=180 ):
kelvin8ec71442015-01-15 16:57:00 -0800190 """
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400191 Produce a self-contained tar.gz file that can be deployed
Jon Hall64af8502015-12-15 10:09:33 -0800192 and executed on any platform with Java 8 JRE.
kelvin8ec71442015-01-15 16:57:00 -0800193 """
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400194 try:
Jon Hall64af8502015-12-15 10:09:33 -0800195 ret = main.TRUE
kelvin8ec71442015-01-15 16:57:00 -0800196 self.handle.sendline( "onos-package" )
197 self.handle.expect( "onos-package" )
Jon Hall96451092016-05-04 09:42:30 -0700198 while True:
199 i = self.handle.expect( [ "Downloading",
200 "Unknown options",
201 "No such file or directory",
202 "tar.gz",
Devin Limc20e79a2017-06-07 10:29:57 -0700203 self.prompt ],
Jon Hall96451092016-05-04 09:42:30 -0700204 opTimeout )
205 handle = str( self.handle.before + self.handle.after )
206 if i == 0:
207 # Give more time to download the file
208 continue # expect again
209 elif i == 1:
210 # Incorrect usage
211 main.log.error( "onos-package does not recognize the given options" )
212 ret = main.FALSE
213 continue # expect again
214 elif i == 2:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000215 # File(s) not found
Jon Hall96451092016-05-04 09:42:30 -0700216 main.log.error( "onos-package could not find a file or directory" )
217 ret = main.FALSE
218 continue # expect again
219 elif i == 3:
220 # tar.gz
221 continue # expect again
222 elif i == 4:
223 # Prompt returned
224 break
Jon Hallc6793552016-01-19 14:18:37 -0800225 main.log.info( "onos-package command returned: " + handle )
kelvin8ec71442015-01-15 16:57:00 -0800226 # As long as the sendline does not time out,
227 # return true. However, be careful to interpret
228 # the results of the onos-package command return
Jon Hall64af8502015-12-15 10:09:33 -0800229 return ret
230 except pexpect.TIMEOUT:
231 main.log.exception( self.name + ": TIMEOUT exception found in onosPackage" )
232 main.log.error( self.name + ": " + self.handle.before )
233 return main.FALSE
andrewonlab7735d852014-10-09 13:02:47 -0400234 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800235 main.log.error( self.name + ": EOF exception found" )
236 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700237 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800238 except Exception:
239 main.log.exception( "Failed to package ONOS" )
Devin Lim44075962017-08-11 10:56:37 -0700240 main.cleanAndExit()
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400241
kelvin-onlabd3b64892015-01-20 13:26:24 -0800242 def onosBuild( self ):
kelvin8ec71442015-01-15 16:57:00 -0800243 """
andrewonlab8790abb2014-11-06 13:51:54 -0500244 Use the pre defined script to build onos via mvn
kelvin8ec71442015-01-15 16:57:00 -0800245 """
andrewonlab8790abb2014-11-06 13:51:54 -0500246 try:
kelvin8ec71442015-01-15 16:57:00 -0800247 self.handle.sendline( "onos-build" )
248 self.handle.expect( "onos-build" )
249 i = self.handle.expect( [
kelvin-onlabd3b64892015-01-20 13:26:24 -0800250 "BUILD SUCCESS",
251 "ERROR",
252 "BUILD FAILED" ],
253 timeout=120 )
kelvin8ec71442015-01-15 16:57:00 -0800254 handle = str( self.handle.before )
Devin Limc20e79a2017-06-07 10:29:57 -0700255 self.handle.expect( self.prompt )
andrewonlab8790abb2014-11-06 13:51:54 -0500256
kelvin8ec71442015-01-15 16:57:00 -0800257 main.log.info( "onos-build command returned: " +
258 handle )
andrewonlab8790abb2014-11-06 13:51:54 -0500259
260 if i == 0:
261 return main.TRUE
262 else:
263 return handle
264
265 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800266 main.log.error( self.name + ": EOF exception found" )
267 main.log.error( self.name + ": " + self.handle.before )
Jon Hallfebb1c72015-03-05 13:30:09 -0800268 except Exception:
269 main.log.exception( "Failed to build ONOS" )
Devin Lim44075962017-08-11 10:56:37 -0700270 main.cleanAndExit()
andrewonlab8790abb2014-11-06 13:51:54 -0500271
shahshreya9f531fe2015-06-10 12:03:51 -0700272 def cleanInstall( self, skipTest=False, mciTimeout=600 ):
kelvin8ec71442015-01-15 16:57:00 -0800273 """
274 Runs mvn clean install in the root of the ONOS directory.
275 This will clean all ONOS artifacts then compile each module
shahshreya9f531fe2015-06-10 12:03:51 -0700276 Optional:
277 skipTest - Does "-DskipTests -Dcheckstyle.skip -U -T 1C" which
278 skip the test. This will make the building faster.
279 Disregarding the credibility of the build
kelvin8ec71442015-01-15 16:57:00 -0800280 Returns: main.TRUE on success
Jon Hallde9d9aa2014-10-08 20:36:02 -0400281 On Failure, exits the test
kelvin8ec71442015-01-15 16:57:00 -0800282 """
Jon Hallde9d9aa2014-10-08 20:36:02 -0400283 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800284 main.log.info( "Running 'mvn clean install' on " +
285 str( self.name ) +
kelvin8ec71442015-01-15 16:57:00 -0800286 ". This may take some time." )
287 self.handle.sendline( "cd " + self.home )
Devin Limc20e79a2017-06-07 10:29:57 -0700288 self.handle.expect( self.prompt )
Jon Hallea7818b2014-10-09 14:30:59 -0400289
kelvin8ec71442015-01-15 16:57:00 -0800290 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -0700291 self.handle.expect( self.prompt )
shahshreya9f531fe2015-06-10 12:03:51 -0700292
293 if not skipTest:
294 self.handle.sendline( "mvn clean install" )
295 self.handle.expect( "mvn clean install" )
296 else:
297 self.handle.sendline( "mvn clean install -DskipTests" +
298 " -Dcheckstyle.skip -U -T 1C" )
299 self.handle.expect( "mvn clean install -DskipTests" +
300 " -Dcheckstyle.skip -U -T 1C" )
kelvin8ec71442015-01-15 16:57:00 -0800301 while True:
302 i = self.handle.expect( [
Jon Hall274b6642015-02-17 11:57:17 -0800303 'There\sis\sinsufficient\smemory\sfor\sthe\sJava\s' +
Jon Hallefbd9792015-03-05 16:11:36 -0800304 'Runtime\sEnvironment\sto\scontinue',
Jon Hallde9d9aa2014-10-08 20:36:02 -0400305 'BUILD\sFAILURE',
306 'BUILD\sSUCCESS',
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700307 'onos' + self.prompt, # TODO: fix this to be more generic?
Devin Limdc78e202017-06-09 18:30:07 -0700308 'ONOS' + self.prompt,
pingping-lin57a56ce2015-05-20 16:43:48 -0700309 pexpect.TIMEOUT ], mciTimeout )
Jon Hallde9d9aa2014-10-08 20:36:02 -0400310 if i == 0:
kelvin8ec71442015-01-15 16:57:00 -0800311 main.log.error( self.name + ":There is insufficient memory \
312 for the Java Runtime Environment to continue." )
313 # return main.FALSE
Devin Lim44075962017-08-11 10:56:37 -0700314
315 main.cleanAndExit()
Jon Hallde9d9aa2014-10-08 20:36:02 -0400316 if i == 1:
kelvin8ec71442015-01-15 16:57:00 -0800317 main.log.error( self.name + ": Build failure!" )
318 # return main.FALSE
Devin Lim44075962017-08-11 10:56:37 -0700319
320 main.cleanAndExit()
Jon Hallde9d9aa2014-10-08 20:36:02 -0400321 elif i == 2:
kelvin8ec71442015-01-15 16:57:00 -0800322 main.log.info( self.name + ": Build success!" )
Jon Halle94919c2015-03-23 11:42:57 -0700323 elif i == 3 or i == 4:
kelvin8ec71442015-01-15 16:57:00 -0800324 main.log.info( self.name + ": Build complete" )
325 # Print the build time
Jon Hallf8ef52c2014-10-09 19:37:33 -0400326 for line in self.handle.before.splitlines():
327 if "Total time:" in line:
kelvin8ec71442015-01-15 16:57:00 -0800328 main.log.info( line )
329 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -0700330 self.handle.expect( self.prompt, timeout=60 )
Jon Hallde9d9aa2014-10-08 20:36:02 -0400331 return main.TRUE
Jon Halle94919c2015-03-23 11:42:57 -0700332 elif i == 5:
kelvin8ec71442015-01-15 16:57:00 -0800333 main.log.error(
334 self.name +
335 ": mvn clean install TIMEOUT!" )
336 # return main.FALSE
Devin Lim44075962017-08-11 10:56:37 -0700337
338 main.cleanAndExit()
Jon Hallde9d9aa2014-10-08 20:36:02 -0400339 else:
Jon Hall274b6642015-02-17 11:57:17 -0800340 main.log.error( self.name + ": unexpected response from " +
Jon Hallefbd9792015-03-05 16:11:36 -0800341 "mvn clean install" )
kelvin8ec71442015-01-15 16:57:00 -0800342 # return main.FALSE
Devin Lim44075962017-08-11 10:56:37 -0700343
344 main.cleanAndExit()
Jon Hallde9d9aa2014-10-08 20:36:02 -0400345 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800346 main.log.error( self.name + ": EOF exception found" )
347 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700348 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800349 except Exception:
350 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700351 main.cleanAndExit()
Jon Hallacabffd2014-10-09 12:36:53 -0400352
Jon Hall3576f572016-08-23 10:01:07 -0700353 def buckBuild( self, timeout=180 ):
354 """
355 Build onos using buck.
356 """
357 try:
358 ret = main.TRUE
359 self.handle.sendline( "buck build onos" )
360 self.handle.expect( "buck build onos" )
361 output = ""
362 while True:
363 i = self.handle.expect( [ "This does not appear to be the root of a Buck project.",
364 "\n",
365 "BUILD FAILED",
Devin Limc20e79a2017-06-07 10:29:57 -0700366 self.prompt ],
Jon Hall3576f572016-08-23 10:01:07 -0700367 timeout=timeout )
368 output += str( self.handle.before + self.handle.after )
369 if i == 0:
370 main.log.error( "Wrong location" )
371 ret = main.FALSE
372 elif i == 1:
373 # end of a line, buck is still printing output
374 pass
375 elif i == 2:
376 # Build failed
377 main.log.error( "Build failed" )
378 ret = main.FALSE
379 elif i == 3:
380 # Prompt returned
381 break
382 main.log.debug( output )
383 return ret
384 except pexpect.TIMEOUT:
385 main.log.exception( self.name + ": TIMEOUT exception found" )
386 main.log.error( self.name + ": " + self.handle.before )
387 return main.FALSE
388 except pexpect.EOF:
389 main.log.error( self.name + ": EOF exception found" )
390 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700391 main.cleanAndExit()
Jon Hall3576f572016-08-23 10:01:07 -0700392 except Exception:
393 main.log.exception( "Failed to build and package ONOS" )
Devin Lim44075962017-08-11 10:56:37 -0700394 main.cleanAndExit()
Jon Hall3576f572016-08-23 10:01:07 -0700395
Jon Hall61282e32015-03-19 11:34:11 -0700396 def gitPull( self, comp1="", fastForward=True ):
kelvin8ec71442015-01-15 16:57:00 -0800397 """
Jon Hallacabffd2014-10-09 12:36:53 -0400398 Assumes that "git pull" works without login
Jon Hall47a93fb2015-01-06 16:46:06 -0800399
Jon Hall61282e32015-03-19 11:34:11 -0700400 If the fastForward boolean is set to true, only git pulls that can
401 be fast forwarded will be performed. IE if you have not local commits
402 in your branch.
403
Jon Hallacabffd2014-10-09 12:36:53 -0400404 This function will perform a git pull on the ONOS instance.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800405 If used as gitPull( "NODE" ) it will do git pull + NODE. This is
Jon Hallacabffd2014-10-09 12:36:53 -0400406 for the purpose of pulling from other nodes if necessary.
407
Jon Hall47a93fb2015-01-06 16:46:06 -0800408 Otherwise, this function will perform a git pull in the
Jon Hallacabffd2014-10-09 12:36:53 -0400409 ONOS repository. If it has any problems, it will return main.ERROR
kelvin-onlabd3b64892015-01-20 13:26:24 -0800410 If it successfully does a gitPull, it will return a 1 ( main.TRUE )
Shreya Shahee15f6c2014-10-28 18:12:30 -0400411 If it has no updates, it will return 3.
Jon Hallacabffd2014-10-09 12:36:53 -0400412
kelvin8ec71442015-01-15 16:57:00 -0800413 """
Jon Hallacabffd2014-10-09 12:36:53 -0400414 try:
kelvin8ec71442015-01-15 16:57:00 -0800415 self.handle.sendline( "cd " + self.home )
Devin Limc20e79a2017-06-07 10:29:57 -0700416 self.handle.expect( self.prompt )
Jon Hall61282e32015-03-19 11:34:11 -0700417 cmd = "git pull"
418 if comp1 != "":
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700419 cmd += ' ' + comp1
Jon Hall61282e32015-03-19 11:34:11 -0700420 if fastForward:
421 cmd += ' ' + " --ff-only"
422 self.handle.sendline( cmd )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800423 i = self.handle.expect(
424 [
425 'fatal',
426 'Username\sfor\s(.*):\s',
427 '\sfile(s*) changed,\s',
428 'Already up-to-date',
429 'Aborting',
430 'You\sare\snot\scurrently\son\sa\sbranch',
Jon Hall274b6642015-02-17 11:57:17 -0800431 'You asked me to pull without telling me which branch you',
432 'Pull is not possible because you have unmerged files',
Jon Hall61282e32015-03-19 11:34:11 -0700433 'Please enter a commit message to explain why this merge',
434 'Found a swap file by the name',
435 'Please, commit your changes before you can merge.',
kelvin-onlabd3b64892015-01-20 13:26:24 -0800436 pexpect.TIMEOUT ],
437 timeout=300 )
kelvin8ec71442015-01-15 16:57:00 -0800438 if i == 0:
Jon Hall61282e32015-03-19 11:34:11 -0700439 main.log.error( self.name + ": Git pull had some issue" )
440 output = self.handle.after
Devin Limdc78e202017-06-09 18:30:07 -0700441 self.handle.expect( self.prompt )
Jon Hall61282e32015-03-19 11:34:11 -0700442 output += self.handle.before
443 main.log.warn( output )
Jon Hallacabffd2014-10-09 12:36:53 -0400444 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -0800445 elif i == 1:
446 main.log.error(
447 self.name +
448 ": Git Pull Asking for username. " )
Jon Hallacabffd2014-10-09 12:36:53 -0400449 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -0800450 elif i == 2:
451 main.log.info(
452 self.name +
453 ": Git Pull - pulling repository now" )
Devin Limc20e79a2017-06-07 10:29:57 -0700454 self.handle.expect( self.prompt, 120 )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800455 # So that only when git pull is done, we do mvn clean compile
456 return main.TRUE
kelvin8ec71442015-01-15 16:57:00 -0800457 elif i == 3:
458 main.log.info( self.name + ": Git Pull - Already up to date" )
Devin Limc20e79a2017-06-07 10:29:57 -0700459 return main.TRUE
kelvin8ec71442015-01-15 16:57:00 -0800460 elif i == 4:
461 main.log.info(
462 self.name +
Jon Hall274b6642015-02-17 11:57:17 -0800463 ": Git Pull - Aborting..." +
464 "Are there conflicting git files?" )
Jon Hallacabffd2014-10-09 12:36:53 -0400465 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -0800466 elif i == 5:
467 main.log.info(
468 self.name +
Jon Hall274b6642015-02-17 11:57:17 -0800469 ": Git Pull - You are not currently " +
470 "on a branch so git pull failed!" )
Jon Hallacabffd2014-10-09 12:36:53 -0400471 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -0800472 elif i == 6:
473 main.log.info(
474 self.name +
Jon Hall274b6642015-02-17 11:57:17 -0800475 ": Git Pull - You have not configured an upstream " +
476 "branch to pull from. Git pull failed!" )
Jon Hallacabffd2014-10-09 12:36:53 -0400477 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -0800478 elif i == 7:
479 main.log.info(
480 self.name +
Jon Hall274b6642015-02-17 11:57:17 -0800481 ": Git Pull - Pull is not possible because " +
482 "you have unmerged files." )
Jon Hallacabffd2014-10-09 12:36:53 -0400483 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -0800484 elif i == 8:
Jon Hall61282e32015-03-19 11:34:11 -0700485 # NOTE: abandoning test since we can't reliably handle this
486 # there could be different default text editors and we
487 # also don't know if we actually want to make the commit
488 main.log.error( "Git pull resulted in a merge commit message" +
489 ". Exiting test!" )
Devin Lim44075962017-08-11 10:56:37 -0700490
491 main.cleanAndExit()
Jon Hall61282e32015-03-19 11:34:11 -0700492 elif i == 9: # Merge commit message but swap file exists
493 main.log.error( "Git pull resulted in a merge commit message" +
494 " but a swap file exists." )
495 try:
496 self.handle.send( 'A' ) # Abort
Devin Limc20e79a2017-06-07 10:29:57 -0700497 self.handle.expect( self.prompt )
Jon Hall61282e32015-03-19 11:34:11 -0700498 return main.ERROR
499 except Exception:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700500 main.log.exception( "Couldn't exit editor prompt!" )
Devin Lim44075962017-08-11 10:56:37 -0700501
502 main.cleanAndExit()
Jon Hall61282e32015-03-19 11:34:11 -0700503 elif i == 10: # In the middle of a merge commit
504 main.log.error( "Git branch is in the middle of a merge. " )
505 main.log.warn( self.handle.before + self.handle.after )
506 return main.ERROR
507 elif i == 11:
kelvin8ec71442015-01-15 16:57:00 -0800508 main.log.error( self.name + ": Git Pull - TIMEOUT" )
509 main.log.error(
510 self.name + " Response was: " + str(
511 self.handle.before ) )
Jon Hallacabffd2014-10-09 12:36:53 -0400512 return main.ERROR
513 else:
kelvin8ec71442015-01-15 16:57:00 -0800514 main.log.error(
515 self.name +
516 ": Git Pull - Unexpected response, check for pull errors" )
Jon Hallacabffd2014-10-09 12:36:53 -0400517 return main.ERROR
518 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800519 main.log.error( self.name + ": EOF exception found" )
520 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700521 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800522 except Exception:
523 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700524 main.cleanAndExit()
Jon Hallacabffd2014-10-09 12:36:53 -0400525
kelvin-onlabd3b64892015-01-20 13:26:24 -0800526 def gitCheckout( self, branch="master" ):
kelvin8ec71442015-01-15 16:57:00 -0800527 """
Jon Hallacabffd2014-10-09 12:36:53 -0400528 Assumes that "git pull" works without login
kelvin8ec71442015-01-15 16:57:00 -0800529
Jon Hallacabffd2014-10-09 12:36:53 -0400530 This function will perform a git git checkout on the ONOS instance.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800531 If used as gitCheckout( "branch" ) it will do git checkout
532 of the "branch".
Jon Hallacabffd2014-10-09 12:36:53 -0400533
534 Otherwise, this function will perform a git checkout of the master
kelvin8ec71442015-01-15 16:57:00 -0800535 branch of the ONOS repository. If it has any problems, it will return
536 main.ERROR.
537 If the branch was already the specified branch, or the git checkout was
Jon Hallacabffd2014-10-09 12:36:53 -0400538 successful then the function will return main.TRUE.
539
kelvin8ec71442015-01-15 16:57:00 -0800540 """
Jon Hallacabffd2014-10-09 12:36:53 -0400541 try:
kelvin8ec71442015-01-15 16:57:00 -0800542 self.handle.sendline( "cd " + self.home )
Devin Limc20e79a2017-06-07 10:29:57 -0700543 self.handle.expect( self.prompt )
Jon Hall274b6642015-02-17 11:57:17 -0800544 main.log.info( self.name +
545 ": Checking out git branch/ref: " + branch + "..." )
kelvin8ec71442015-01-15 16:57:00 -0800546 cmd = "git checkout " + branch
547 self.handle.sendline( cmd )
548 self.handle.expect( cmd )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800549 i = self.handle.expect(
Jon Hall274b6642015-02-17 11:57:17 -0800550 [ 'fatal',
Jon Hall61282e32015-03-19 11:34:11 -0700551 'Username for (.*): ',
552 'Already on \'',
Jon Hall7a8354f2015-06-10 15:37:00 -0700553 'Switched to (a new )?branch \'' + str( branch ),
Jon Hall274b6642015-02-17 11:57:17 -0800554 pexpect.TIMEOUT,
555 'error: Your local changes to the following files' +
Jon Hallefbd9792015-03-05 16:11:36 -0800556 'would be overwritten by checkout:',
Jon Hall274b6642015-02-17 11:57:17 -0800557 'error: you need to resolve your current index first',
558 "You are in 'detached HEAD' state.",
559 "HEAD is now at " ],
kelvin-onlabd3b64892015-01-20 13:26:24 -0800560 timeout=60 )
kelvin8ec71442015-01-15 16:57:00 -0800561 if i == 0:
562 main.log.error(
563 self.name +
564 ": Git checkout had some issue..." )
565 main.log.error( self.name + ": " + self.handle.before )
Jon Hallacabffd2014-10-09 12:36:53 -0400566 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -0800567 elif i == 1:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800568 main.log.error(
569 self.name +
570 ": Git checkout asking for username." +
571 " Please configure your local git repository to be able " +
572 "to access your remote repository passwordlessly" )
Jon Hall274b6642015-02-17 11:57:17 -0800573 # TODO add support for authenticating
Jon Hallacabffd2014-10-09 12:36:53 -0400574 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -0800575 elif i == 2:
576 main.log.info(
577 self.name +
Jon Hall274b6642015-02-17 11:57:17 -0800578 ": Git Checkout %s : Already on this branch" % branch )
Devin Limc20e79a2017-06-07 10:29:57 -0700579 self.handle.expect( self.prompt )
kelvin8ec71442015-01-15 16:57:00 -0800580 # main.log.info( "DEBUG: after checkout cmd = "+
581 # self.handle.before )
Jon Hallacabffd2014-10-09 12:36:53 -0400582 return main.TRUE
kelvin8ec71442015-01-15 16:57:00 -0800583 elif i == 3:
584 main.log.info(
585 self.name +
Jon Hall274b6642015-02-17 11:57:17 -0800586 ": Git checkout %s - Switched to this branch" % branch )
Devin Limc20e79a2017-06-07 10:29:57 -0700587 self.handle.expect( self.prompt )
kelvin8ec71442015-01-15 16:57:00 -0800588 # main.log.info( "DEBUG: after checkout cmd = "+
589 # self.handle.before )
Jon Hallacabffd2014-10-09 12:36:53 -0400590 return main.TRUE
kelvin8ec71442015-01-15 16:57:00 -0800591 elif i == 4:
592 main.log.error( self.name + ": Git Checkout- TIMEOUT" )
593 main.log.error(
Jon Hall274b6642015-02-17 11:57:17 -0800594 self.name + " Response was: " + str( self.handle.before ) )
Jon Hallacabffd2014-10-09 12:36:53 -0400595 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -0800596 elif i == 5:
597 self.handle.expect( "Aborting" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800598 main.log.error(
599 self.name +
600 ": Git checkout error: \n" +
Jon Hall274b6642015-02-17 11:57:17 -0800601 "Your local changes to the following files would" +
602 " be overwritten by checkout:" +
603 str( self.handle.before ) )
Devin Limc20e79a2017-06-07 10:29:57 -0700604 self.handle.expect( self.prompt )
Jon Hall81e29af2014-11-04 20:41:23 -0500605 return main.ERROR
kelvin8ec71442015-01-15 16:57:00 -0800606 elif i == 6:
Jon Hall274b6642015-02-17 11:57:17 -0800607 main.log.error(
608 self.name +
609 ": Git checkout error: \n" +
610 "You need to resolve your current index first:" +
611 str( self.handle.before ) )
Devin Limc20e79a2017-06-07 10:29:57 -0700612 self.handle.expect( self.prompt )
Jon Hall81e29af2014-11-04 20:41:23 -0500613 return main.ERROR
Jon Hall274b6642015-02-17 11:57:17 -0800614 elif i == 7:
615 main.log.info(
616 self.name +
617 ": Git checkout " + str( branch ) +
618 " - You are in 'detached HEAD' state. HEAD is now at " +
619 str( branch ) )
Devin Limc20e79a2017-06-07 10:29:57 -0700620 self.handle.expect( self.prompt )
Jon Hall274b6642015-02-17 11:57:17 -0800621 return main.TRUE
622 elif i == 8: # Already in detached HEAD on the specified commit
623 main.log.info(
624 self.name +
625 ": Git Checkout %s : Already on commit" % branch )
Devin Limc20e79a2017-06-07 10:29:57 -0700626 self.handle.expect( self.prompt )
Jon Hall274b6642015-02-17 11:57:17 -0800627 return main.TRUE
Jon Hallacabffd2014-10-09 12:36:53 -0400628 else:
kelvin8ec71442015-01-15 16:57:00 -0800629 main.log.error(
630 self.name +
Jon Hall274b6642015-02-17 11:57:17 -0800631 ": Git Checkout - Unexpected response, " +
632 "check for pull errors" )
kelvin8ec71442015-01-15 16:57:00 -0800633 main.log.error( self.name + ": " + self.handle.before )
Jon Hallacabffd2014-10-09 12:36:53 -0400634 return main.ERROR
635
636 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800637 main.log.error( self.name + ": EOF exception found" )
638 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700639 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800640 except Exception:
641 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700642 main.cleanAndExit()
andrewonlab95ca1462014-10-09 14:04:24 -0400643
pingping-lin6d23d9e2015-02-02 16:54:24 -0800644 def getBranchName( self ):
You Wang9cdf9a22017-05-01 13:44:18 -0700645 import re
646 try:
647 main.log.info( "self.home = " )
648 main.log.info( self.home )
649 self.handle.sendline( "cd " + self.home )
Devin Limc20e79a2017-06-07 10:29:57 -0700650 self.handle.expect( self.prompt )
You Wang9cdf9a22017-05-01 13:44:18 -0700651 self.handle.sendline( "git name-rev --name-only HEAD" )
652 self.handle.expect( "git name-rev --name-only HEAD" )
Devin Limc20e79a2017-06-07 10:29:57 -0700653 self.handle.expect( self.prompt )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700654 lines = self.handle.before.splitlines()
655 if lines[ 1 ] == "master" or re.search( "^onos-\d+(\.\d+)+$", lines[ 1 ] ):
656 return lines[ 1 ]
You Wang9cdf9a22017-05-01 13:44:18 -0700657 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700658 main.log.info( lines[ 1 ] )
You Wang9cdf9a22017-05-01 13:44:18 -0700659 return "unexpected ONOS branch"
660 except pexpect.EOF:
661 main.log.error( self.name + ": EOF exception found" )
662 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700663 main.cleanAndExit()
You Wang9cdf9a22017-05-01 13:44:18 -0700664 except pexpect.TIMEOUT:
665 main.log.error( self.name + ": TIMEOUT exception found" )
666 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700667 main.cleanAndExit()
You Wang9cdf9a22017-05-01 13:44:18 -0700668 except Exception:
669 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700670 main.cleanAndExit()
pingping-lin6d23d9e2015-02-02 16:54:24 -0800671
kelvin-onlabd3b64892015-01-20 13:26:24 -0800672 def getVersion( self, report=False ):
kelvin8ec71442015-01-15 16:57:00 -0800673 """
Jon Hall274b6642015-02-17 11:57:17 -0800674 Writes the COMMIT number to the report to be parsed
Jon Hallefbd9792015-03-05 16:11:36 -0800675 by Jenkins data collector.
kelvin8ec71442015-01-15 16:57:00 -0800676 """
Jon Hall45ec0922014-10-10 19:33:49 -0400677 try:
kelvin8ec71442015-01-15 16:57:00 -0800678 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -0700679 self.handle.expect( self.prompt )
kelvin8ec71442015-01-15 16:57:00 -0800680 self.handle.sendline(
681 "cd " +
682 self.home +
Jon Hall274b6642015-02-17 11:57:17 -0800683 "; git log -1 --pretty=fuller --decorate=short | grep -A 6 " +
684 " \"commit\" --color=never" )
kelvin8ec71442015-01-15 16:57:00 -0800685 # NOTE: for some reason there are backspaces inserted in this
686 # phrase when run from Jenkins on some tests
687 self.handle.expect( "never" )
Devin Limc20e79a2017-06-07 10:29:57 -0700688 self.handle.expect( self.prompt )
kelvin8ec71442015-01-15 16:57:00 -0800689 response = ( self.name + ": \n" + str(
690 self.handle.before + self.handle.after ) )
691 self.handle.sendline( "cd " + self.home )
Devin Limc20e79a2017-06-07 10:29:57 -0700692 self.handle.expect( self.prompt )
kelvin8ec71442015-01-15 16:57:00 -0800693 lines = response.splitlines()
Jon Hall45ec0922014-10-10 19:33:49 -0400694 for line in lines:
Jon Hallfd191202014-11-07 18:36:09 -0500695 print line
696 if report:
pingping-lin763ee042015-05-20 17:45:30 -0700697 main.log.wiki( "<blockquote>" )
kelvin8ec71442015-01-15 16:57:00 -0800698 for line in lines[ 2:-1 ]:
699 # Bracket replacement is for Wiki-compliant
700 # formatting. '<' or '>' are interpreted
701 # as xml specific tags that cause errors
702 line = line.replace( "<", "[" )
703 line = line.replace( ">", "]" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700704 # main.log.wiki( "\t" + line )
pingping-lin763ee042015-05-20 17:45:30 -0700705 main.log.wiki( line + "<br /> " )
706 main.log.summary( line )
707 main.log.wiki( "</blockquote>" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700708 main.log.summary( "\n" )
kelvin8ec71442015-01-15 16:57:00 -0800709 return lines[ 2 ]
Jon Hall45ec0922014-10-10 19:33:49 -0400710 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800711 main.log.error( self.name + ": EOF exception found" )
712 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700713 main.cleanAndExit()
Jon Hall368769f2014-11-19 15:43:35 -0800714 except pexpect.TIMEOUT:
kelvin8ec71442015-01-15 16:57:00 -0800715 main.log.error( self.name + ": TIMEOUT exception found" )
716 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700717 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800718 except Exception:
719 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700720 main.cleanAndExit()
Jon Hall45ec0922014-10-10 19:33:49 -0400721
kelvin-onlabd3b64892015-01-20 13:26:24 -0800722 def createCellFile( self, benchIp, fileName, mnIpAddrs,
Jon Hall810b67d2016-12-05 10:19:01 -0800723 appString, onosIpAddrs, onosUser="sdn", useSSH=True ):
kelvin8ec71442015-01-15 16:57:00 -0800724 """
andrewonlab94282092014-10-10 13:00:11 -0400725 Creates a cell file based on arguments
726 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800727 * Bench IP address ( benchIp )
andrewonlab94282092014-10-10 13:00:11 -0400728 - Needed to copy the cell file over
kelvin-onlabd3b64892015-01-20 13:26:24 -0800729 * File name of the cell file ( fileName )
730 * Mininet IP address ( mnIpAddrs )
kelvin8ec71442015-01-15 16:57:00 -0800731 - Note that only 1 ip address is
andrewonlab94282092014-10-10 13:00:11 -0400732 supported currently
kelvin-onlabd3b64892015-01-20 13:26:24 -0800733 * ONOS IP addresses ( onosIpAddrs )
andrewonlab94282092014-10-10 13:00:11 -0400734 - Must be passed in as last arguments
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000735 * ONOS USER (onosUser)
Flavio Castrocc38a542016-03-03 13:15:46 -0800736 - optional argument to set ONOS_USER environment variable
kelvin8ec71442015-01-15 16:57:00 -0800737
andrewonlab94282092014-10-10 13:00:11 -0400738 NOTE: Assumes cells are located at:
739 ~/<self.home>/tools/test/cells/
kelvin8ec71442015-01-15 16:57:00 -0800740 """
andrewonlab94282092014-10-10 13:00:11 -0400741 try:
Devin Lim461f0872017-06-05 16:49:33 -0700742
Jon Hall2c8959e2016-12-16 12:17:34 -0800743 # Variable initialization
744 cellDirectory = self.home + "/tools/test/cells/"
745 # We want to create the cell file in the dependencies directory
746 # of TestON first, then copy over to ONOS bench
747 tempDirectory = "/tmp/"
748 # Create the cell file in the directory for writing ( w+ )
749 cellFile = open( tempDirectory + fileName, 'w+' )
750 if isinstance( onosIpAddrs, types.StringType ):
751 onosIpAddrs = [ onosIpAddrs ]
752
753 # App string is hardcoded environment variables
754 # That you may wish to use by default on startup.
755 # Note that you may not want certain apps listed
756 # on here.
757 appString = "export ONOS_APPS=" + appString
758 onosGroup = "export ONOS_GROUP=" + onosUser
759 onosUser = "export ONOS_USER=" + onosUser
760 if useSSH:
761 onosUseSSH = "export ONOS_USE_SSH=true"
762 mnString = "export OCN="
763 if mnIpAddrs == "":
764 mnString = ""
765 onosString = "export OC"
766 tempCount = 1
767
768 # Create ONOSNIC ip address prefix
769 tempOnosIp = str( onosIpAddrs[ 0 ] )
770 tempList = []
771 tempList = tempOnosIp.split( "." )
772 # Omit last element of list to format for NIC
773 tempList = tempList[ :-1 ]
774 # Structure the nic string ip
775 nicAddr = ".".join( tempList ) + ".*"
776 self.nicAddr = nicAddr
777 onosNicString = "export ONOS_NIC=" + nicAddr
778
kelvin8ec71442015-01-15 16:57:00 -0800779 # Start writing to file
kelvin-onlabd3b64892015-01-20 13:26:24 -0800780 cellFile.write( onosNicString + "\n" )
andrewonlab94282092014-10-10 13:00:11 -0400781
kelvin-onlabd3b64892015-01-20 13:26:24 -0800782 for arg in onosIpAddrs:
783 # For each argument in onosIpAddrs, write to file
kelvin8ec71442015-01-15 16:57:00 -0800784 # Output should look like the following:
andrewonlabd4940492014-10-24 12:21:27 -0400785 # export OC1="10.128.20.11"
786 # export OC2="10.128.20.12"
kelvin-onlabd3b64892015-01-20 13:26:24 -0800787 cellFile.write( onosString + str( tempCount ) +
Jon Hall6f665652015-09-18 10:08:07 -0700788 "=\"" + arg + "\"\n" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800789 tempCount = tempCount + 1
kelvin8ec71442015-01-15 16:57:00 -0800790
Jon Hall6f665652015-09-18 10:08:07 -0700791 cellFile.write( "export OCI=$OC1\n" )
792 cellFile.write( mnString + "\"" + mnIpAddrs + "\"\n" )
cameron@onlab.us75900962015-03-30 13:22:49 -0700793 cellFile.write( appString + "\n" )
Flavio Castrocc38a542016-03-03 13:15:46 -0800794 cellFile.write( onosGroup + "\n" )
795 cellFile.write( onosUser + "\n" )
Pier88189b62016-09-07 17:01:53 -0700796 if useSSH:
797 cellFile.write( onosUseSSH + "\n" )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800798 cellFile.close()
andrewonlab94282092014-10-10 13:00:11 -0400799
kelvin8ec71442015-01-15 16:57:00 -0800800 # We use os.system to send the command to TestON cluster
801 # to account for the case in which TestON is not located
802 # on the same cluster as the ONOS bench
803 # Note that even if TestON is located on the same cluster
804 # as ONOS bench, you must setup passwordless ssh
805 # between TestON and ONOS bench in order to automate the test.
kelvin-onlabc2b79102015-07-14 11:41:20 -0700806 os.system( "scp " + tempDirectory + fileName + " " +
807 self.user_name + "@" + self.ip_address + ":" + cellDirectory )
andrewonlab94282092014-10-10 13:00:11 -0400808
andrewonlab2a6c9342014-10-16 13:40:15 -0400809 return main.TRUE
810
andrewonlab94282092014-10-10 13:00:11 -0400811 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800812 main.log.error( self.name + ": EOF exception found" )
813 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700814 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800815 except Exception:
816 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700817 main.cleanAndExit()
andrewonlab94282092014-10-10 13:00:11 -0400818
kelvin-onlabd3b64892015-01-20 13:26:24 -0800819 def setCell( self, cellname ):
kelvin8ec71442015-01-15 16:57:00 -0800820 """
andrewonlab95ca1462014-10-09 14:04:24 -0400821 Calls 'cell <name>' to set the environment variables on ONOSbench
kelvin8ec71442015-01-15 16:57:00 -0800822 """
Hari Krishna03f530e2015-07-10 17:28:27 -0700823 import re
andrewonlab95ca1462014-10-09 14:04:24 -0400824 try:
825 if not cellname:
kelvin8ec71442015-01-15 16:57:00 -0800826 main.log.error( "Must define cellname" )
Devin Lim44075962017-08-11 10:56:37 -0700827
828 main.cleanAndExit()
andrewonlab95ca1462014-10-09 14:04:24 -0400829 else:
kelvin8ec71442015-01-15 16:57:00 -0800830 self.handle.sendline( "cell " + str( cellname ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800831 # Expect the cellname in the ONOSCELL variable.
kelvin8ec71442015-01-15 16:57:00 -0800832 # Note that this variable name is subject to change
andrewonlab95ca1462014-10-09 14:04:24 -0400833 # and that this driver will have to change accordingly
Jon Hall3b489db2015-10-05 14:38:37 -0700834 self.handle.expect( str( cellname ) )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800835 handleBefore = self.handle.before
836 handleAfter = self.handle.after
kelvin8ec71442015-01-15 16:57:00 -0800837 # Get the rest of the handle
Devin Limc20e79a2017-06-07 10:29:57 -0700838 self.handle.expect( self.prompt )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700839 time.sleep( 10 )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800840 handleMore = self.handle.before
andrewonlab95ca1462014-10-09 14:04:24 -0400841
Hari Krishna03f530e2015-07-10 17:28:27 -0700842 cell_result = handleBefore + handleAfter + handleMore
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700843 # print cell_result
Hari Krishna03f530e2015-07-10 17:28:27 -0700844 if( re.search( "No such cell", cell_result ) ):
845 main.log.error( "Cell call returned: " + handleBefore +
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700846 handleAfter + handleMore )
Devin Lim44075962017-08-11 10:56:37 -0700847
848 main.cleanAndExit()
andrewonlab95ca1462014-10-09 14:04:24 -0400849 return main.TRUE
andrewonlab95ca1462014-10-09 14:04:24 -0400850 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800851 main.log.error( self.name + ": EOF exception found" )
852 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700853 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800854 except Exception:
855 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700856 main.cleanAndExit()
andrewonlab95ca1462014-10-09 14:04:24 -0400857
kelvin-onlabd3b64892015-01-20 13:26:24 -0800858 def verifyCell( self ):
kelvin8ec71442015-01-15 16:57:00 -0800859 """
andrewonlabc03bf6c2014-10-09 14:56:18 -0400860 Calls 'onos-verify-cell' to check for cell installation
kelvin8ec71442015-01-15 16:57:00 -0800861 """
862 # TODO: Add meaningful expect value
andrewonlab8d0d7d72014-10-09 16:33:15 -0400863
andrewonlabc03bf6c2014-10-09 14:56:18 -0400864 try:
kelvin8ec71442015-01-15 16:57:00 -0800865 # Clean handle by sending empty and expecting $
866 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -0700867 self.handle.expect( self.prompt )
kelvin8ec71442015-01-15 16:57:00 -0800868 self.handle.sendline( "onos-verify-cell" )
Devin Limc20e79a2017-06-07 10:29:57 -0700869 self.handle.expect( self.prompt )
kelvin-onlabd3b64892015-01-20 13:26:24 -0800870 handleBefore = self.handle.before
871 handleAfter = self.handle.after
kelvin-onlabd3b64892015-01-20 13:26:24 -0800872 main.log.info( "Verify cell returned: " + handleBefore +
Jon Hall3b489db2015-10-05 14:38:37 -0700873 handleAfter )
andrewonlabc03bf6c2014-10-09 14:56:18 -0400874 return main.TRUE
Jon Halla5cb6172015-02-23 09:28:28 -0800875 except pexpect.ExceptionPexpect as e:
Jon Hall3b489db2015-10-05 14:38:37 -0700876 main.log.exception( self.name + ": Pexpect exception found: " )
kelvin8ec71442015-01-15 16:57:00 -0800877 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700878 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800879 except Exception:
880 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700881 main.cleanAndExit()
Jon Hall7993bfc2014-10-09 16:30:14 -0400882
jenkins1e99e7b2015-04-02 18:15:39 -0700883 def onosCfgSet( self, ONOSIp, configName, configParam ):
884 """
885 Uses 'onos <node-ip> cfg set' to change a parameter value of an
Jon Hall4ba53f02015-07-29 13:07:41 -0700886 application.
887
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000888 ex)
jenkins1e99e7b2015-04-02 18:15:39 -0700889 onos 10.0.0.1 cfg set org.onosproject.myapp appSetting 1
jenkins1e99e7b2015-04-02 18:15:39 -0700890 ONOSIp = '10.0.0.1'
891 configName = 'org.onosproject.myapp'
892 configParam = 'appSetting 1'
jenkins1e99e7b2015-04-02 18:15:39 -0700893 """
Jon Hall72280bc2016-01-25 14:29:05 -0800894 try:
895 cfgStr = "onos {} cfg set {} {}".format( ONOSIp,
896 configName,
897 configParam )
898 self.handle.sendline( "" )
899 self.handle.expect( ":~" )
900 self.handle.sendline( cfgStr )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700901 self.handle.expect( "cfg set" )
Jon Hall72280bc2016-01-25 14:29:05 -0800902 self.handle.expect( ":~" )
jenkins1e99e7b2015-04-02 18:15:39 -0700903
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700904 paramValue = configParam.split( " " )[ 1 ]
905 paramName = configParam.split( " " )[ 0 ]
Jon Hall4ba53f02015-07-29 13:07:41 -0700906
Jon Hall72280bc2016-01-25 14:29:05 -0800907 checkStr = 'onos {} cfg get " {} {} " '.format( ONOSIp, configName, paramName )
Jon Hall4ba53f02015-07-29 13:07:41 -0700908
Jon Hall72280bc2016-01-25 14:29:05 -0800909 self.handle.sendline( checkStr )
910 self.handle.expect( ":~" )
jenkins1e99e7b2015-04-02 18:15:39 -0700911
Jon Hall72280bc2016-01-25 14:29:05 -0800912 if "value=" + paramValue + "," in self.handle.before:
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700913 main.log.info( "cfg " + configName + " successfully set to " + configParam )
Jon Hall72280bc2016-01-25 14:29:05 -0800914 return main.TRUE
915 except pexpect.ExceptionPexpect as e:
916 main.log.exception( self.name + ": Pexpect exception found: " )
917 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700918 main.cleanAndExit()
Jon Hall72280bc2016-01-25 14:29:05 -0800919 except Exception:
920 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700921 main.cleanAndExit()
Jon Hall4ba53f02015-07-29 13:07:41 -0700922
kelvin-onlabd3b64892015-01-20 13:26:24 -0800923 def onosCli( self, ONOSIp, cmdstr ):
kelvin8ec71442015-01-15 16:57:00 -0800924 """
andrewonlab05e362f2014-10-10 00:40:57 -0400925 Uses 'onos' command to send various ONOS CLI arguments.
926 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800927 * ONOSIp: specify the ip of the cell machine
andrewonlab94282092014-10-10 13:00:11 -0400928 * cmdstr: specify the command string to send
kelvin8ec71442015-01-15 16:57:00 -0800929
930 This function is intended to expose the entire karaf
andrewonlab6e20c342014-10-10 18:08:48 -0400931 CLI commands for ONOS. Try to use this function first
932 before attempting to write a ONOS CLI specific driver
kelvin8ec71442015-01-15 16:57:00 -0800933 function.
934 You can see a list of available 'cmdstr' arguments
andrewonlab6e20c342014-10-10 18:08:48 -0400935 by starting onos, and typing in 'onos' to enter the
936 onos> CLI. Then, type 'help' to see the list of
kelvin8ec71442015-01-15 16:57:00 -0800937 available commands.
938 """
andrewonlab05e362f2014-10-10 00:40:57 -0400939 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -0800940 if not ONOSIp:
kelvin8ec71442015-01-15 16:57:00 -0800941 main.log.error( "You must specify the IP address" )
andrewonlab05e362f2014-10-10 00:40:57 -0400942 return main.FALSE
943 if not cmdstr:
kelvin8ec71442015-01-15 16:57:00 -0800944 main.log.error( "You must specify the command string" )
andrewonlab05e362f2014-10-10 00:40:57 -0400945 return main.FALSE
946
kelvin8ec71442015-01-15 16:57:00 -0800947 cmdstr = str( cmdstr )
948 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -0700949 self.handle.expect( self.prompt )
andrewonlab05e362f2014-10-10 00:40:57 -0400950
kelvin-onlabd3b64892015-01-20 13:26:24 -0800951 self.handle.sendline( "onos -w " + ONOSIp + " " + cmdstr )
Devin Limc20e79a2017-06-07 10:29:57 -0700952 self.handle.expect( self.prompt )
andrewonlab05e362f2014-10-10 00:40:57 -0400953
kelvin-onlabd3b64892015-01-20 13:26:24 -0800954 handleBefore = self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800955 main.log.info( "Command sent successfully" )
kelvin8ec71442015-01-15 16:57:00 -0800956 # Obtain return handle that consists of result from
957 # the onos command. The string may need to be
958 # configured further.
kelvin-onlabd3b64892015-01-20 13:26:24 -0800959 returnString = handleBefore
kelvin-onlabd3b64892015-01-20 13:26:24 -0800960 return returnString
andrewonlab05e362f2014-10-10 00:40:57 -0400961 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -0800962 main.log.error( self.name + ": EOF exception found" )
963 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -0700964 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -0800965 except Exception:
966 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -0700967 main.cleanAndExit()
Jon Hall7993bfc2014-10-09 16:30:14 -0400968
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700969 def onosSecureSSH( self, userName="onos", userPWD="rocks", node="" ):
Pier88189b62016-09-07 17:01:53 -0700970 """
971 Enables secure access to ONOS console
972 by removing default users & keys.
973
974 onos-secure-ssh -u onos -p rocks node
975
976 Returns: main.TRUE on success and main.FALSE on failure
977 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000978
Pier88189b62016-09-07 17:01:53 -0700979 try:
Chiyu Chengef109502016-11-21 15:51:38 -0800980 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -0700981 self.handle.expect( self.prompt )
Pier88189b62016-09-07 17:01:53 -0700982 self.handle.sendline( " onos-secure-ssh -u " + userName + " -p " + userPWD + " " + node )
983
984 # NOTE: this timeout may need to change depending on the network
985 # and size of ONOS
986 # TODO: Handle the other possible error
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700987 i = self.handle.expect( [ "Network\sis\sunreachable",
988 self.prompt,
989 pexpect.TIMEOUT ], timeout=180 )
Pier88189b62016-09-07 17:01:53 -0700990 if i == 0:
991 # can't reach ONOS node
992 main.log.warn( "Network is unreachable" )
Devin Limc20e79a2017-06-07 10:29:57 -0700993 self.handle.expect( self.prompt )
Pier88189b62016-09-07 17:01:53 -0700994 return main.FALSE
995 elif i == 1:
996 # Process started
997 main.log.info(
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700998 "Secure SSH performed on " +
999 node )
Pier88189b62016-09-07 17:01:53 -07001000 return main.TRUE
1001 except pexpect.EOF:
1002 main.log.error( self.name + ": EOF exception found" )
1003 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001004 main.cleanAndExit()
Pier88189b62016-09-07 17:01:53 -07001005 except Exception:
1006 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001007 main.cleanAndExit()
Pier88189b62016-09-07 17:01:53 -07001008
kelvin-onlabd3b64892015-01-20 13:26:24 -08001009 def onosInstall( self, options="-f", node="" ):
kelvin8ec71442015-01-15 16:57:00 -08001010 """
Jon Hall7993bfc2014-10-09 16:30:14 -04001011 Installs ONOS bits on the designated cell machine.
kelvin8ec71442015-01-15 16:57:00 -08001012 If -f option is provided, it also forces an uninstall.
1013 Presently, install also includes onos-push-bits and
Jon Hall7993bfc2014-10-09 16:30:14 -04001014 onos-config within.
kelvin8ec71442015-01-15 16:57:00 -08001015 The node option allows you to selectively only push the jar
Jon Hall7993bfc2014-10-09 16:30:14 -04001016 files to certain onos nodes
1017
1018 Returns: main.TRUE on success and main.FALSE on failure
kelvin8ec71442015-01-15 16:57:00 -08001019 """
Jon Hall7993bfc2014-10-09 16:30:14 -04001020 try:
andrewonlab114768a2014-11-14 12:44:44 -05001021 if options:
kelvin8ec71442015-01-15 16:57:00 -08001022 self.handle.sendline( "onos-install " + options + " " + node )
andrewonlab114768a2014-11-14 12:44:44 -05001023 else:
kelvin8ec71442015-01-15 16:57:00 -08001024 self.handle.sendline( "onos-install " + node )
1025 self.handle.expect( "onos-install " )
1026 # NOTE: this timeout may need to change depending on the network
1027 # and size of ONOS
1028 i = self.handle.expect( [ "Network\sis\sunreachable",
kelvin-onlabd3b64892015-01-20 13:26:24 -08001029 "onos\sstart/running,\sprocess",
kelvin8ec71442015-01-15 16:57:00 -08001030 "ONOS\sis\salready\sinstalled",
Jeremyc72b2582016-02-26 18:27:38 -08001031 "already\sup-to-date",
Jon Hall3576f572016-08-23 10:01:07 -07001032 "does not exist",
Devin Limc20e79a2017-06-07 10:29:57 -07001033 self.prompt,
Jon Hall6c44c0b2016-04-20 15:21:00 -07001034 pexpect.TIMEOUT ], timeout=180 )
Jon Hall7993bfc2014-10-09 16:30:14 -04001035 if i == 0:
Jon Hall3576f572016-08-23 10:01:07 -07001036 # can't reach ONOS node
kelvin8ec71442015-01-15 16:57:00 -08001037 main.log.warn( "Network is unreachable" )
Devin Limc20e79a2017-06-07 10:29:57 -07001038 self.handle.expect( self.prompt )
Jon Hall7993bfc2014-10-09 16:30:14 -04001039 return main.FALSE
1040 elif i == 1:
Jon Hall3576f572016-08-23 10:01:07 -07001041 # Process started
kelvin8ec71442015-01-15 16:57:00 -08001042 main.log.info(
1043 "ONOS was installed on " +
1044 node +
1045 " and started" )
Devin Limc20e79a2017-06-07 10:29:57 -07001046 self.handle.expect( self.prompt )
Jon Hall7993bfc2014-10-09 16:30:14 -04001047 return main.TRUE
Jon Hall3576f572016-08-23 10:01:07 -07001048 elif i == 2 or i == 3:
1049 # same bits are already on ONOS node
Jeremyc72b2582016-02-26 18:27:38 -08001050 main.log.info( "ONOS is already installed on " + node )
Devin Limc20e79a2017-06-07 10:29:57 -07001051 self.handle.expect( self.prompt )
Jeremyc72b2582016-02-26 18:27:38 -08001052 return main.TRUE
1053 elif i == 4:
Jon Hall3576f572016-08-23 10:01:07 -07001054 # onos not packaged
1055 main.log.error( "ONOS package not found." )
Devin Limc20e79a2017-06-07 10:29:57 -07001056 self.handle.expect( self.prompt )
Jon Hall3576f572016-08-23 10:01:07 -07001057 return main.FALSE
1058 elif i == 5:
1059 # prompt
Jeremyc72b2582016-02-26 18:27:38 -08001060 main.log.info( "ONOS was installed on " + node )
1061 return main.TRUE
Jon Hall3576f572016-08-23 10:01:07 -07001062 elif i == 6:
1063 # timeout
kelvin8ec71442015-01-15 16:57:00 -08001064 main.log.info(
1065 "Installation of ONOS on " +
1066 node +
1067 " timed out" )
Devin Limc20e79a2017-06-07 10:29:57 -07001068 self.handle.expect( self.prompt )
Jon Hall53c5e662016-04-13 16:06:56 -07001069 main.log.warn( self.handle.before )
Jon Hall7993bfc2014-10-09 16:30:14 -04001070 return main.FALSE
andrewonlabc03bf6c2014-10-09 14:56:18 -04001071 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001072 main.log.error( self.name + ": EOF exception found" )
1073 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001074 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001075 except Exception:
1076 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001077 main.cleanAndExit()
andrewonlab95ca1462014-10-09 14:04:24 -04001078
kelvin-onlabd3b64892015-01-20 13:26:24 -08001079 def onosStart( self, nodeIp ):
kelvin8ec71442015-01-15 16:57:00 -08001080 """
andrewonlab8d0d7d72014-10-09 16:33:15 -04001081 Calls onos command: 'onos-service [<node-ip>] start'
andrewonlabe8e56fd2014-10-09 17:12:44 -04001082 This command is a remote management of the ONOS upstart daemon
kelvin8ec71442015-01-15 16:57:00 -08001083 """
andrewonlab8d0d7d72014-10-09 16:33:15 -04001084 try:
kelvin8ec71442015-01-15 16:57:00 -08001085 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001086 self.handle.expect( self.prompt )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001087 self.handle.sendline( "onos-service " + str( nodeIp ) +
kelvin8ec71442015-01-15 16:57:00 -08001088 " start" )
1089 i = self.handle.expect( [
andrewonlab8d0d7d72014-10-09 16:33:15 -04001090 "Job\sis\salready\srunning",
1091 "start/running",
Devin Limc20e79a2017-06-07 10:29:57 -07001092 self.prompt,
andrewonlab8d0d7d72014-10-09 16:33:15 -04001093 "Unknown\sinstance",
Jeremy Songster14c13572016-04-21 17:34:03 -07001094 pexpect.TIMEOUT ], timeout=180 )
andrewonlab8d0d7d72014-10-09 16:33:15 -04001095 if i == 0:
Devin Limc20e79a2017-06-07 10:29:57 -07001096 self.handle.expect( self.prompt )
kelvin8ec71442015-01-15 16:57:00 -08001097 main.log.info( "Service is already running" )
andrewonlab8d0d7d72014-10-09 16:33:15 -04001098 return main.TRUE
1099 elif i == 1:
Devin Limc20e79a2017-06-07 10:29:57 -07001100 self.handle.expect( self.prompt )
kelvin8ec71442015-01-15 16:57:00 -08001101 main.log.info( "ONOS service started" )
andrewonlab8d0d7d72014-10-09 16:33:15 -04001102 return main.TRUE
Jeremyd0e9a6d2016-03-02 11:28:52 -08001103 elif i == 2:
1104 main.log.info( "ONOS service started" )
1105 return main.TRUE
andrewonlab8d0d7d72014-10-09 16:33:15 -04001106 else:
Devin Limc20e79a2017-06-07 10:29:57 -07001107 self.handle.expect( self.prompt )
kelvin8ec71442015-01-15 16:57:00 -08001108 main.log.error( "ONOS service failed to start" )
Devin Lim44075962017-08-11 10:56:37 -07001109
1110 main.cleanAndExit()
andrewonlab8d0d7d72014-10-09 16:33:15 -04001111 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001112 main.log.error( self.name + ": EOF exception found" )
1113 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001114 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001115 except Exception:
1116 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001117 main.cleanAndExit()
andrewonlab8d0d7d72014-10-09 16:33:15 -04001118
kelvin-onlabd3b64892015-01-20 13:26:24 -08001119 def onosStop( self, nodeIp ):
kelvin8ec71442015-01-15 16:57:00 -08001120 """
andrewonlab2b30bd32014-10-09 16:48:55 -04001121 Calls onos command: 'onos-service [<node-ip>] stop'
andrewonlabe8e56fd2014-10-09 17:12:44 -04001122 This command is a remote management of the ONOS upstart daemon
kelvin8ec71442015-01-15 16:57:00 -08001123 """
andrewonlab2b30bd32014-10-09 16:48:55 -04001124 try:
kelvin8ec71442015-01-15 16:57:00 -08001125 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001126 self.handle.expect( self.prompt )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001127 self.handle.sendline( "onos-service " + str( nodeIp ) +
kelvin8ec71442015-01-15 16:57:00 -08001128 " stop" )
1129 i = self.handle.expect( [
andrewonlab2b30bd32014-10-09 16:48:55 -04001130 "stop/waiting",
Jon Hall61282e32015-03-19 11:34:11 -07001131 "Could not resolve hostname",
andrewonlab2b30bd32014-10-09 16:48:55 -04001132 "Unknown\sinstance",
Devin Limc20e79a2017-06-07 10:29:57 -07001133 self.prompt,
Jeremy Songster14c13572016-04-21 17:34:03 -07001134 pexpect.TIMEOUT ], timeout=180 )
andrewonlab2b30bd32014-10-09 16:48:55 -04001135 if i == 0:
Devin Limc20e79a2017-06-07 10:29:57 -07001136 self.handle.expect( self.prompt )
kelvin8ec71442015-01-15 16:57:00 -08001137 main.log.info( "ONOS service stopped" )
andrewonlab2b30bd32014-10-09 16:48:55 -04001138 return main.TRUE
1139 elif i == 1:
Devin Limc20e79a2017-06-07 10:29:57 -07001140 self.handle.expect( self.prompt )
Jon Hall65844a32015-03-09 19:09:37 -07001141 main.log.info( "onosStop() Unknown ONOS instance specified: " +
kelvin-onlabd3b64892015-01-20 13:26:24 -08001142 str( nodeIp ) )
andrewonlab2b30bd32014-10-09 16:48:55 -04001143 return main.FALSE
Jon Hall61282e32015-03-19 11:34:11 -07001144 elif i == 2:
Devin Limc20e79a2017-06-07 10:29:57 -07001145 self.handle.expect( self.prompt )
Jon Hall61282e32015-03-19 11:34:11 -07001146 main.log.warn( "ONOS wasn't running" )
1147 return main.TRUE
YPZhang77badfc2016-03-09 10:28:59 -08001148 elif i == 3:
1149 main.log.info( "ONOS service stopped" )
1150 return main.TRUE
andrewonlab2b30bd32014-10-09 16:48:55 -04001151 else:
kelvin8ec71442015-01-15 16:57:00 -08001152 main.log.error( "ONOS service failed to stop" )
andrewonlab2b30bd32014-10-09 16:48:55 -04001153 return main.FALSE
andrewonlab2b30bd32014-10-09 16:48:55 -04001154 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001155 main.log.error( self.name + ": EOF exception found" )
1156 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001157 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001158 except Exception:
1159 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001160 main.cleanAndExit()
kelvin8ec71442015-01-15 16:57:00 -08001161
kelvin-onlabd3b64892015-01-20 13:26:24 -08001162 def onosUninstall( self, nodeIp="" ):
kelvin8ec71442015-01-15 16:57:00 -08001163 """
andrewonlabc8d47972014-10-09 16:52:36 -04001164 Calls the command: 'onos-uninstall'
kelvin8ec71442015-01-15 16:57:00 -08001165 Uninstalls ONOS from the designated cell machine, stopping
andrewonlabe8e56fd2014-10-09 17:12:44 -04001166 if needed
kelvin8ec71442015-01-15 16:57:00 -08001167 """
andrewonlabc8d47972014-10-09 16:52:36 -04001168 try:
kelvin8ec71442015-01-15 16:57:00 -08001169 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001170 self.handle.expect( self.prompt, timeout=180 )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001171 self.handle.sendline( "onos-uninstall " + str( nodeIp ) )
Devin Limc20e79a2017-06-07 10:29:57 -07001172 self.handle.expect( self.prompt, timeout=180 )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001173 main.log.info( "ONOS " + nodeIp + " was uninstalled" )
kelvin8ec71442015-01-15 16:57:00 -08001174 # onos-uninstall command does not return any text
andrewonlabc8d47972014-10-09 16:52:36 -04001175 return main.TRUE
pingping-lin763ee042015-05-20 17:45:30 -07001176 except pexpect.TIMEOUT:
1177 main.log.exception( self.name + ": Timeout in onosUninstall" )
1178 return main.FALSE
andrewonlabc8d47972014-10-09 16:52:36 -04001179 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001180 main.log.error( self.name + ": EOF exception found" )
1181 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001182 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001183 except Exception:
1184 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001185 main.cleanAndExit()
andrewonlab2b30bd32014-10-09 16:48:55 -04001186
kelvin-onlabd3b64892015-01-20 13:26:24 -08001187 def onosDie( self, nodeIp ):
kelvin8ec71442015-01-15 16:57:00 -08001188 """
andrewonlabaedc8332014-12-04 12:43:03 -05001189 Issues the command 'onos-die <node-ip>'
1190 This command calls onos-kill and also stops the node
kelvin8ec71442015-01-15 16:57:00 -08001191 """
andrewonlabaedc8332014-12-04 12:43:03 -05001192 try:
kelvin8ec71442015-01-15 16:57:00 -08001193 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001194 self.handle.expect( self.prompt )
Jeremyf0aecdb2016-03-30 13:19:57 -07001195 cmdStr = "onos-die " + str( nodeIp )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001196 self.handle.sendline( cmdStr )
kelvin8ec71442015-01-15 16:57:00 -08001197 i = self.handle.expect( [
andrewonlabaedc8332014-12-04 12:43:03 -05001198 "Killing\sONOS",
1199 "ONOS\sprocess\sis\snot\srunning",
Jeremy Songster14c13572016-04-21 17:34:03 -07001200 pexpect.TIMEOUT ], timeout=60 )
andrewonlabaedc8332014-12-04 12:43:03 -05001201 if i == 0:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001202 main.log.info( "ONOS instance " + str( nodeIp ) +
kelvin8ec71442015-01-15 16:57:00 -08001203 " was killed and stopped" )
Jon Hall53c5e662016-04-13 16:06:56 -07001204 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001205 self.handle.expect( self.prompt )
andrewonlabaedc8332014-12-04 12:43:03 -05001206 return main.TRUE
1207 elif i == 1:
kelvin8ec71442015-01-15 16:57:00 -08001208 main.log.info( "ONOS process was not running" )
Jon Hall53c5e662016-04-13 16:06:56 -07001209 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001210 self.handle.expect( self.prompt )
andrewonlabaedc8332014-12-04 12:43:03 -05001211 return main.FALSE
1212 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001213 main.log.error( self.name + ": EOF exception found" )
1214 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001215 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001216 except Exception:
1217 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001218 main.cleanAndExit()
andrewonlabaedc8332014-12-04 12:43:03 -05001219
kelvin-onlabd3b64892015-01-20 13:26:24 -08001220 def onosKill( self, nodeIp ):
kelvin8ec71442015-01-15 16:57:00 -08001221 """
andrewonlabe8e56fd2014-10-09 17:12:44 -04001222 Calls the command: 'onos-kill [<node-ip>]'
1223 "Remotely, and unceremoniously kills the ONOS instance running on
1224 the specified cell machine" - Tom V
kelvin8ec71442015-01-15 16:57:00 -08001225 """
andrewonlabe8e56fd2014-10-09 17:12:44 -04001226 try:
kelvin8ec71442015-01-15 16:57:00 -08001227 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001228 self.handle.expect( self.prompt )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001229 self.handle.sendline( "onos-kill " + str( nodeIp ) )
kelvin8ec71442015-01-15 16:57:00 -08001230 i = self.handle.expect( [
Devin Limc20e79a2017-06-07 10:29:57 -07001231 self.prompt,
andrewonlabe8e56fd2014-10-09 17:12:44 -04001232 "No\sroute\sto\shost",
1233 "password:",
Jeremy Songster14c13572016-04-21 17:34:03 -07001234 pexpect.TIMEOUT ], timeout=60 )
kelvin8ec71442015-01-15 16:57:00 -08001235
andrewonlabe8e56fd2014-10-09 17:12:44 -04001236 if i == 0:
kelvin8ec71442015-01-15 16:57:00 -08001237 main.log.info(
1238 "ONOS instance " + str(
kelvin-onlabd3b64892015-01-20 13:26:24 -08001239 nodeIp ) + " was killed" )
andrewonlabe8e56fd2014-10-09 17:12:44 -04001240 return main.TRUE
1241 elif i == 1:
kelvin8ec71442015-01-15 16:57:00 -08001242 main.log.info( "No route to host" )
andrewonlabe8e56fd2014-10-09 17:12:44 -04001243 return main.FALSE
1244 elif i == 2:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001245 main.log.info(
1246 "Passwordless login for host: " +
1247 str( nodeIp ) +
1248 " not configured" )
andrewonlabe8e56fd2014-10-09 17:12:44 -04001249 return main.FALSE
1250 else:
Jon Hallefbd9792015-03-05 16:11:36 -08001251 main.log.info( "ONOS instance was not killed" )
andrewonlabe8e56fd2014-10-09 17:12:44 -04001252 return main.FALSE
kelvin8ec71442015-01-15 16:57:00 -08001253
andrewonlabe8e56fd2014-10-09 17:12:44 -04001254 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001255 main.log.error( self.name + ": EOF exception found" )
1256 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001257 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001258 except Exception:
1259 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001260 main.cleanAndExit()
andrewonlabe8e56fd2014-10-09 17:12:44 -04001261
kelvin-onlabd3b64892015-01-20 13:26:24 -08001262 def onosRemoveRaftLogs( self ):
kelvin8ec71442015-01-15 16:57:00 -08001263 """
andrewonlab19fbdca2014-11-14 12:55:59 -05001264 Removes Raft / Copy cat files from ONOS to ensure
Jon Hallfcc88622014-11-25 13:09:54 -05001265 a cleaner environment.
1266
andrewonlab19fbdca2014-11-14 12:55:59 -05001267 Description:
Jon Hallfcc88622014-11-25 13:09:54 -05001268 Stops all ONOS defined in the cell,
andrewonlab19fbdca2014-11-14 12:55:59 -05001269 wipes the raft / copycat log files
kelvin8ec71442015-01-15 16:57:00 -08001270 """
andrewonlab19fbdca2014-11-14 12:55:59 -05001271 try:
kelvin8ec71442015-01-15 16:57:00 -08001272 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001273 self.handle.expect( self.prompt )
kelvin8ec71442015-01-15 16:57:00 -08001274 self.handle.sendline( "onos-remove-raft-logs" )
1275 # Sometimes this command hangs
Devin Limc20e79a2017-06-07 10:29:57 -07001276 i = self.handle.expect( [ self.prompt, pexpect.TIMEOUT ],
kelvin8ec71442015-01-15 16:57:00 -08001277 timeout=120 )
Jon Hallfcc88622014-11-25 13:09:54 -05001278 if i == 1:
Devin Limc20e79a2017-06-07 10:29:57 -07001279 i = self.handle.expect( [ self.prompt, pexpect.TIMEOUT ],
kelvin8ec71442015-01-15 16:57:00 -08001280 timeout=120 )
Jon Hallfcc88622014-11-25 13:09:54 -05001281 if i == 1:
1282 return main.FALSE
andrewonlab19fbdca2014-11-14 12:55:59 -05001283 return main.TRUE
andrewonlab19fbdca2014-11-14 12:55:59 -05001284 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001285 main.log.error( self.name + ": EOF exception found" )
1286 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001287 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001288 except Exception:
1289 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001290 main.cleanAndExit()
Jon Hallfcc88622014-11-25 13:09:54 -05001291
kelvin-onlabd3b64892015-01-20 13:26:24 -08001292 def onosStartNetwork( self, mntopo ):
kelvin8ec71442015-01-15 16:57:00 -08001293 """
1294 Calls the command 'onos-start-network [ <mininet-topo> ]
1295 "remotely starts the specified topology on the cell's
andrewonlab94282092014-10-10 13:00:11 -04001296 mininet machine against all controllers configured in the
kelvin8ec71442015-01-15 16:57:00 -08001297 cell."
andrewonlab94282092014-10-10 13:00:11 -04001298 * Specify mininet topology file name for mntopo
1299 * Topo files should be placed at:
1300 ~/<your-onos-directory>/tools/test/topos
kelvin8ec71442015-01-15 16:57:00 -08001301
andrewonlab94282092014-10-10 13:00:11 -04001302 NOTE: This function will take you to the mininet prompt
kelvin8ec71442015-01-15 16:57:00 -08001303 """
andrewonlab94282092014-10-10 13:00:11 -04001304 try:
1305 if not mntopo:
kelvin8ec71442015-01-15 16:57:00 -08001306 main.log.error( "You must specify a topo file to execute" )
andrewonlab94282092014-10-10 13:00:11 -04001307 return main.FALSE
andrewonlab94282092014-10-10 13:00:11 -04001308
kelvin8ec71442015-01-15 16:57:00 -08001309 mntopo = str( mntopo )
1310 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001311 self.handle.expect( self.prompt )
andrewonlab94282092014-10-10 13:00:11 -04001312
kelvin8ec71442015-01-15 16:57:00 -08001313 self.handle.sendline( "onos-start-network " + mntopo )
1314 self.handle.expect( "mininet>" )
1315 main.log.info( "Network started, entered mininet prompt" )
1316
1317 # TODO: Think about whether return is necessary or not
andrewonlab94282092014-10-10 13:00:11 -04001318
1319 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001320 main.log.error( self.name + ": EOF exception found" )
1321 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001322 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001323 except Exception:
1324 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001325 main.cleanAndExit()
andrewonlab94282092014-10-10 13:00:11 -04001326
Jeremy Songster14c13572016-04-21 17:34:03 -07001327 def isup( self, node="", timeout=240 ):
kelvin8ec71442015-01-15 16:57:00 -08001328 """
1329 Run's onos-wait-for-start which only returns once ONOS is at run
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001330 level 100(ready for use)
andrewonlab8d0d7d72014-10-09 16:33:15 -04001331
Jon Hall7993bfc2014-10-09 16:30:14 -04001332 Returns: main.TRUE if ONOS is running and main.FALSE on timeout
kelvin8ec71442015-01-15 16:57:00 -08001333 """
Jon Hall7993bfc2014-10-09 16:30:14 -04001334 try:
Jon Hall3b489db2015-10-05 14:38:37 -07001335 self.handle.sendline( "onos-wait-for-start " + node )
1336 self.handle.expect( "onos-wait-for-start" )
kelvin8ec71442015-01-15 16:57:00 -08001337 # NOTE: this timeout is arbitrary"
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001338 i = self.handle.expect( [ self.prompt, pexpect.TIMEOUT ], timeout )
Jon Hall7993bfc2014-10-09 16:30:14 -04001339 if i == 0:
kelvin8ec71442015-01-15 16:57:00 -08001340 main.log.info( self.name + ": " + node + " is up" )
Jon Hall7993bfc2014-10-09 16:30:14 -04001341 return main.TRUE
1342 elif i == 1:
kelvin8ec71442015-01-15 16:57:00 -08001343 # NOTE: since this function won't return until ONOS is ready,
Jon Hall7993bfc2014-10-09 16:30:14 -04001344 # we will kill it on timeout
kelvin8ec71442015-01-15 16:57:00 -08001345 main.log.error( "ONOS has not started yet" )
1346 self.handle.send( "\x03" ) # Control-C
Devin Limc20e79a2017-06-07 10:29:57 -07001347 self.handle.expect( self.prompt )
Jon Hall7993bfc2014-10-09 16:30:14 -04001348 return main.FALSE
1349 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001350 main.log.error( self.name + ": EOF exception found" )
1351 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001352 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001353 except Exception:
1354 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001355 main.cleanAndExit()
andrewonlab05e362f2014-10-10 00:40:57 -04001356
Devin Lim142b5342017-07-20 15:22:39 -07001357 def preventAutoRespawn( self ):
1358 """
1359 Description:
1360 This will prevent ONOSservice to automatically
1361 respawn.
1362 """
1363 try:
1364 self.handle.sendline( "sed -i -e 's/^respawn$/#respawn/g' tools/package/init/onos.conf" )
1365 self.handle.expect( "\$" ) # $ from the command
1366 self.handle.sendline( "sed -i -e 's/^Restart=always/Restart=no/g' tools/package/init/onos.service" )
1367 self.handle.expect( "\$" ) # $ from the command
1368 self.handle.expect( "\$" ) # $ from the prompt
1369 except pexpect.EOF:
1370 main.log.error( self.name + ": EOF exception found" )
1371 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001372 main.cleanAndExit()
Devin Lim142b5342017-07-20 15:22:39 -07001373 except Exception:
1374 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001375 main.cleanAndExit()
Devin Lim142b5342017-07-20 15:22:39 -07001376
kelvin-onlabd3b64892015-01-20 13:26:24 -08001377 def pushTestIntentsShell(
1378 self,
1379 dpidSrc,
1380 dpidDst,
1381 numIntents,
1382 dirFile,
1383 onosIp,
1384 numMult="",
1385 appId="",
1386 report=True,
1387 options="" ):
kelvin8ec71442015-01-15 16:57:00 -08001388 """
andrewonlabb66dfa12014-12-02 15:51:10 -05001389 Description:
kelvin8ec71442015-01-15 16:57:00 -08001390 Use the linux prompt to push test intents to
andrewonlabb66dfa12014-12-02 15:51:10 -05001391 better parallelize the results than the CLI
1392 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001393 * dpidSrc: specify source dpid
1394 * dpidDst: specify destination dpid
1395 * numIntents: specify number of intents to push
1396 * dirFile: specify directory and file name to save
andrewonlabb66dfa12014-12-02 15:51:10 -05001397 results
kelvin-onlabd3b64892015-01-20 13:26:24 -08001398 * onosIp: specify the IP of ONOS to install on
kelvin8ec71442015-01-15 16:57:00 -08001399 NOTE:
andrewonlabb66dfa12014-12-02 15:51:10 -05001400 You must invoke this command at linux shell prompt
kelvin8ec71442015-01-15 16:57:00 -08001401 """
1402 try:
1403 # Create the string to sendline
andrewonlabaedc8332014-12-04 12:43:03 -05001404 if options:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001405 baseCmd = "onos " + str( onosIp ) + " push-test-intents " +\
kelvin8ec71442015-01-15 16:57:00 -08001406 options + " "
andrewonlabaedc8332014-12-04 12:43:03 -05001407 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001408 baseCmd = "onos " + str( onosIp ) + " push-test-intents "
kelvin8ec71442015-01-15 16:57:00 -08001409
kelvin-onlabd3b64892015-01-20 13:26:24 -08001410 addDpid = baseCmd + str( dpidSrc ) + " " + str( dpidDst )
1411 if not numMult:
1412 addIntents = addDpid + " " + str( numIntents )
1413 elif numMult:
1414 addIntents = addDpid + " " + str( numIntents ) + " " +\
1415 str( numMult )
1416 if appId:
1417 addApp = addIntents + " " + str( appId )
andrewonlabb66dfa12014-12-02 15:51:10 -05001418 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001419 addApp = addIntents
andrewonlabb66dfa12014-12-02 15:51:10 -05001420
andrewonlabaedc8332014-12-04 12:43:03 -05001421 if report:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001422 sendCmd = addApp + " > " + str( dirFile ) + " &"
andrewonlabaedc8332014-12-04 12:43:03 -05001423 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001424 sendCmd = addApp + " &"
1425 main.log.info( "Send cmd: " + sendCmd )
andrewonlabb66dfa12014-12-02 15:51:10 -05001426
kelvin-onlabd3b64892015-01-20 13:26:24 -08001427 self.handle.sendline( sendCmd )
andrewonlabb66dfa12014-12-02 15:51:10 -05001428
1429 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001430 main.log.error( self.name + ": EOF exception found" )
1431 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001432 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001433 except Exception:
1434 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001435 main.cleanAndExit()
andrewonlab05e362f2014-10-10 00:40:57 -04001436
kelvin-onlabd3b64892015-01-20 13:26:24 -08001437 def tsharkPcap( self, interface, dirFile ):
kelvin8ec71442015-01-15 16:57:00 -08001438 """
andrewonlab970399c2014-11-07 13:09:32 -05001439 Capture all packet activity and store in specified
1440 directory/file
1441
1442 Required:
1443 * interface: interface to capture
1444 * dir: directory/filename to store pcap
kelvin8ec71442015-01-15 16:57:00 -08001445 """
Jon Hallfebb1c72015-03-05 13:30:09 -08001446 try:
1447 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001448 self.handle.expect( self.prompt )
andrewonlab970399c2014-11-07 13:09:32 -05001449
cameron@onlab.us21106ea2015-07-23 15:32:51 -07001450 self.handle.sendline( "tshark -i " + str( interface ) + " -t e -w " + str( dirFile ) + " &" )
Jon Hall5ec6b1b2015-09-17 18:20:14 -07001451 self.handle.sendline( "\n" )
Jon Hallfebb1c72015-03-05 13:30:09 -08001452 self.handle.expect( "Capturing on" )
Jon Hall5ec6b1b2015-09-17 18:20:14 -07001453 self.handle.sendline( "\n" )
Devin Limc20e79a2017-06-07 10:29:57 -07001454 self.handle.expect( self.prompt )
andrewonlab970399c2014-11-07 13:09:32 -05001455
Jon Hallfebb1c72015-03-05 13:30:09 -08001456 main.log.info( "Tshark started capturing files on " +
1457 str( interface ) + " and saving to directory: " +
1458 str( dirFile ) )
1459 except pexpect.EOF:
1460 main.log.error( self.name + ": EOF exception found" )
1461 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001462 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001463 except Exception:
1464 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001465 main.cleanAndExit()
Shreya Shaha73aaad2014-10-27 18:03:09 -04001466
kelvin-onlabd9e23de2015-08-06 10:34:44 -07001467 def onosTopoCfg( self, onosIp, jsonFile ):
kelvin8ec71442015-01-15 16:57:00 -08001468 """
kelvin-onlabd9e23de2015-08-06 10:34:44 -07001469 Description:
1470 Execute onos-topo-cfg command
1471 Required:
1472 onosIp - IP of the onos node you want to send the json to
1473 jsonFile - File path of the json file
1474 Return:
1475 Returns main.TRUE if the command is successfull; Returns
1476 main.FALSE if there was an error
kelvin8ec71442015-01-15 16:57:00 -08001477 """
shahshreyae6c7cf42014-11-26 16:39:01 -08001478 try:
kelvin8ec71442015-01-15 16:57:00 -08001479 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001480 self.handle.expect( self.prompt )
kelvin-onlabd9e23de2015-08-06 10:34:44 -07001481 cmd = "onos-topo-cfg "
1482 self.handle.sendline( cmd + str( onosIp ) + " " + jsonFile )
1483 handle = self.handle.before
1484 print handle
1485 if "Error" in handle:
1486 main.log.error( self.name + ": " + self.handle.before )
1487 return main.FALSE
1488 else:
Devin Limc20e79a2017-06-07 10:29:57 -07001489 self.handle.expect( self.prompt )
kelvin-onlabd9e23de2015-08-06 10:34:44 -07001490 return main.TRUE
1491
Jon Hallfebb1c72015-03-05 13:30:09 -08001492 except pexpect.EOF:
1493 main.log.error( self.name + ": EOF exception found" )
1494 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001495 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001496 except Exception:
1497 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001498 main.cleanAndExit()
kelvin8ec71442015-01-15 16:57:00 -08001499
jenkins1e99e7b2015-04-02 18:15:39 -07001500 def tsharkGrep( self, grep, directory, interface='eth0', grepOptions='' ):
kelvin8ec71442015-01-15 16:57:00 -08001501 """
andrewonlabba44bcf2014-10-16 16:54:41 -04001502 Required:
kelvin8ec71442015-01-15 16:57:00 -08001503 * grep string
andrewonlabba44bcf2014-10-16 16:54:41 -04001504 * directory to store results
1505 Optional:
1506 * interface - default: eth0
Jon Hall4ba53f02015-07-29 13:07:41 -07001507 * grepOptions - options for grep
andrewonlabba44bcf2014-10-16 16:54:41 -04001508 Description:
1509 Uses tshark command to grep specific group of packets
1510 and stores the results to specified directory.
kelvin8ec71442015-01-15 16:57:00 -08001511 The timestamp is hardcoded to be in epoch
1512 """
Jon Hallfebb1c72015-03-05 13:30:09 -08001513 try:
1514 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001515 self.handle.expect( self.prompt )
Jon Hallfebb1c72015-03-05 13:30:09 -08001516 self.handle.sendline( "" )
jenkins1e99e7b2015-04-02 18:15:39 -07001517 if grepOptions:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001518 grepStr = "grep " + str( grepOptions )
jenkins1e99e7b2015-04-02 18:15:39 -07001519 else:
1520 grepStr = "grep"
Jon Hall4ba53f02015-07-29 13:07:41 -07001521
cameron@onlab.us21106ea2015-07-23 15:32:51 -07001522 cmd = (
1523 "sudo tshark -i " +
Jon Hallfebb1c72015-03-05 13:30:09 -08001524 str( interface ) +
jenkins1e99e7b2015-04-02 18:15:39 -07001525 " -t e | " +
1526 grepStr + " --line-buffered \"" +
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001527 str( grep ) +
Jon Hallfebb1c72015-03-05 13:30:09 -08001528 "\" >" +
1529 directory +
1530 " &" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001531 self.handle.sendline( cmd )
1532 main.log.info( cmd )
Jon Hallfebb1c72015-03-05 13:30:09 -08001533 self.handle.expect( "Capturing on" )
cameron@onlab.us21106ea2015-07-23 15:32:51 -07001534 self.handle.sendline( "\n" )
Devin Limc20e79a2017-06-07 10:29:57 -07001535 self.handle.expect( self.prompt )
Jon Hallfebb1c72015-03-05 13:30:09 -08001536 except pexpect.EOF:
1537 main.log.error( self.name + ": EOF exception found" )
1538 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001539 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001540 except Exception:
1541 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001542 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001543
kelvin-onlabd3b64892015-01-20 13:26:24 -08001544 def tsharkStop( self ):
kelvin8ec71442015-01-15 16:57:00 -08001545 """
andrewonlabba44bcf2014-10-16 16:54:41 -04001546 Removes wireshark files from /tmp and kills all tshark processes
kelvin8ec71442015-01-15 16:57:00 -08001547 """
1548 # Remove all pcap from previous captures
Jon Hallfebb1c72015-03-05 13:30:09 -08001549 try:
1550 self.execute( cmd="sudo rm /tmp/wireshark*" )
1551 self.handle.sendline( "" )
Jon Hallefbd9792015-03-05 16:11:36 -08001552 self.handle.sendline( "sudo kill -9 `ps -ef | grep \"tshark -i\"" +
1553 " | grep -v grep | awk '{print $2}'`" )
Jon Hallfebb1c72015-03-05 13:30:09 -08001554 self.handle.sendline( "" )
1555 main.log.info( "Tshark stopped" )
1556 except pexpect.EOF:
1557 main.log.error( self.name + ": EOF exception found" )
1558 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001559 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001560 except Exception:
1561 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001562 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001563
kelvin8ec71442015-01-15 16:57:00 -08001564 def ptpd( self, args ):
1565 """
andrewonlab0c38a4a2014-10-28 18:35:35 -04001566 Initiate ptp with user-specified args.
1567 Required:
1568 * args: specify string of args after command
1569 'sudo ptpd'
kelvin8ec71442015-01-15 16:57:00 -08001570 """
andrewonlab0c38a4a2014-10-28 18:35:35 -04001571 try:
kelvin8ec71442015-01-15 16:57:00 -08001572 self.handle.sendline( "sudo ptpd " + str( args ) )
1573 i = self.handle.expect( [
andrewonlab0c38a4a2014-10-28 18:35:35 -04001574 "Multiple",
1575 "Error",
Devin Limc20e79a2017-06-07 10:29:57 -07001576 self.prompt ] )
1577 self.handle.expect( self.prompt )
andrewonlabba44bcf2014-10-16 16:54:41 -04001578
andrewonlab0c38a4a2014-10-28 18:35:35 -04001579 if i == 0:
1580 handle = self.handle.before
kelvin8ec71442015-01-15 16:57:00 -08001581 main.log.info( "ptpd returned an error: " +
1582 str( handle ) )
andrewonlab0c38a4a2014-10-28 18:35:35 -04001583 return handle
1584 elif i == 1:
1585 handle = self.handle.before
kelvin8ec71442015-01-15 16:57:00 -08001586 main.log.error( "ptpd returned an error: " +
1587 str( handle ) )
andrewonlab0c38a4a2014-10-28 18:35:35 -04001588 return handle
1589 else:
1590 return main.TRUE
kelvin8ec71442015-01-15 16:57:00 -08001591
andrewonlab0c38a4a2014-10-28 18:35:35 -04001592 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001593 main.log.error( self.name + ": EOF exception found" )
1594 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001595 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001596 except Exception:
1597 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001598 main.cleanAndExit()
andrewonlabba44bcf2014-10-16 16:54:41 -04001599
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001600 def dumpONOSCmd( self, ONOSIp, CMD, destDir, filename, options="" ):
Flavio Castrod2ffffa2016-04-26 15:56:56 -07001601 """
Pier50f0bc62016-09-07 17:53:40 -07001602 Dump Cmd to a desired directory.
Flavio Castrod2ffffa2016-04-26 15:56:56 -07001603 For debugging purposes, you may want to use
Pier50f0bc62016-09-07 17:53:40 -07001604 this function to capture Cmd at a given point in time.
Flavio Castrod2ffffa2016-04-26 15:56:56 -07001605 Localtime will be attached to the filename
1606
1607 Required:
1608 * ONOSIp: the IP of the target ONOS instance
Pier50f0bc62016-09-07 17:53:40 -07001609 * CMD: the command to dump;
Flavio Castrod2ffffa2016-04-26 15:56:56 -07001610 * destDir: specify directory to copy to.
1611 ex ) /tmp/
Flavio Castrod2ffffa2016-04-26 15:56:56 -07001612 * fileName: Name of the file
Pier50f0bc62016-09-07 17:53:40 -07001613 * options: Options for ONOS command
Flavio Castrod2ffffa2016-04-26 15:56:56 -07001614 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001615
Flavio Castrod2ffffa2016-04-26 15:56:56 -07001616 localtime = time.strftime( '%x %X' )
1617 localtime = localtime.replace( "/", "" )
1618 localtime = localtime.replace( " ", "_" )
1619 localtime = localtime.replace( ":", "" )
1620 if destDir[ -1: ] != "/":
1621 destDir += "/"
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001622 cmd = CMD + " " + options + " > " + str( destDir ) + str( filename ) + localtime
1623 return self.onosCli( ONOSIp, cmd )
Flavio Castrob7718952016-05-18 08:53:41 -07001624
kelvin-onlabd3b64892015-01-20 13:26:24 -08001625 def cpLogsToDir( self, logToCopy,
Jon Hallefbd9792015-03-05 16:11:36 -08001626 destDir, copyFileName="" ):
kelvin8ec71442015-01-15 16:57:00 -08001627 """
1628 Copies logs to a desired directory.
andrewonlab5d7a8f32014-11-10 13:07:56 -05001629 Current implementation of ONOS deletes its karaf
1630 logs on every iteration. For debugging purposes,
kelvin8ec71442015-01-15 16:57:00 -08001631 you may want to use this function to capture
1632 certain karaf logs. ( or any other logs if needed )
andrewonlab5d7a8f32014-11-10 13:07:56 -05001633 Localtime will be attached to the filename
1634
1635 Required:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001636 * logToCopy: specify directory and log name to
andrewonlab5d7a8f32014-11-10 13:07:56 -05001637 copy.
kelvin8ec71442015-01-15 16:57:00 -08001638 ex ) /opt/onos/log/karaf.log.1
kelvin-onlabd3b64892015-01-20 13:26:24 -08001639 For copying multiple files, leave copyFileName
1640 empty and only specify destDir -
kelvin8ec71442015-01-15 16:57:00 -08001641 ex ) /opt/onos/log/karaf*
kelvin-onlabd3b64892015-01-20 13:26:24 -08001642 * destDir: specify directory to copy to.
kelvin8ec71442015-01-15 16:57:00 -08001643 ex ) /tmp/
1644 Optional:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001645 * copyFileName: If you want to rename the log
1646 file, specify copyFileName. This will not work
andrewonlab5d7a8f32014-11-10 13:07:56 -05001647 with multiple file copying
kelvin8ec71442015-01-15 16:57:00 -08001648 """
andrewonlab5d7a8f32014-11-10 13:07:56 -05001649 try:
Flavio Castro09ab59d2016-05-25 17:01:35 -07001650 localtime = time.strftime( '%H %M' )
kelvin8ec71442015-01-15 16:57:00 -08001651 localtime = localtime.replace( "/", "" )
1652 localtime = localtime.replace( " ", "_" )
1653 localtime = localtime.replace( ":", "" )
kelvin-onlabd3b64892015-01-20 13:26:24 -08001654 if destDir[ -1: ] != "/":
1655 destDir += "/"
andrewonlab5d7a8f32014-11-10 13:07:56 -05001656
kelvin-onlabd3b64892015-01-20 13:26:24 -08001657 if copyFileName:
Jon Hallfebb1c72015-03-05 13:30:09 -08001658 self.handle.sendline( "cp " + str( logToCopy ) + " " +
1659 str( destDir ) + str( copyFileName ) +
1660 localtime )
kelvin8ec71442015-01-15 16:57:00 -08001661 self.handle.expect( "cp" )
Devin Limc20e79a2017-06-07 10:29:57 -07001662 self.handle.expect( self.prompt )
andrewonlab5d7a8f32014-11-10 13:07:56 -05001663 else:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001664 self.handle.sendline( "cp " + str( logToCopy ) +
1665 " " + str( destDir ) )
kelvin8ec71442015-01-15 16:57:00 -08001666 self.handle.expect( "cp" )
Devin Limc20e79a2017-06-07 10:29:57 -07001667 self.handle.expect( self.prompt )
andrewonlab5d7a8f32014-11-10 13:07:56 -05001668
kelvin8ec71442015-01-15 16:57:00 -08001669 return self.handle.before
1670
1671 except pexpect.EOF:
1672 main.log.error( "Copying files failed" )
1673 main.log.error( self.name + ": EOF exception found" )
1674 main.log.error( self.name + ": " + self.handle.before )
Jon Hallfebb1c72015-03-05 13:30:09 -08001675 except Exception:
1676 main.log.exception( "Copying files failed" )
1677
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001678 def checkLogs( self, onosIp, restart=False ):
kelvin8ec71442015-01-15 16:57:00 -08001679 """
Jon Hall94fd0472014-12-08 11:52:42 -08001680 runs onos-check-logs on the given onos node
Jon Hall80daded2015-05-27 16:07:00 -07001681 If restart is True, use the old version of onos-check-logs which
1682 does not print the full stacktrace, but shows the entire log file,
1683 including across restarts
Jon Hall94fd0472014-12-08 11:52:42 -08001684 returns the response
kelvin8ec71442015-01-15 16:57:00 -08001685 """
Jon Hall94fd0472014-12-08 11:52:42 -08001686 try:
kelvin-onlabd3b64892015-01-20 13:26:24 -08001687 cmd = "onos-check-logs " + str( onosIp )
Jon Hall16b72c42015-05-20 10:23:36 -07001688 if restart:
1689 cmd += " old"
kelvin8ec71442015-01-15 16:57:00 -08001690 self.handle.sendline( cmd )
1691 self.handle.expect( cmd )
Devin Limdc78e202017-06-09 18:30:07 -07001692 self.handle.expect( self.prompt + " " )
Jon Hall94fd0472014-12-08 11:52:42 -08001693 response = self.handle.before
1694 return response
1695 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001696 main.log.error( "Lost ssh connection" )
1697 main.log.error( self.name + ": EOF exception found" )
1698 main.log.error( self.name + ": " + self.handle.before )
Jon Hallfebb1c72015-03-05 13:30:09 -08001699 except Exception:
1700 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001701 main.cleanAndExit()
Jon Hall94fd0472014-12-08 11:52:42 -08001702
kelvin-onlabd3b64892015-01-20 13:26:24 -08001703 def onosStatus( self, node="" ):
kelvin8ec71442015-01-15 16:57:00 -08001704 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08001705 Calls onos command: 'onos-service [<node-ip>] status'
kelvin8ec71442015-01-15 16:57:00 -08001706 """
Hari Krishnaa43d4e92014-12-19 13:22:40 -08001707 try:
kelvin8ec71442015-01-15 16:57:00 -08001708 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001709 self.handle.expect( self.prompt )
kelvin8ec71442015-01-15 16:57:00 -08001710 self.handle.sendline( "onos-service " + str( node ) +
1711 " status" )
1712 i = self.handle.expect( [
You Wangef1e6572016-03-08 12:53:18 -08001713 "start/running",
You Wang7bd83062016-03-01 11:50:00 -08001714 "Running ...",
You Wangef1e6572016-03-08 12:53:18 -08001715 "stop/waiting",
You Wang7bd83062016-03-01 11:50:00 -08001716 "Not Running ...",
kelvin8ec71442015-01-15 16:57:00 -08001717 pexpect.TIMEOUT ], timeout=120 )
YPZhangfebf7302016-05-24 16:45:56 -07001718 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001719 self.handle.expect( self.prompt )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08001720
You Wangef1e6572016-03-08 12:53:18 -08001721 if i == 0 or i == 1:
kelvin8ec71442015-01-15 16:57:00 -08001722 main.log.info( "ONOS is running" )
Hari Krishnaa43d4e92014-12-19 13:22:40 -08001723 return main.TRUE
You Wangef1e6572016-03-08 12:53:18 -08001724 elif i == 2 or i == 3:
kelvin8ec71442015-01-15 16:57:00 -08001725 main.log.info( "ONOS is stopped" )
kelvin8ec71442015-01-15 16:57:00 -08001726 main.log.error( "ONOS service failed to check the status" )
Devin Lim44075962017-08-11 10:56:37 -07001727
1728 main.cleanAndExit()
Hari Krishnaa43d4e92014-12-19 13:22:40 -08001729 except pexpect.EOF:
kelvin8ec71442015-01-15 16:57:00 -08001730 main.log.error( self.name + ": EOF exception found" )
1731 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001732 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001733 except Exception:
1734 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001735 main.cleanAndExit()
Jon Hall21270ac2015-02-16 17:59:55 -08001736
Jon Hall63604932015-02-26 17:09:50 -08001737 def setIpTables( self, ip, port='', action='add', packet_type='',
1738 direction='INPUT', rule='DROP', states=True ):
Jon Hallefbd9792015-03-05 16:11:36 -08001739 """
Jon Hall21270ac2015-02-16 17:59:55 -08001740 Description:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001741 add or remove iptables rule to DROP (default) packets from
Jon Hall21270ac2015-02-16 17:59:55 -08001742 specific IP and PORT
1743 Usage:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001744 * specify action ('add' or 'remove')
Jon Hall21270ac2015-02-16 17:59:55 -08001745 when removing, pass in the same argument as you would add. It will
1746 delete that specific rule.
1747 * specify the ip to block
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001748 * specify the destination port to block (defaults to all ports)
1749 * optional packet type to block (default tcp)
1750 * optional iptables rule (default DROP)
1751 * optional direction to block (default 'INPUT')
Jon Hall63604932015-02-26 17:09:50 -08001752 * States boolean toggles adding all supported tcp states to the
1753 firewall rule
Jon Hall21270ac2015-02-16 17:59:55 -08001754 Returns:
1755 main.TRUE on success or
1756 main.FALSE if given invalid input or
1757 main.ERROR if there is an error in response from iptables
1758 WARNING:
1759 * This function uses root privilege iptables command which may result
1760 in unwanted network errors. USE WITH CAUTION
Jon Hallefbd9792015-03-05 16:11:36 -08001761 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001762
Jon Hall21270ac2015-02-16 17:59:55 -08001763 # NOTE*********
1764 # The strict checking methods of this driver function is intentional
1765 # to discourage any misuse or error of iptables, which can cause
1766 # severe network errors
1767 # *************
1768
1769 # NOTE: Sleep needed to give some time for rule to be added and
1770 # registered to the instance. If you are calling this function
1771 # multiple times this sleep will prevent any errors.
1772 # DO NOT REMOVE
Jon Hall63604932015-02-26 17:09:50 -08001773 # time.sleep( 5 )
Jon Hall21270ac2015-02-16 17:59:55 -08001774 try:
1775 # input validation
1776 action_type = action.lower()
1777 rule = rule.upper()
1778 direction = direction.upper()
1779 if action_type != 'add' and action_type != 'remove':
1780 main.log.error( "Invalid action type. Use 'add' or "
1781 "'remove' table rule" )
1782 if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
1783 # NOTE Currently only supports rules DROP, ACCEPT, and LOG
1784 main.log.error( "Invalid rule. Valid rules are 'DROP' or "
1785 "'ACCEPT' or 'LOG' only." )
1786 if direction != 'INPUT' and direction != 'OUTPUT':
1787 # NOTE currently only supports rules INPUT and OUPTUT
1788 main.log.error( "Invalid rule. Valid directions are"
1789 " 'OUTPUT' or 'INPUT'" )
1790 return main.FALSE
1791 return main.FALSE
1792 return main.FALSE
1793 if action_type == 'add':
1794 # -A is the 'append' action of iptables
1795 actionFlag = '-A'
1796 elif action_type == 'remove':
1797 # -D is the 'delete' rule of iptables
1798 actionFlag = '-D'
1799 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001800 self.handle.expect( self.prompt )
Jon Hall21270ac2015-02-16 17:59:55 -08001801 cmd = "sudo iptables " + actionFlag + " " +\
1802 direction +\
Jon Hall21270ac2015-02-16 17:59:55 -08001803 " -s " + str( ip )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001804 # " -p " + str( packet_type ) +\
Jon Hall63604932015-02-26 17:09:50 -08001805 if packet_type:
1806 cmd += " -p " + str( packet_type )
Jon Hall21270ac2015-02-16 17:59:55 -08001807 if port:
1808 cmd += " --dport " + str( port )
Jon Hall63604932015-02-26 17:09:50 -08001809 if states:
1810 cmd += " -m state --state="
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001811 # FIXME- Allow user to configure which states to block
Jon Hall63604932015-02-26 17:09:50 -08001812 cmd += "INVALID,ESTABLISHED,NEW,RELATED,UNTRACKED"
Jon Hall21270ac2015-02-16 17:59:55 -08001813 cmd += " -j " + str( rule )
1814
1815 self.handle.sendline( cmd )
Devin Limc20e79a2017-06-07 10:29:57 -07001816 self.handle.expect( self.prompt )
Jon Hall21270ac2015-02-16 17:59:55 -08001817 main.log.warn( self.handle.before )
1818
1819 info_string = "On " + str( self.name )
1820 info_string += " " + str( action_type )
1821 info_string += " iptable rule [ "
1822 info_string += " IP: " + str( ip )
1823 info_string += " Port: " + str( port )
1824 info_string += " Rule: " + str( rule )
1825 info_string += " Direction: " + str( direction ) + " ]"
1826 main.log.info( info_string )
1827 return main.TRUE
1828 except pexpect.TIMEOUT:
1829 main.log.exception( self.name + ": Timeout exception in "
1830 "setIpTables function" )
1831 return main.ERROR
1832 except pexpect.EOF:
1833 main.log.error( self.name + ": EOF exception found" )
1834 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001835 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001836 except Exception:
1837 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001838 main.cleanAndExit()
Jon Hall21270ac2015-02-16 17:59:55 -08001839
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001840 def detailed_status( self, log_filename ):
Jon Hallefbd9792015-03-05 16:11:36 -08001841 """
Jon Hall0468b042015-02-19 19:08:21 -08001842 This method is used by STS to check the status of the controller
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001843 Reports RUNNING, STARTING, STOPPED, FROZEN, ERROR (and reason)
Jon Hallefbd9792015-03-05 16:11:36 -08001844 """
Jon Hall0468b042015-02-19 19:08:21 -08001845 import re
1846 try:
1847 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07001848 self.handle.expect( self.prompt )
Jon Hall0468b042015-02-19 19:08:21 -08001849 self.handle.sendline( "cd " + self.home )
Devin Limc20e79a2017-06-07 10:29:57 -07001850 self.handle.expect( self.prompt )
Jon Hall0468b042015-02-19 19:08:21 -08001851 self.handle.sendline( "service onos status" )
Devin Limc20e79a2017-06-07 10:29:57 -07001852 self.handle.expect( self.prompt )
Jon Hall0468b042015-02-19 19:08:21 -08001853 response = self.handle.before
1854 if re.search( "onos start/running", response ):
1855 # onos start/running, process 10457
1856 return 'RUNNING'
1857 # FIXME: Implement this case
1858 # elif re.search( pattern, response ):
1859 # return 'STARTING'
1860 elif re.search( "onos stop/", response ):
1861 # onos stop/waiting
1862 # FIXME handle this differently?: onos stop/pre-stop
1863 return 'STOPPED'
1864 # FIXME: Implement this case
1865 # elif re.search( pattern, response ):
1866 # return 'FROZEN'
1867 else:
1868 main.log.warn( self.name +
Jon Hallefbd9792015-03-05 16:11:36 -08001869 " WARNING: status received unknown response" )
Jon Hall0468b042015-02-19 19:08:21 -08001870 main.log.warn( response )
1871 return 'ERROR', "Unknown response: %s" % response
1872 except pexpect.TIMEOUT:
1873 main.log.exception( self.name + ": Timeout exception in "
1874 "setIpTables function" )
1875 return 'ERROR', "Pexpect Timeout"
1876 except pexpect.EOF:
1877 main.log.error( self.name + ": EOF exception found" )
1878 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07001879 main.cleanAndExit()
Jon Hallfebb1c72015-03-05 13:30:09 -08001880 except Exception:
1881 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07001882 main.cleanAndExit()
Jon Hall0468b042015-02-19 19:08:21 -08001883
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001884 def createLinkGraphFile( self, benchIp, ONOSIpList, deviceCount ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001885 '''
Jon Hall4ba53f02015-07-29 13:07:41 -07001886 Create/formats the LinkGraph.cfg file based on arguments
1887 -only creates a linear topology and connects islands
1888 -evenly distributes devices
andrew@onlab.us3b087132015-03-11 15:00:08 -07001889 -must be called by ONOSbench
1890
Jon Hall4ba53f02015-07-29 13:07:41 -07001891 ONOSIpList - list of all of the node IPs to be used
1892
1893 deviceCount - number of switches to be assigned
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001894 '''
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001895 main.log.info( "Creating link graph configuration file." )
andrew@onlab.us3b087132015-03-11 15:00:08 -07001896 linkGraphPath = self.home + "/tools/package/etc/linkGraph.cfg"
Jon Hall4ba53f02015-07-29 13:07:41 -07001897 tempFile = "/tmp/linkGraph.cfg"
andrew@onlab.us3b087132015-03-11 15:00:08 -07001898
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001899 linkGraph = open( tempFile, 'w+' )
1900 linkGraph.write( "# NullLinkProvider topology description (config file).\n" )
1901 linkGraph.write( "# The NodeId is only added if the destination is another node's device.\n" )
1902 linkGraph.write( "# Bugs: Comments cannot be appended to a line to be read.\n" )
Jon Hall4ba53f02015-07-29 13:07:41 -07001903
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001904 clusterCount = len( ONOSIpList )
Jon Hall4ba53f02015-07-29 13:07:41 -07001905
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001906 if isinstance( deviceCount, int ) or isinstance( deviceCount, str ):
1907 deviceCount = int( deviceCount )
1908 switchList = [ 0 ]*( clusterCount+1 )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001909 baselineSwitchCount = deviceCount/clusterCount
Jon Hall4ba53f02015-07-29 13:07:41 -07001910
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001911 for node in range( 1, clusterCount + 1 ):
1912 switchList[ node ] = baselineSwitchCount
andrew@onlab.us3b087132015-03-11 15:00:08 -07001913
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001914 for node in range( 1, ( deviceCount % clusterCount )+1 ):
1915 switchList[ node ] += 1
Jon Hall4ba53f02015-07-29 13:07:41 -07001916
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001917 if isinstance( deviceCount, list ):
1918 main.log.info( "Using provided device distribution" )
1919 switchList = [ 0 ]
andrew@onlab.us3b087132015-03-11 15:00:08 -07001920 for i in deviceCount:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001921 switchList.append( int( i ) )
andrew@onlab.us3b087132015-03-11 15:00:08 -07001922
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001923 tempList = [ '0' ]
1924 tempList.extend( ONOSIpList )
andrew@onlab.us3b087132015-03-11 15:00:08 -07001925 ONOSIpList = tempList
1926
1927 myPort = 6
1928 lastSwitch = 0
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001929 for node in range( 1, clusterCount+1 ):
1930 if switchList[ node ] == 0:
andrew@onlab.us3b087132015-03-11 15:00:08 -07001931 continue
1932
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001933 linkGraph.write( "graph " + ONOSIpList[ node ] + " {\n" )
Jon Hall4ba53f02015-07-29 13:07:41 -07001934
andrew@onlab.us3b087132015-03-11 15:00:08 -07001935 if node > 1:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001936 # connect to last device on previous node
1937 line = ( "\t0:5 -> " + str( lastSwitch ) + ":6:" + lastIp + "\n" ) # ONOSIpList[node-1]
1938 linkGraph.write( line )
Jon Hall4ba53f02015-07-29 13:07:41 -07001939
1940 lastSwitch = 0
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001941 for switch in range( 0, switchList[ node ]-1 ):
andrew@onlab.us3b087132015-03-11 15:00:08 -07001942 line = ""
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001943 line = ( "\t" + str( switch ) + ":" + str( myPort ) )
andrew@onlab.us3b087132015-03-11 15:00:08 -07001944 line += " -- "
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001945 line += ( str( switch+1 ) + ":" + str( myPort-1 ) + "\n" )
1946 linkGraph.write( line )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001947 lastSwitch = switch+1
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001948 lastIp = ONOSIpList[ node ]
Jon Hall4ba53f02015-07-29 13:07:41 -07001949
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001950 # lastSwitch += 1
1951 if node < ( clusterCount ):
1952 # connect to first device on the next node
1953 line = ( "\t" + str( lastSwitch ) + ":6 -> 0:5:" + ONOSIpList[ node+1 ] + "\n" )
1954 linkGraph.write( line )
Jon Hall4ba53f02015-07-29 13:07:41 -07001955
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001956 linkGraph.write( "}\n" )
andrew@onlab.us3b087132015-03-11 15:00:08 -07001957 linkGraph.close()
1958
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001959 # SCP
1960 os.system( "scp " + tempFile + " " + self.user_name + "@" + benchIp + ":" + linkGraphPath )
1961 main.log.info( "linkGraph.cfg creation complete" )
andrew@onlab.us3b087132015-03-11 15:00:08 -07001962
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001963 def configNullDev( self, ONOSIpList, deviceCount, numPorts=10 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001964 '''
Jon Hall4ba53f02015-07-29 13:07:41 -07001965 ONOSIpList = list of Ip addresses of nodes switches will be devided amongst
1966 deviceCount = number of switches to distribute, or list of values to use as custom distribution
cameron@onlab.us75900962015-03-30 13:22:49 -07001967 numPorts = number of ports per device. Defaults to 10 both in this function and in ONOS. Optional arg
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001968 '''
1969
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001970 main.log.info( "Configuring Null Device Provider" )
1971 clusterCount = len( ONOSIpList )
andrew@onlab.us3b087132015-03-11 15:00:08 -07001972
Jon Hall4ba53f02015-07-29 13:07:41 -07001973 try:
1974
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001975 if isinstance( deviceCount, int ) or isinstance( deviceCount, str ):
1976 main.log.info( "Creating device distribution" )
1977 deviceCount = int( deviceCount )
1978 switchList = [ 0 ]*( clusterCount+1 )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001979 baselineSwitchCount = deviceCount/clusterCount
andrew@onlab.us3b087132015-03-11 15:00:08 -07001980
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001981 for node in range( 1, clusterCount + 1 ):
1982 switchList[ node ] = baselineSwitchCount
andrew@onlab.us3b087132015-03-11 15:00:08 -07001983
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001984 for node in range( 1, ( deviceCount % clusterCount )+1 ):
1985 switchList[ node ] += 1
Jon Hall4ba53f02015-07-29 13:07:41 -07001986
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001987 if isinstance( deviceCount, list ):
1988 main.log.info( "Using provided device distribution" )
Jon Hall4ba53f02015-07-29 13:07:41 -07001989
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001990 if len( deviceCount ) == clusterCount:
1991 switchList = [ '0' ]
1992 switchList.extend( deviceCount )
Jon Hall4ba53f02015-07-29 13:07:41 -07001993
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001994 if len( deviceCount ) == ( clusterCount + 1 ):
1995 if deviceCount[ 0 ] == '0' or deviceCount[ 0 ] == 0:
cameron@onlab.us75900962015-03-30 13:22:49 -07001996 switchList = deviceCount
andrew@onlab.us3b087132015-03-11 15:00:08 -07001997
Jeremy Ronquillo82705492017-10-18 14:19:55 -07001998 assert len( switchList ) == ( clusterCount + 1 )
Jon Hall4ba53f02015-07-29 13:07:41 -07001999
cameron@onlab.us75900962015-03-30 13:22:49 -07002000 except AssertionError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002001 main.log.error( "Bad device/Ip list match" )
cameron@onlab.us75900962015-03-30 13:22:49 -07002002 except TypeError:
2003 main.log.exception( self.name + ": Object not as expected" )
2004 return None
Jon Hall77ba41c2015-04-06 10:25:40 -07002005 except Exception:
cameron@onlab.us75900962015-03-30 13:22:49 -07002006 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002007 main.cleanAndExit()
cameron@onlab.us75900962015-03-30 13:22:49 -07002008
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002009 ONOSIp = [ 0 ]
2010 ONOSIp.extend( ONOSIpList )
andrew@onlab.us3b087132015-03-11 15:00:08 -07002011
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002012 devicesString = "devConfigs = "
2013 for node in range( 1, len( ONOSIp ) ):
2014 devicesString += ( ONOSIp[ node ] + ":" + str( switchList[ node ] ) )
andrew@onlab.us3b087132015-03-11 15:00:08 -07002015 if node < clusterCount:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002016 devicesString += ( "," )
Jon Hall4ba53f02015-07-29 13:07:41 -07002017
2018 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002019 self.handle.sendline( "onos $OC1 cfg set org.onosproject.provider.nil.device.impl.NullDeviceProvider devConfigs " + devicesString )
2020 self.handle.expect( ":~" )
2021 self.handle.sendline( "onos $OC1 cfg set org.onosproject.provider.nil.device.impl.NullDeviceProvider numPorts " + str( numPorts ) )
2022 self.handle.expect( ":~" )
andrew@onlab.us3b087132015-03-11 15:00:08 -07002023
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002024 for i in range( 10 ):
2025 self.handle.sendline( "onos $OC1 cfg get org.onosproject.provider.nil.device.impl.NullDeviceProvider" )
2026 self.handle.expect( ":~" )
cameron@onlab.us75900962015-03-30 13:22:49 -07002027 verification = self.handle.before
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002028 if ( " value=" + str( numPorts ) ) in verification and ( " value=" + devicesString ) in verification:
cameron@onlab.us75900962015-03-30 13:22:49 -07002029 break
2030 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002031 time.sleep( 1 )
andrew@onlab.us3b087132015-03-11 15:00:08 -07002032
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002033 assert ( "value=" + str( numPorts ) ) in verification and ( " value=" + devicesString ) in verification
Jon Hall4ba53f02015-07-29 13:07:41 -07002034
cameron@onlab.us75900962015-03-30 13:22:49 -07002035 except AssertionError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002036 main.log.error( "Incorrect Config settings: " + verification )
Jon Hall77ba41c2015-04-06 10:25:40 -07002037 except Exception:
cameron@onlab.us75900962015-03-30 13:22:49 -07002038 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002039 main.cleanAndExit()
cameron@onlab.us75900962015-03-30 13:22:49 -07002040
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002041 def configNullLink( self, fileName="/opt/onos/apache-karaf-3.0.3/etc/linkGraph.cfg", eventRate=0 ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002042 '''
Jon Hall4ba53f02015-07-29 13:07:41 -07002043 fileName default is currently the same as the default on ONOS, specify alternate file if
cameron@onlab.us75900962015-03-30 13:22:49 -07002044 you want to use a different topology file than linkGraph.cfg
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002045 '''
Jon Hall4ba53f02015-07-29 13:07:41 -07002046
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002047 try:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002048 self.handle.sendline( "onos $OC1 cfg set org.onosproject.provider.nil.link.impl.NullLinkProvider eventRate " + str( eventRate ) )
2049 self.handle.expect( ":~" )
2050 self.handle.sendline( "onos $OC1 cfg set org.onosproject.provider.nil.link.impl.NullLinkProvider cfgFile " + fileName )
2051 self.handle.expect( ":~" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002052
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002053 for i in range( 10 ):
2054 self.handle.sendline( "onos $OC1 cfg get org.onosproject.provider.nil.link.impl.NullLinkProvider" )
2055 self.handle.expect( ":~" )
cameron@onlab.us75900962015-03-30 13:22:49 -07002056 verification = self.handle.before
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002057 if ( " value=" + str( eventRate ) ) in verification and ( " value=" + fileName ) in verification:
cameron@onlab.us75900962015-03-30 13:22:49 -07002058 break
Jon Hall4ba53f02015-07-29 13:07:41 -07002059 else:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002060 time.sleep( 1 )
Jon Hall4ba53f02015-07-29 13:07:41 -07002061
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002062 assert ( "value=" + str( eventRate ) ) in verification and ( " value=" + fileName ) in verification
Jon Hall4ba53f02015-07-29 13:07:41 -07002063
cameron@onlab.us75900962015-03-30 13:22:49 -07002064 except pexpect.EOF:
2065 main.log.error( self.name + ": EOF exception found" )
2066 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002067 main.cleanAndExit()
cameron@onlab.us75900962015-03-30 13:22:49 -07002068 except AssertionError:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002069 main.log.info( "Settings did not post to ONOS" )
2070 main.log.error( varification )
Jon Hall77ba41c2015-04-06 10:25:40 -07002071 except Exception:
cameron@onlab.us75900962015-03-30 13:22:49 -07002072 main.log.exception( self.name + ": Uncaught exception!" )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002073 main.log.error( varification )
Devin Lim44075962017-08-11 10:56:37 -07002074 main.cleanAndExit()
andrew@onlab.us3b087132015-03-11 15:00:08 -07002075
kelvin-onlaba4074292015-07-09 15:19:49 -07002076 def getOnosIps( self ):
2077 """
2078 Get all onos IPs stored in
2079 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002080
kelvin-onlaba4074292015-07-09 15:19:49 -07002081 return sorted( self.onosIps.values() )
cameron@onlab.us59d29d92015-05-11 14:31:54 -07002082
Chiyu Chengec63bde2016-11-17 18:11:36 -08002083 def listLog( self, nodeIp ):
2084 """
2085 Get a list of all the karaf log names
2086 """
2087 try:
2088 cmd = "onos-ssh " + nodeIp + " ls -tr /opt/onos/log"
2089 self.handle.sendline( cmd )
2090 self.handle.expect( ":~" )
2091 before = self.handle.before.splitlines()
2092 logNames = []
2093 for word in before:
2094 if 'karaf.log' in word:
2095 logNames.append( word )
2096 return logNames
2097 except pexpect.EOF:
2098 main.log.error( self.name + ": EOF exception found" )
2099 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002100 main.cleanAndExit()
Chiyu Chengec63bde2016-11-17 18:11:36 -08002101 except pexpect.TIMEOUT:
2102 main.log.error( self.name + ": TIMEOUT exception found" )
2103 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002104 main.cleanAndExit()
Chiyu Chengec63bde2016-11-17 18:11:36 -08002105 except Exception:
2106 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002107 main.cleanAndExit()
Chiyu Chengec63bde2016-11-17 18:11:36 -08002108
Pratik Parab3b2ab5a2017-02-14 13:15:14 -08002109 def logReport( self, nodeIp, searchTerms, outputMode="s", startStr=None, endStr=None ):
Jon Hallb4242222016-01-25 17:07:04 -08002110 """
2111 Searches the latest ONOS log file for the given search terms and
2112 prints the total occurances of each term. Returns to combined total of
2113 all occurances.
cameron@onlab.us70dd8c62015-05-14 11:19:39 -07002114
Jon Hallb4242222016-01-25 17:07:04 -08002115 Arguments:
2116 * nodeIp - The ip of the ONOS node where the log is located
2117 * searchTerms - A string to grep for or a list of strings to grep
2118 for in the ONOS log. Will print out the number of
2119 occurances for each term.
2120 Optional Arguments:
2121 * outputMode - 's' or 'd'. If 'd' will print the last 5 lines
2122 containing each search term as well as the total
2123 number of occurances of each term. Defaults to 's',
2124 which prints the simple output of just the number
2125 of occurances for each term.
Pratik Parab3b2ab5a2017-02-14 13:15:14 -08002126 * startStr - the start string to be given to stream editor command
2127 as the start point for extraction of data
2128 * endStr - the end string to be given to stream editor command as
2129 the end point for extraction of data
Jon Hallb4242222016-01-25 17:07:04 -08002130 """
2131 try:
2132 main.log.info( " Log Report for {} ".format( nodeIp ).center( 70, '=' ) )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002133 if isinstance( searchTerms, str ):
2134 searchTerms = [ searchTerms ]
Jon Hallb4242222016-01-25 17:07:04 -08002135 numTerms = len( searchTerms )
2136 outputMode = outputMode.lower()
cameron@onlab.us70dd8c62015-05-14 11:19:39 -07002137
Jon Hallb4242222016-01-25 17:07:04 -08002138 totalHits = 0
2139 logLines = []
2140 for termIndex in range( numTerms ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002141 term = searchTerms[ termIndex ]
2142 logLines.append( [ term ] )
Pratik Parab3b2ab5a2017-02-14 13:15:14 -08002143 if startStr and endStr:
2144 cmd = "onos-ssh {} \"sed -n '/{}/,/{}/p' /opt/onos/log/karaf.log | grep {}\"".format( nodeIp,
2145 startStr,
2146 endStr,
2147 term )
2148 else:
2149 cmd = "onos-ssh {} cat /opt/onos/log/karaf.log | grep {}".format( nodeIp,
2150 term )
Jon Hallb4242222016-01-25 17:07:04 -08002151 self.handle.sendline( cmd )
2152 self.handle.expect( ":~" )
2153 before = self.handle.before.splitlines()
2154 count = 0
2155 for line in before:
2156 if term in line and "grep" not in line:
2157 count += 1
2158 if before.index( line ) > ( len( before ) - 7 ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002159 logLines[ termIndex ].append( line )
Jon Hallb4242222016-01-25 17:07:04 -08002160 main.log.info( "{}: {}".format( term, count ) )
2161 totalHits += count
2162 if termIndex == numTerms - 1:
2163 print "\n"
2164 if outputMode != "s":
2165 outputString = ""
2166 for term in logLines:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002167 outputString = term[ 0 ] + ": \n"
Jon Hallb4242222016-01-25 17:07:04 -08002168 for line in range( 1, len( term ) ):
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002169 outputString += ( "\t" + term[ line ] + "\n" )
2170 if outputString != ( term[ 0 ] + ": \n" ):
Jon Hallb4242222016-01-25 17:07:04 -08002171 main.log.info( outputString )
2172 main.log.info( "=" * 70 )
2173 return totalHits
2174 except pexpect.EOF:
2175 main.log.error( self.name + ": EOF exception found" )
2176 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002177 main.cleanAndExit()
Jon Hallb4242222016-01-25 17:07:04 -08002178 except pexpect.TIMEOUT:
2179 main.log.error( self.name + ": TIMEOUT exception found" )
2180 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002181 main.cleanAndExit()
Jon Hallb4242222016-01-25 17:07:04 -08002182 except Exception:
2183 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002184 main.cleanAndExit()
kelvin-onlab7a719bb2015-07-08 11:09:51 -07002185
2186 def copyMininetFile( self, fileName, localPath, userName, ip,
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002187 mnPath='~/mininet/custom/', timeout = 60 ):
kelvin-onlab7a719bb2015-07-08 11:09:51 -07002188 """
2189 Description:
2190 Copy mininet topology file from dependency folder in the test folder
2191 and paste it to the mininet machine's mininet/custom folder
2192 Required:
2193 fileName - Name of the topology file to copy
2194 localPath - File path of the mininet topology file
2195 userName - User name of the mininet machine to send the file to
2196 ip - Ip address of the mininet machine
2197 Optional:
2198 mnPath - of the mininet directory to send the file to
2199 Return:
2200 Return main.TRUE if successfully copied the file otherwise
2201 return main.FALSE
2202 """
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002203
kelvin-onlab7a719bb2015-07-08 11:09:51 -07002204 try:
2205 cmd = "scp " + localPath + fileName + " " + userName + "@" + \
2206 str( ip ) + ":" + mnPath + fileName
2207
2208 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07002209 self.handle.expect( self.prompt )
kelvin-onlab7a719bb2015-07-08 11:09:51 -07002210
2211 main.log.info( self.name + ": Execute: " + cmd )
2212
2213 self.handle.sendline( cmd )
2214
2215 i = self.handle.expect( [ 'No such file',
2216 "100%",
2217 pexpect.TIMEOUT ] )
2218
2219 if i == 0:
2220 main.log.error( self.name + ": File " + fileName +
2221 " does not exist!" )
2222 return main.FALSE
2223
2224 if i == 1:
2225 main.log.info( self.name + ": File " + fileName +
2226 " has been copied!" )
2227 self.handle.sendline( "" )
Devin Limc20e79a2017-06-07 10:29:57 -07002228 self.handle.expect( self.prompt )
kelvin-onlab7a719bb2015-07-08 11:09:51 -07002229 return main.TRUE
2230
2231 except pexpect.EOF:
2232 main.log.error( self.name + ": EOF exception found" )
2233 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002234 main.cleanAndExit()
kelvin-onlab7a719bb2015-07-08 11:09:51 -07002235 except pexpect.TIMEOUT:
2236 main.log.error( self.name + ": TIMEOUT exception found" )
2237 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002238 main.cleanAndExit()
cameron@onlab.us78b89652015-07-08 15:21:03 -07002239
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002240 def jvmSet( self, memory=8 ):
Jon Hall4ba53f02015-07-29 13:07:41 -07002241
cameron@onlab.us78b89652015-07-08 15:21:03 -07002242 import os
2243
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002244 homeDir = os.path.expanduser( '~' )
cameron@onlab.us78b89652015-07-08 15:21:03 -07002245 filename = "/onos/tools/package/bin/onos-service"
2246
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002247 serviceConfig = open( homeDir + filename, 'w+' )
2248 serviceConfig.write( "#!/bin/bash\n " )
2249 serviceConfig.write( "#------------------------------------- \n " )
2250 serviceConfig.write( "# Starts ONOS Apache Karaf container\n " )
2251 serviceConfig.write( "#------------------------------------- \n " )
2252 serviceConfig.write( "#export JAVA_HOME=${JAVA_HOME:-/usr/lib/jvm/java-7-openjdk-amd64/}\n " )
2253 serviceConfig.write( """export JAVA_OPTS="${JAVA_OPTS:--Xms""" + str( memory ) + "G -Xmx" + str( memory ) + """G}" \n """ )
2254 serviceConfig.write( "[ -d $ONOS_HOME ] && cd $ONOS_HOME || ONOS_HOME=$(dirname $0)/..\n" )
2255 serviceConfig.write( """${ONOS_HOME}/apache-karaf-$KARAF_VERSION/bin/karaf "$@" \n """ )
cameron@onlab.us78b89652015-07-08 15:21:03 -07002256 serviceConfig.close()
2257
Jon Hall6c44c0b2016-04-20 15:21:00 -07002258 def createDBFile( self, testData ):
Jon Hall4ba53f02015-07-29 13:07:41 -07002259
cameron@onlab.us78b89652015-07-08 15:21:03 -07002260 filename = main.TEST + "DB"
2261 DBString = ""
Jon Hall4ba53f02015-07-29 13:07:41 -07002262
cameron@onlab.us78b89652015-07-08 15:21:03 -07002263 for item in testData:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002264 if isinstance( item, string ):
cameron@onlab.us78b89652015-07-08 15:21:03 -07002265 item = "'" + item + "'"
Jon Hall6c44c0b2016-04-20 15:21:00 -07002266 if testData.index( item ) < len( testData - 1 ):
cameron@onlab.us78b89652015-07-08 15:21:03 -07002267 item += ","
Jon Hall6c44c0b2016-04-20 15:21:00 -07002268 DBString += str( item )
cameron@onlab.us78b89652015-07-08 15:21:03 -07002269
Jon Hall6c44c0b2016-04-20 15:21:00 -07002270 DBFile = open( filename, "a" )
2271 DBFile.write( DBString )
cameron@onlab.us78b89652015-07-08 15:21:03 -07002272 DBFile.close()
2273
Jon Hall6c44c0b2016-04-20 15:21:00 -07002274 def verifySummary( self, ONOSIp, *deviceCount ):
cameron@onlab.us78b89652015-07-08 15:21:03 -07002275
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002276 self.handle.sendline( "onos " + ONOSIp + " summary" )
Jon Hall6c44c0b2016-04-20 15:21:00 -07002277 self.handle.expect( ":~" )
cameron@onlab.us78b89652015-07-08 15:21:03 -07002278
2279 summaryStr = self.handle.before
2280 print "\nSummary\n==============\n" + summaryStr + "\n\n"
2281
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002282 # passed = "SCC(s)=1" in summaryStr
2283 # if deviceCount:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002284 # passed = "devices=" + str(deviceCount) + "," not in summaryStr
cameron@onlab.us78b89652015-07-08 15:21:03 -07002285
GlennRC772363b2015-08-25 13:05:57 -07002286 passed = False
cameron@onlab.us78b89652015-07-08 15:21:03 -07002287 if "SCC(s)=1," in summaryStr:
2288 passed = True
Jon Hall6c44c0b2016-04-20 15:21:00 -07002289 print "Summary is verifed"
Jon Hall4ba53f02015-07-29 13:07:41 -07002290 else:
Jon Hall6c44c0b2016-04-20 15:21:00 -07002291 print "Summary failed"
cameron@onlab.us78b89652015-07-08 15:21:03 -07002292
2293 if deviceCount:
2294 print" ============================="
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002295 checkStr = "devices=" + str( deviceCount[ 0 ] ) + ","
cameron@onlab.us78b89652015-07-08 15:21:03 -07002296 print "Checkstr: " + checkStr
2297 if checkStr not in summaryStr:
2298 passed = False
Jon Hall6c44c0b2016-04-20 15:21:00 -07002299 print "Device count failed"
Jon Hall4ba53f02015-07-29 13:07:41 -07002300 else:
2301 print "device count verified"
cameron@onlab.us78b89652015-07-08 15:21:03 -07002302
2303 return passed
Jon Hall6c44c0b2016-04-20 15:21:00 -07002304
Jon Hall8f6d4622016-05-23 15:27:18 -07002305 def getIpAddr( self, iface=None ):
Jon Hall6c44c0b2016-04-20 15:21:00 -07002306 """
2307 Update self.ip_address with numerical ip address. If multiple IP's are
2308 located on the device, will attempt to use self.nicAddr to choose the
2309 right one. Defaults to 127.0.0.1 if no other address is found or cannot
2310 determine the correct address.
2311
2312 ONLY WORKS WITH IPV4 ADDRESSES
2313 """
2314 try:
Jon Hall8f6d4622016-05-23 15:27:18 -07002315 LOCALHOST = "127.0.0.1"
Jon Hall6c44c0b2016-04-20 15:21:00 -07002316 ipPat = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
2317 pattern = re.compile( ipPat )
2318 match = re.search( pattern, self.ip_address )
2319 if self.nicAddr:
2320 nicPat = self.nicAddr.replace( ".", "\." ).replace( "\*", r"\d{1,3}" )
2321 nicPat = re.compile( nicPat )
2322 else:
2323 nicPat = None
2324 # IF self.ip_address is an ip address and matches
2325 # self.nicAddr: return self.ip_address
2326 if match:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002327 curIp = match.group( 0 )
Jon Hall6c44c0b2016-04-20 15:21:00 -07002328 if nicPat:
2329 nicMatch = re.search( nicPat, curIp )
2330 if nicMatch:
2331 return self.ip_address
Jon Hall8f6d4622016-05-23 15:27:18 -07002332 # ELSE: IF iface, return ip of interface
2333 cmd = "ifconfig"
2334 ifPat = re.compile( "inet addr:({})".format( ipPat ) )
2335 if iface:
2336 cmd += " " + str( iface )
2337 raw = subprocess.check_output( cmd.split() )
Jon Hall6c44c0b2016-04-20 15:21:00 -07002338 ifPat = re.compile( "inet addr:({})".format( ipPat ) )
2339 ips = re.findall( ifPat, raw )
Jon Hall8f6d4622016-05-23 15:27:18 -07002340 if iface:
2341 if ips:
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002342 ip = ips[ 0 ]
Jon Hall8f6d4622016-05-23 15:27:18 -07002343 self.ip_address = ip
2344 return ip
2345 else:
2346 main.log.error( "Error finding ip, ifconfig output:".format( raw ) )
2347 # ELSE: attempt to get address matching nicPat.
Jon Hall6c44c0b2016-04-20 15:21:00 -07002348 if nicPat:
2349 for ip in ips:
2350 curMatch = re.search( nicPat, ip )
2351 if curMatch:
2352 self.ip_address = ip
2353 return ip
Jon Hall8f6d4622016-05-23 15:27:18 -07002354 else: # If only one non-localhost ip, return that
2355 tmpList = [ ip for ip in ips if ip is not LOCALHOST ]
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002356 if len( tmpList ) == 1:
2357 curIp = tmpList[ 0 ]
Jon Hall6c44c0b2016-04-20 15:21:00 -07002358 self.ip_address = curIp
2359 return curIp
Jon Hall8f6d4622016-05-23 15:27:18 -07002360 # Either no non-localhost IPs, or more than 1
Jon Hallebccd352016-05-20 15:17:17 -07002361 main.log.warn( "getIpAddr failed to find a public IP address" )
Jon Hall8f6d4622016-05-23 15:27:18 -07002362 return LOCALHOST
Jon Halle1790952016-05-23 15:51:46 -07002363 except subprocess.CalledProcessError:
Jon Hall8f6d4622016-05-23 15:27:18 -07002364 main.log.exception( "Error executing ifconfig" )
2365 except IndexError:
2366 main.log.exception( "Error getting IP Address" )
Jon Hall6c44c0b2016-04-20 15:21:00 -07002367 except Exception:
2368 main.log.exception( "Uncaught exception" )
suibin zhang116647a2016-05-06 16:30:09 -07002369
Devin Lim461f0872017-06-05 16:49:33 -07002370 def startBasicONOS( self, nodeList, opSleep=60, onosStartupSleep=30, onosUser="sdn" ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002371 '''
suibin zhang116647a2016-05-06 16:30:09 -07002372 Start onos cluster with defined nodes, but only with drivers app
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002373 '''
suibin zhang116647a2016-05-06 16:30:09 -07002374 import time
2375
2376 self.createCellFile( self.ip_address,
2377 "temp",
2378 self.ip_address,
2379 "drivers",
Devin Lim461f0872017-06-05 16:49:33 -07002380 nodeList, onosUser )
suibin zhang116647a2016-05-06 16:30:09 -07002381
2382 main.log.info( self.name + ": Apply cell to environment" )
2383 cellResult = self.setCell( "temp" )
2384 verifyResult = self.verifyCell()
2385
2386 main.log.info( self.name + ": Creating ONOS package" )
You Wangd1bcaca2016-10-24 15:23:26 -07002387 packageResult = self.buckBuild( timeout=opSleep )
suibin zhang116647a2016-05-06 16:30:09 -07002388
You Wangc669d212017-01-25 11:09:48 -08002389 main.log.info( self.name + ": Uninstalling ONOS" )
2390 for nd in nodeList:
2391 self.onosUninstall( nodeIp=nd )
2392
suibin zhang116647a2016-05-06 16:30:09 -07002393 main.log.info( self.name + ": Installing ONOS package" )
2394 for nd in nodeList:
You Wangc669d212017-01-25 11:09:48 -08002395 self.onosInstall( node=nd )
2396
2397 main.log.info( self.name + ": Set up ONOS secure SSH" )
2398 for nd in nodeList:
2399 self.onosSecureSSH( node=nd )
suibin zhang116647a2016-05-06 16:30:09 -07002400
2401 main.log.info( self.name + ": Starting ONOS service" )
2402 time.sleep( onosStartupSleep )
2403
2404 onosStatus = True
2405 for nd in nodeList:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002406 onosStatus = onosStatus & self.isup( node = nd )
Jeremy Ronquillo82705492017-10-18 14:19:55 -07002407 # print "onosStatus is: " + str( onosStatus )
suibin zhang116647a2016-05-06 16:30:09 -07002408
2409 return main.TRUE if onosStatus else main.FALSE
2410
Devin Lim02075272017-07-10 15:33:21 -07002411 def onosNetCfg( self, controllerIp, path, fileName ):
Jeremy Songster5665f1b2016-06-20 14:38:22 -07002412 """
2413 Push a specified json file to ONOS through the onos-netcfg service
2414
2415 Required:
Devin Lim02075272017-07-10 15:33:21 -07002416 controllerIp - the Ip of the ONOS node in the cluster
Jeremy Songster5665f1b2016-06-20 14:38:22 -07002417 path - the location of the file to be sent
2418 fileName - name of the json file to be sent
2419
2420 Returns main.TRUE on successfully sending json file, and main.FALSE if
2421 there is an error.
2422 """
2423 try:
Devin Lim02075272017-07-10 15:33:21 -07002424 cmd = "onos-netcfg {0} {1}{2}".format( controllerIp, path, fileName )
2425 main.log.info( "Sending: " + cmd )
2426 main.ONOSbench.handle.sendline( cmd )
Jeremy Ronquillo3008aa32017-07-07 15:38:57 -07002427 main.ONOSbench.handle.expect( self.prompt )
Devin Lim02075272017-07-10 15:33:21 -07002428 handle = self.handle.before
Jeremy Ronquillo3008aa32017-07-07 15:38:57 -07002429 if "Error" in handle or "No such file or directory" in handle or "curl: " in handle:
2430 main.log.error( self.name + ": " + handle + self.handle.after )
Devin Lim02075272017-07-10 15:33:21 -07002431 return main.FALSE
Devin Lim752dd7b2017-06-27 14:40:03 -07002432 return main.TRUE
Jeremy Songster5665f1b2016-06-20 14:38:22 -07002433 except pexpect.EOF:
2434 main.log.error( self.name + ": EOF exception found" )
2435 main.log.error( self.name + ": " + self.handle.before )
Devin Lim44075962017-08-11 10:56:37 -07002436 main.cleanAndExit()
Jeremy Songster5665f1b2016-06-20 14:38:22 -07002437 except Exception:
2438 main.log.exception( self.name + ": Uncaught exception!" )
Devin Lim44075962017-08-11 10:56:37 -07002439 main.cleanAndExit()