blob: 9238f8a0da8d53c0291816d4d61e5eb71a439d7f [file] [log] [blame]
Jon Hall05b2b432014-10-08 19:53:25 -04001#!/usr/bin/env python
andrewonlabe8e56fd2014-10-09 17:12:44 -04002
Jon Hall05b2b432014-10-08 19:53:25 -04003'''
andrewonlabe8e56fd2014-10-09 17:12:44 -04004This driver interacts with ONOS bench, the OSGi platform
5that configures the ONOS nodes. (aka ONOS-next)
6
7Please follow the coding style demonstrated by existing
8functions 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
17
Jon Hall05b2b432014-10-08 19:53:25 -040018'''
andrewonlabe8e56fd2014-10-09 17:12:44 -040019
andrewonlab7735d852014-10-09 13:02:47 -040020import sys
Jon Hall05b2b432014-10-08 19:53:25 -040021import time
22import pexpect
23import re
24import traceback
andrewonlab7735d852014-10-09 13:02:47 -040025import os.path
andrewonlab6e20c342014-10-10 18:08:48 -040026import pydoc
Jon Hall05b2b432014-10-08 19:53:25 -040027sys.path.append("../")
28from drivers.common.clidriver import CLI
29
30class OnosDriver(CLI):
31
32 def __init__(self):
andrewonlab6e20c342014-10-10 18:08:48 -040033 '''
34 Initialize client
35 '''
Jon Hall05b2b432014-10-08 19:53:25 -040036 super(CLI, self).__init__()
37
38 def connect(self,**connectargs):
39 '''
40 Creates ssh handle for ONOS "bench".
41 '''
42 try:
43 for key in connectargs:
44 vars(self)[key] = connectargs[key]
45 self.home = "~/ONOS"
46 for key in self.options:
47 if key == "home":
48 self.home = self.options['home']
49 break
50
51
52 self.name = self.options['name']
Jon Hallea7818b2014-10-09 14:30:59 -040053 self.handle = super(OnosDriver,self).connect(
54 user_name = self.user_name,
55 ip_address = self.ip_address,
56 port = self.port,
57 pwd = self.pwd,
58 home = self.home)
Jon Hallea7818b2014-10-09 14:30:59 -040059
60 self.handle.sendline("cd "+ self.home)
61 self.handle.expect("\$")
Jon Hall05b2b432014-10-08 19:53:25 -040062 if self.handle:
63 return self.handle
64 else :
65 main.log.info("NO ONOS HANDLE")
66 return main.FALSE
67 except pexpect.EOF:
68 main.log.error(self.name + ": EOF exception found")
69 main.log.error(self.name + ": " + self.handle.before)
70 main.cleanup()
71 main.exit()
72 except:
73 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
74 main.log.error( traceback.print_exc() )
75 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
76 main.cleanup()
77 main.exit()
78
79 def disconnect(self):
80 '''
81 Called when Test is complete to disconnect the ONOS handle.
82 '''
83 response = ''
84 try:
Jon Hallf8d10982014-10-22 12:23:38 -040085 self.handle.sendline("\n")
86 self.handle.expect("\$")
Jon Hall05b2b432014-10-08 19:53:25 -040087 self.handle.sendline("exit")
88 self.handle.expect("closed")
89 except pexpect.EOF:
90 main.log.error(self.name + ": EOF exception found")
91 main.log.error(self.name + ": " + self.handle.before)
92 except:
93 main.log.error(self.name + ": Connection failed to the host")
94 response = main.FALSE
95 return response
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -040096
97 def onos_package(self):
98 '''
99 Produce a self-contained tar.gz file that can be deployed
100 and executed on any platform with Java 7 JRE.
101 '''
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400102
103 try:
104 self.handle.sendline("onos-package")
Jon Hallea7818b2014-10-09 14:30:59 -0400105 self.handle.expect("onos-package")
andrewonlab0748d2a2014-10-09 13:24:17 -0400106 self.handle.expect("tar.gz",timeout=10)
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400107 handle = str(self.handle.before)
108 main.log.info("onos-package command returned: "+
109 handle)
andrewonlab0748d2a2014-10-09 13:24:17 -0400110 #As long as the sendline does not time out,
111 #return true. However, be careful to interpret
112 #the results of the onos-package command return
113 return main.TRUE
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400114
andrewonlab7735d852014-10-09 13:02:47 -0400115 except pexpect.EOF:
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400116 main.log.error(self.name + ": EOF exception found")
117 main.log.error(self.name + ": " + self.handle.before)
118 except:
119 main.log.error("Failed to package ONOS")
120 main.cleanup()
121 main.exit()
122
Jon Hallde9d9aa2014-10-08 20:36:02 -0400123 def clean_install(self):
124 '''
125 Runs mvn clean install in the root of the ONOS directory.
126 This will clean all ONOS artifacts then compile each module
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400127
Jon Hallde9d9aa2014-10-08 20:36:02 -0400128 Returns: main.TRUE on success
129 On Failure, exits the test
130 '''
131 try:
Jon Hallea7818b2014-10-09 14:30:59 -0400132 main.log.info("Running 'mvn clean install' on " + str(self.name) +
133 ". This may take some time.")
134 self.handle.sendline("cd "+ self.home)
135 self.handle.expect("\$")
136
137 self.handle.sendline("\n")
138 self.handle.expect("\$")
Jon Hallde9d9aa2014-10-08 20:36:02 -0400139 self.handle.sendline("mvn clean install")
Jon Hallea7818b2014-10-09 14:30:59 -0400140 self.handle.expect("mvn clean install")
Jon Hallde9d9aa2014-10-08 20:36:02 -0400141 while 1:
142 i=self.handle.expect([
143 'There\sis\sinsufficient\smemory\sfor\sthe\sJava\s\
144 Runtime\sEnvironment\sto\scontinue',
145 'BUILD\sFAILURE',
146 'BUILD\sSUCCESS',
147 'ONOS\$',
148 pexpect.TIMEOUT],timeout=600)
149 if i == 0:
150 main.log.error(self.name + ":There is insufficient memory \
151 for the Java Runtime Environment to continue.")
152 #return main.FALSE
153 main.cleanup()
154 main.exit()
155 if i == 1:
156 main.log.error(self.name + ": Build failure!")
157 #return main.FALSE
158 main.cleanup()
159 main.exit()
160 elif i == 2:
161 main.log.info(self.name + ": Build success!")
162 elif i == 3:
163 main.log.info(self.name + ": Build complete")
Jon Hallf8ef52c2014-10-09 19:37:33 -0400164 #Print the build time
165 for line in self.handle.before.splitlines():
166 if "Total time:" in line:
167 main.log.info(line)
Jon Hallea7818b2014-10-09 14:30:59 -0400168 self.handle.sendline("\n")
Jon Hallde9d9aa2014-10-08 20:36:02 -0400169 self.handle.expect("\$", timeout=60)
170 return main.TRUE
171 elif i == 4:
172 main.log.error(self.name + ": mvn clean install TIMEOUT!")
173 #return main.FALSE
174 main.cleanup()
175 main.exit()
176 else:
177 main.log.error(self.name + ": unexpected response from \
178 mvn clean install")
179 #return main.FALSE
180 main.cleanup()
181 main.exit()
182 except pexpect.EOF:
183 main.log.error(self.name + ": EOF exception found")
184 main.log.error(self.name + ": " + self.handle.before)
185 main.cleanup()
186 main.exit()
187 except:
188 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
189 main.log.error( traceback.print_exc() )
190 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
191 main.cleanup()
192 main.exit()
Jon Hallacabffd2014-10-09 12:36:53 -0400193
194 def git_pull(self, comp1=""):
195 '''
196 Assumes that "git pull" works without login
197
198 This function will perform a git pull on the ONOS instance.
199 If used as git_pull("NODE") it will do git pull + NODE. This is
200 for the purpose of pulling from other nodes if necessary.
201
202 Otherwise, this function will perform a git pull in the
203 ONOS repository. If it has any problems, it will return main.ERROR
Shreya Shahee15f6c2014-10-28 18:12:30 -0400204 If it successfully does a git_pull, it will return a 1 (main.TRUE)
205 If it has no updates, it will return 3.
Jon Hallacabffd2014-10-09 12:36:53 -0400206
207 '''
208 try:
209 # main.log.info(self.name + ": Stopping ONOS")
210 #self.stop()
211 self.handle.sendline("cd " + self.home)
212 self.handle.expect("ONOS\$")
213 if comp1=="":
214 self.handle.sendline("git pull")
215 else:
216 self.handle.sendline("git pull " + comp1)
217
218 uptodate = 0
219 i=self.handle.expect(['fatal',
220 'Username\sfor\s(.*):\s',
221 '\sfile(s*) changed,\s',
222 'Already up-to-date',
223 'Aborting',
224 'You\sare\snot\scurrently\son\sa\sbranch',
225 'You\sasked\sme\sto\spull\swithout\stelling\sme\swhich\sbranch\syou',
226 'Pull\sis\snot\spossible\sbecause\syou\shave\sunmerged\sfiles',
227 pexpect.TIMEOUT],
228 timeout=300)
229 #debug
Jon Hall81e29af2014-11-04 20:41:23 -0500230 #main.log.report(self.name +": DEBUG: \n"+"git pull response: " + str(self.handle.before) + str(self.handle.after))
Jon Hallacabffd2014-10-09 12:36:53 -0400231 if i==0:
232 main.log.error(self.name + ": Git pull had some issue...")
233 return main.ERROR
234 elif i==1:
235 main.log.error(self.name + ": Git Pull Asking for username. ")
236 return main.ERROR
237 elif i==2:
238 main.log.info(self.name + ": Git Pull - pulling repository now")
239 self.handle.expect("ONOS\$", 120)
Shreya Shahee15f6c2014-10-28 18:12:30 -0400240 return main.TRUE # So that only when git pull is done, we do mvn clean compile
Jon Hallacabffd2014-10-09 12:36:53 -0400241 elif i==3:
242 main.log.info(self.name + ": Git Pull - Already up to date")
Shreya Shahee15f6c2014-10-28 18:12:30 -0400243 return i
Jon Hallacabffd2014-10-09 12:36:53 -0400244 elif i==4:
245 main.log.info(self.name + ": Git Pull - Aborting... Are there conflicting git files?")
246 return main.ERROR
247 elif i==5:
248 main.log.info(self.name + ": Git Pull - You are not currently on a branch so git pull failed!")
249 return main.ERROR
250 elif i==6:
251 main.log.info(self.name + ": Git Pull - You have not configured an upstream branch to pull from. Git pull failed!")
252 return main.ERROR
253 elif i==7:
254 main.log.info(self.name + ": Git Pull - Pull is not possible because you have unmerged files.")
255 return main.ERROR
256 elif i==8:
257 main.log.error(self.name + ": Git Pull - TIMEOUT")
258 main.log.error(self.name + " Response was: " + str(self.handle.before))
259 return main.ERROR
260 else:
261 main.log.error(self.name + ": Git Pull - Unexpected response, check for pull errors")
262 return main.ERROR
263 except pexpect.EOF:
264 main.log.error(self.name + ": EOF exception found")
265 main.log.error(self.name + ": " + self.handle.before)
266 main.cleanup()
267 main.exit()
268 except:
269 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
270 main.log.error( traceback.print_exc() )
271 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
272 main.cleanup()
273 main.exit()
274
275 def git_checkout(self, branch="master"):
276 '''
277 Assumes that "git pull" works without login
278
279 This function will perform a git git checkout on the ONOS instance.
280 If used as git_checkout("branch") it will do git checkout of the "branch".
281
282 Otherwise, this function will perform a git checkout of the master
283 branch of the ONOS repository. If it has any problems, it will return
284 main.ERROR.
285 If the branch was already the specified branch, or the git checkout was
286 successful then the function will return main.TRUE.
287
288 '''
289 try:
Jon Hallacabffd2014-10-09 12:36:53 -0400290 self.handle.sendline("cd " + self.home)
291 self.handle.expect("ONOS\$")
Jon Hall81e29af2014-11-04 20:41:23 -0500292 main.log.info(self.name + ": Checking out git branch: " + branch + "...")
293 cmd = "git checkout "+branch
294 self.handle.sendline(cmd)
295 self.handle.expect(cmd)
296 i=self.handle.expect(['fatal',
297 'Username\sfor\s(.*):\s',
298 'Already\son\s\'',
299 'Switched\sto\sbranch\s\'' + str(branch),
300 pexpect.TIMEOUT,
301 'error: Your local changes to the following files would be overwritten by checkout:',
302 'error: you need to resolve your current index first'],timeout=60)
Jon Hallacabffd2014-10-09 12:36:53 -0400303
304 if i==0:
305 main.log.error(self.name + ": Git checkout had some issue...")
Jon Hall81e29af2014-11-04 20:41:23 -0500306 main.log.error(self.name + ": " + self.handle.before)
Jon Hallacabffd2014-10-09 12:36:53 -0400307 return main.ERROR
308 elif i==1:
Jon Hall81e29af2014-11-04 20:41:23 -0500309 main.log.error(self.name + ": Git checkout asking for username."\
310 +" Please configure your local git repository to be able "\
311 +"to access your remote repository passwordlessly")
Jon Hallacabffd2014-10-09 12:36:53 -0400312 return main.ERROR
313 elif i==2:
314 main.log.info(self.name + ": Git Checkout %s : Already on this branch" %branch)
315 self.handle.expect("ONOS\$")
Jon Hall81e29af2014-11-04 20:41:23 -0500316 #main.log.info("DEBUG: after checkout cmd = "+ self.handle.before)
Jon Hallacabffd2014-10-09 12:36:53 -0400317 return main.TRUE
318 elif i==3:
319 main.log.info(self.name + ": Git checkout %s - Switched to this branch" %branch)
320 self.handle.expect("ONOS\$")
Jon Hall81e29af2014-11-04 20:41:23 -0500321 #main.log.info("DEBUG: after checkout cmd = "+ self.handle.before)
Jon Hallacabffd2014-10-09 12:36:53 -0400322 return main.TRUE
323 elif i==4:
324 main.log.error(self.name + ": Git Checkout- TIMEOUT")
325 main.log.error(self.name + " Response was: " + str(self.handle.before))
326 return main.ERROR
Jon Hall81e29af2014-11-04 20:41:23 -0500327 elif i==5:
328 self.handle.expect("Aborting")
329 main.log.error(self.name + ": Git checkout error: \n" + \
330 "Your local changes to the following files would be overwritten by checkout:" + \
331 str(self.handle.before))
332 self.handle.expect("ONOS\$")
333 return main.ERROR
334 elif i==6:
335 main.log.error(self.name + ": Git checkout error: \n" + \
336 "You need to resolve your current index first:" + \
337 str(self.handle.before))
338 self.handle.expect("ONOS\$")
339 return main.ERROR
Jon Hallacabffd2014-10-09 12:36:53 -0400340 else:
341 main.log.error(self.name + ": Git Checkout - Unexpected response, check for pull errors")
Jon Hall81e29af2014-11-04 20:41:23 -0500342 main.log.error(self.name + ": " + self.handle.before)
Jon Hallacabffd2014-10-09 12:36:53 -0400343 return main.ERROR
344
345 except pexpect.EOF:
346 main.log.error(self.name + ": EOF exception found")
347 main.log.error(self.name + ": " + self.handle.before)
348 main.cleanup()
349 main.exit()
350 except:
351 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
352 main.log.error( traceback.print_exc() )
353 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
354 main.cleanup()
355 main.exit()
andrewonlab95ca1462014-10-09 14:04:24 -0400356
Jon Hall45ec0922014-10-10 19:33:49 -0400357 def get_version(self):
358 '''
359 Writes the COMMIT number to the report to be parsed by Jenkins data collecter.
360 '''
361 try:
362 self.handle.sendline("export TERM=xterm-256color")
363 self.handle.expect("xterm-256color")
364 self.handle.expect("\$")
Jon Hall42db6dc2014-10-24 19:03:48 -0400365 self.handle.sendline("\n")
366 self.handle.expect("\$")
367 self.handle.sendline("cd " + self.home + "; git log -1 --pretty=fuller --decorate=short | grep -A 6 \"commit\" --color=never")
368 self.handle.expect("--color=never")
Jon Hall45ec0922014-10-10 19:33:49 -0400369 self.handle.expect("\$")
370 response=(self.name +": \n"+ str(self.handle.before + self.handle.after))
Jon Hall42db6dc2014-10-24 19:03:48 -0400371 self.handle.sendline("cd " + self.home)
372 self.handle.expect("\$")
Jon Hall45ec0922014-10-10 19:33:49 -0400373 lines=response.splitlines()
374 for line in lines:
375 print line
376 return lines[2]
377 except pexpect.EOF:
378 main.log.error(self.name + ": EOF exception found")
379 main.log.error(self.name + ": " + self.handle.before)
380 main.cleanup()
381 main.exit()
382 except:
383 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
384 main.log.error( traceback.print_exc() )
385 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
386 main.cleanup()
387 main.exit()
388
andrewonlabba44bcf2014-10-16 16:54:41 -0400389 def create_cell_file(self, bench_ip, file_name, mn_ip_addrs,
andrewonlab3f0a4af2014-10-17 12:25:14 -0400390 extra_feature_string, *onos_ip_addrs):
andrewonlab94282092014-10-10 13:00:11 -0400391 '''
392 Creates a cell file based on arguments
393 Required:
394 * Bench IP address (bench_ip)
395 - Needed to copy the cell file over
396 * File name of the cell file (file_name)
397 * Mininet IP address (mn_ip_addrs)
398 - Note that only 1 ip address is
399 supported currently
400 * ONOS IP addresses (onos_ip_addrs)
401 - Must be passed in as last arguments
402
403 NOTE: Assumes cells are located at:
404 ~/<self.home>/tools/test/cells/
405 '''
406
407 #Variable initialization
408 cell_directory = self.home + "/tools/test/cells/"
409 #We want to create the cell file in the dependencies directory
410 #of TestON first, then copy over to ONOS bench
411 temp_directory = "/tmp/"
412 #Create the cell file in the directory for writing (w+)
413 cell_file = open(temp_directory+file_name , 'w+')
andrewonlabd4940492014-10-24 12:21:27 -0400414
415 comment = ""
416 comment_string = "#"+ comment
andrewonlab7e4d2d32014-10-15 13:23:21 -0400417 #Feature string is hardcoded environment variables
418 #That you may wish to use by default on startup.
419 #Note that you may not want certain features listed
420 #on here.
andrewonlabba44bcf2014-10-16 16:54:41 -0400421 core_feature_string = "export ONOS_FEATURES=webconsole,onos-api,"+\
422 "onos-cli,onos-openflow,onos-app-mobility,onos-app-tvue,"+\
423 "onos-app-proxyarp,"+extra_feature_string
andrewonlab94282092014-10-10 13:00:11 -0400424 mn_string = "export OCN="
425 onos_string = "export OC"
426 temp_count = 1
427
428 #Create ONOS_NIC ip address prefix
429 temp_onos_ip = onos_ip_addrs[0]
430 temp_list = []
431 temp_list = temp_onos_ip.split(".")
andrewonlab7e4d2d32014-10-15 13:23:21 -0400432 #Omit last element of list to format for NIC
andrewonlab94282092014-10-10 13:00:11 -0400433 temp_list = temp_list[:-1]
434 #Structure the nic string ip
andrewonlabd4940492014-10-24 12:21:27 -0400435 nic_addr = ".".join(temp_list) + ".*"
andrewonlab94282092014-10-10 13:00:11 -0400436 onos_nic_string = "export ONOS_NIC="+nic_addr
437
438 try:
439 #Start writing to file
andrewonlabd4940492014-10-24 12:21:27 -0400440 cell_file.write(onos_nic_string + "\n")
andrewonlab94282092014-10-10 13:00:11 -0400441
442 for arg in onos_ip_addrs:
443 #For each argument in onos_ip_addrs, write to file
444 #Output should look like the following:
andrewonlabd4940492014-10-24 12:21:27 -0400445 # export OC1="10.128.20.11"
446 # export OC2="10.128.20.12"
andrewonlab94282092014-10-10 13:00:11 -0400447 cell_file.write(onos_string + str(temp_count) +
andrewonlabd4940492014-10-24 12:21:27 -0400448 "=" + "\"" + arg + "\"" + "\n" )
andrewonlab94282092014-10-10 13:00:11 -0400449 temp_count = temp_count + 1
450
andrewonlabd4940492014-10-24 12:21:27 -0400451 cell_file.write(mn_string +"\""+ mn_ip_addrs +"\""+ "\n")
452 cell_file.write(core_feature_string + "\n")
andrewonlab94282092014-10-10 13:00:11 -0400453 cell_file.close()
454
455 #We use os.system to send the command to TestON cluster
456 #to account for the case in which TestON is not located
457 #on the same cluster as the ONOS bench
458 #Note that even if TestON is located on the same cluster
459 #as ONOS bench, you must setup passwordless ssh
andrewonlab7e4d2d32014-10-15 13:23:21 -0400460 #between TestON and ONOS bench in order to automate the test.
andrewonlab94282092014-10-10 13:00:11 -0400461 os.system("scp "+temp_directory+file_name+
462 " admin@"+bench_ip+":"+cell_directory)
463
andrewonlab2a6c9342014-10-16 13:40:15 -0400464 return main.TRUE
465
andrewonlab94282092014-10-10 13:00:11 -0400466 except pexpect.EOF:
467 main.log.error(self.name + ": EOF exception found")
468 main.log.error(self.name + ": " + self.handle.before)
469 main.cleanup()
470 main.exit()
471 except:
472 main.log.info(self.name + ":::::::::")
473 main.log.error( traceback.print_exc() )
474 main.log.info(":::::::")
475 main.cleanup()
476 main.exit()
477
andrewonlab95ca1462014-10-09 14:04:24 -0400478 def set_cell(self, cellname):
479 '''
480 Calls 'cell <name>' to set the environment variables on ONOSbench
481 '''
482 try:
483 if not cellname:
484 main.log.error("Must define cellname")
485 main.cleanup()
486 main.exit()
487 else:
488 self.handle.sendline("cell "+str(cellname))
489 #Expect the cellname in the ONOS_CELL variable.
490 #Note that this variable name is subject to change
491 # and that this driver will have to change accordingly
492 self.handle.expect("ONOS_CELL="+str(cellname))
493 handle_before = self.handle.before
494 handle_after = self.handle.after
andrewonlabc03bf6c2014-10-09 14:56:18 -0400495 #Get the rest of the handle
496 self.handle.sendline("")
497 self.handle.expect("\$")
498 handle_more = self.handle.before
andrewonlab95ca1462014-10-09 14:04:24 -0400499
500 main.log.info("Cell call returned: "+handle_before+
andrewonlabc03bf6c2014-10-09 14:56:18 -0400501 handle_after + handle_more)
andrewonlab95ca1462014-10-09 14:04:24 -0400502
503 return main.TRUE
504
505 except pexpect.EOF:
506 main.log.error(self.name + ": EOF exception found")
507 main.log.error(self.name + ": " + self.handle.before)
508 main.cleanup()
509 main.exit()
510 except:
511 main.log.info(self.name+" ::::::")
512 main.log.error( traceback.print_exc())
513 main.log.info(self.name+" ::::::")
514 main.cleanup()
515 main.exit()
516
andrewonlabc03bf6c2014-10-09 14:56:18 -0400517 def verify_cell(self):
518 '''
519 Calls 'onos-verify-cell' to check for cell installation
520 '''
andrewonlab8d0d7d72014-10-09 16:33:15 -0400521 #TODO: Add meaningful expect value
522
andrewonlabc03bf6c2014-10-09 14:56:18 -0400523 try:
524 #Clean handle by sending empty and expecting $
525 self.handle.sendline("")
526 self.handle.expect("\$")
527 self.handle.sendline("onos-verify-cell")
528 self.handle.expect("\$")
529 handle_before = self.handle.before
530 handle_after = self.handle.after
531 #Get the rest of the handle
532 self.handle.sendline("")
533 self.handle.expect("\$")
534 handle_more = self.handle.before
535
536 main.log.info("Verify cell returned: "+handle_before+
537 handle_after + handle_more)
538
539 return main.TRUE
Jon Hall7993bfc2014-10-09 16:30:14 -0400540 except pexpect.EOF:
541 main.log.error(self.name + ": EOF exception found")
542 main.log.error(self.name + ": " + self.handle.before)
543 main.cleanup()
544 main.exit()
545 except:
546 main.log.info(self.name+" ::::::")
547 main.log.error( traceback.print_exc())
548 main.log.info(self.name+" ::::::")
549 main.cleanup()
550 main.exit()
551
andrewonlab05e362f2014-10-10 00:40:57 -0400552 def onos_cli(self, ONOS_ip, cmdstr):
553 '''
554 Uses 'onos' command to send various ONOS CLI arguments.
555 Required:
556 * ONOS_ip: specify the ip of the cell machine
andrewonlab94282092014-10-10 13:00:11 -0400557 * cmdstr: specify the command string to send
andrewonlab6e20c342014-10-10 18:08:48 -0400558
559 This function is intended to expose the entire karaf
560 CLI commands for ONOS. Try to use this function first
561 before attempting to write a ONOS CLI specific driver
562 function.
563 You can see a list of available 'cmdstr' arguments
564 by starting onos, and typing in 'onos' to enter the
565 onos> CLI. Then, type 'help' to see the list of
566 available commands.
andrewonlab05e362f2014-10-10 00:40:57 -0400567 '''
568 try:
569 if not ONOS_ip:
570 main.log.error("You must specify the IP address")
571 return main.FALSE
572 if not cmdstr:
573 main.log.error("You must specify the command string")
574 return main.FALSE
575
576 cmdstr = str(cmdstr)
577 self.handle.sendline("")
578 self.handle.expect("\$")
579
580 self.handle.sendline("onos -w " + ONOS_ip + " " + cmdstr)
581 self.handle.expect("\$")
582
Shreya Shaha73aaad2014-10-27 18:03:09 -0400583 handle_before = self.handle.before
584 print "handle_before = ", self.handle.before
andrewonlab05e362f2014-10-10 00:40:57 -0400585 handle_after = str(self.handle.after)
586
Shreya Shaha73aaad2014-10-27 18:03:09 -0400587 #self.handle.sendline("")
588 #self.handle.expect("\$")
589 #handle_more = str(self.handle.before)
andrewonlab05e362f2014-10-10 00:40:57 -0400590
591 main.log.info("Command sent successfully")
592
andrewonlab94282092014-10-10 13:00:11 -0400593 #Obtain return handle that consists of result from
594 #the onos command. The string may need to be
595 #configured further.
Shreya Shaha73aaad2014-10-27 18:03:09 -0400596 #return_string = handle_before + handle_after
597 return_string = handle_before
598 print "return_string = ", return_string
andrewonlab05e362f2014-10-10 00:40:57 -0400599 return return_string
600
601 except pexpect.EOF:
602 main.log.error(self.name + ": EOF exception found")
603 main.log.error(self.name + ": " + self.handle.before)
604 main.cleanup()
605 main.exit()
606 except:
607 main.log.info(self.name+" ::::::")
608 main.log.error( traceback.print_exc())
609 main.log.info(self.name+" ::::::")
610 main.cleanup()
611 main.exit()
Jon Hall7993bfc2014-10-09 16:30:14 -0400612
613 def onos_install(self, options="-f", node = ""):
614 '''
615 Installs ONOS bits on the designated cell machine.
616 If -f option is provided, it also forces an uninstall.
617 Presently, install also includes onos-push-bits and
618 onos-config within.
619 The node option allows you to selectively only push the jar
620 files to certain onos nodes
621
622 Returns: main.TRUE on success and main.FALSE on failure
623 '''
624 try:
625 self.handle.sendline("onos-install " + options + " " + node)
626 self.handle.expect("onos-install ")
627 #NOTE: this timeout may need to change depending on the network and size of ONOS
628 i=self.handle.expect(["Network\sis\sunreachable",
629 "onos\sstart/running,\sprocess",
630 pexpect.TIMEOUT],timeout=60)
631
Jon Hall7993bfc2014-10-09 16:30:14 -0400632 if i == 0:
633 main.log.warn("Network is unreachable")
634 return main.FALSE
635 elif i == 1:
Jon Hall42db6dc2014-10-24 19:03:48 -0400636 main.log.info("ONOS was installed on " + node + " and started")
Jon Hall7993bfc2014-10-09 16:30:14 -0400637 return main.TRUE
638 elif i == 2:
Jon Hall42db6dc2014-10-24 19:03:48 -0400639 main.log.info("Installation of ONOS on " + node + " timed out")
Jon Hall7993bfc2014-10-09 16:30:14 -0400640 return main.FALSE
andrewonlabc03bf6c2014-10-09 14:56:18 -0400641
642 except pexpect.EOF:
643 main.log.error(self.name + ": EOF exception found")
644 main.log.error(self.name + ": " + self.handle.before)
645 main.cleanup()
646 main.exit()
647 except:
648 main.log.info(self.name+" ::::::")
649 main.log.error( traceback.print_exc())
650 main.log.info(self.name+" ::::::")
651 main.cleanup()
652 main.exit()
andrewonlab95ca1462014-10-09 14:04:24 -0400653
andrewonlab8d0d7d72014-10-09 16:33:15 -0400654 def onos_start(self, node_ip):
655 '''
656 Calls onos command: 'onos-service [<node-ip>] start'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400657 This command is a remote management of the ONOS upstart daemon
andrewonlab8d0d7d72014-10-09 16:33:15 -0400658 '''
659
660 try:
661 self.handle.sendline("")
662 self.handle.expect("\$")
663 self.handle.sendline("onos-service "+str(node_ip)+
664 " start")
665 i = self.handle.expect([
666 "Job\sis\salready\srunning",
667 "start/running",
668 "Unknown\sinstance",
Shreya Shahd01153d2014-10-23 15:08:56 -0400669 pexpect.TIMEOUT],timeout=120)
andrewonlab8d0d7d72014-10-09 16:33:15 -0400670
671 if i == 0:
672 main.log.info("Service is already running")
673 return main.TRUE
674 elif i == 1:
675 main.log.info("ONOS service started")
676 return main.TRUE
677 else:
678 main.log.error("ONOS service failed to start")
679 main.cleanup()
680 main.exit()
andrewonlab8d0d7d72014-10-09 16:33:15 -0400681 except pexpect.EOF:
682 main.log.error(self.name + ": EOF exception found")
683 main.log.error(self.name + ": " + self.handle.before)
684 main.cleanup()
685 main.exit()
686 except:
687 main.log.info(self.name+" ::::::")
688 main.log.error( traceback.print_exc())
689 main.log.info(self.name+" ::::::")
690 main.cleanup()
691 main.exit()
692
andrewonlab2b30bd32014-10-09 16:48:55 -0400693 def onos_stop(self, node_ip):
694 '''
695 Calls onos command: 'onos-service [<node-ip>] stop'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400696 This command is a remote management of the ONOS upstart daemon
andrewonlab2b30bd32014-10-09 16:48:55 -0400697 '''
698 try:
699 self.handle.sendline("")
700 self.handle.expect("\$")
701 self.handle.sendline("onos-service "+str(node_ip)+
702 " stop")
703 i = self.handle.expect([
704 "stop/waiting",
705 "Unknown\sinstance",
706 pexpect.TIMEOUT],timeout=60)
707
708 if i == 0:
709 main.log.info("ONOS service stopped")
710 return main.TRUE
711 elif i == 1:
712 main.log.info("Unknown ONOS instance specified: "+
713 str(node_ip))
714 return main.FALSE
715 else:
716 main.log.error("ONOS service failed to stop")
717 return main.FALSE
718
719 except pexpect.EOF:
720 main.log.error(self.name + ": EOF exception found")
721 main.log.error(self.name + ": " + self.handle.before)
722 main.cleanup()
723 main.exit()
724 except:
725 main.log.info(self.name+" ::::::")
726 main.log.error( traceback.print_exc())
727 main.log.info(self.name+" ::::::")
728 main.cleanup()
729 main.exit()
730
andrewonlabc8d47972014-10-09 16:52:36 -0400731 def onos_uninstall(self):
732 '''
733 Calls the command: 'onos-uninstall'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400734 Uninstalls ONOS from the designated cell machine, stopping
735 if needed
andrewonlabc8d47972014-10-09 16:52:36 -0400736 '''
737 try:
738 self.handle.sendline("")
739 self.handle.expect("\$")
740 self.handle.sendline("onos-uninstall")
741 self.handle.expect("\$")
742
andrewonlab84727452014-10-09 18:15:36 -0400743 main.log.info("ONOS cell machine was uninstalled")
andrewonlabc8d47972014-10-09 16:52:36 -0400744 #onos-uninstall command does not return any text
745 return main.TRUE
746
747 except pexpect.EOF:
748 main.log.error(self.name + ": EOF exception found")
749 main.log.error(self.name + ": " + self.handle.before)
750 main.cleanup()
751 main.exit()
752 except:
753 main.log.info(self.name+" ::::::")
754 main.log.error( traceback.print_exc())
755 main.log.info(self.name+" ::::::")
756 main.cleanup()
757 main.exit()
andrewonlab2b30bd32014-10-09 16:48:55 -0400758
andrewonlabe8e56fd2014-10-09 17:12:44 -0400759 def onos_kill(self, node_ip):
760 '''
761 Calls the command: 'onos-kill [<node-ip>]'
762 "Remotely, and unceremoniously kills the ONOS instance running on
763 the specified cell machine" - Tom V
764 '''
765
766 try:
767 self.handle.sendline("")
768 self.handle.expect("\$")
769 self.handle.sendline("onos-kill " + str(node_ip))
770 i = self.handle.expect([
771 "\$",
772 "No\sroute\sto\shost",
773 "password:",
774 pexpect.TIMEOUT], timeout=20)
775
776 if i == 0:
777 main.log.info("ONOS instance "+str(node_ip)+" was killed")
778 return main.TRUE
779 elif i == 1:
780 main.log.info("No route to host")
781 return main.FALSE
782 elif i == 2:
783 main.log.info("Passwordless login for host: "+str(node_ip)+
784 " not configured")
785 return main.FALSE
786 else:
787 main.log.info("ONOS instasnce was not killed")
788 return main.FALSE
789
790 except pexpect.EOF:
791 main.log.error(self.name + ": EOF exception found")
792 main.log.error(self.name + ": " + self.handle.before)
793 main.cleanup()
794 main.exit()
795 except:
796 main.log.info(self.name+" ::::::")
797 main.log.error( traceback.print_exc())
798 main.log.info(self.name+" ::::::")
799 main.cleanup()
800 main.exit()
801
andrewonlab94282092014-10-10 13:00:11 -0400802 def onos_start_network(self, mntopo):
803 '''
804 Calls the command 'onos-start-network [<mininet-topo>]
805 "remotely starts the specified topology on the cell's
806 mininet machine against all controllers configured in the
807 cell."
808 * Specify mininet topology file name for mntopo
809 * Topo files should be placed at:
810 ~/<your-onos-directory>/tools/test/topos
811
812 NOTE: This function will take you to the mininet prompt
813 '''
814 try:
815 if not mntopo:
816 main.log.error("You must specify a topo file to execute")
817 return main.FALSE
818
819 mntopo = str(mntopo)
820 self.handle.sendline("")
821 self.handle.expect("\$")
822
823 self.handle.sendline("onos-start-network " + mntopo)
824 self.handle.expect("mininet>")
825 main.log.info("Network started, entered mininet prompt")
826
827 #TODO: Think about whether return is necessary or not
828
829 except pexpect.EOF:
830 main.log.error(self.name + ": EOF exception found")
831 main.log.error(self.name + ": " + self.handle.before)
832 main.cleanup()
833 main.exit()
834 except:
835 main.log.info(self.name+" ::::::")
836 main.log.error( traceback.print_exc())
837 main.log.info(self.name+" ::::::")
838 main.cleanup()
839 main.exit()
840
841
Jon Hall7993bfc2014-10-09 16:30:14 -0400842 def isup(self, node = ""):
843 '''
Jon Hall77f53ce2014-10-13 18:02:06 -0400844 Run's onos-wait-for-start which only returns once ONOS is at run
845 level 100(ready for use)
andrewonlab8d0d7d72014-10-09 16:33:15 -0400846
Jon Hall7993bfc2014-10-09 16:30:14 -0400847 Returns: main.TRUE if ONOS is running and main.FALSE on timeout
848 '''
849 try:
850 self.handle.sendline("onos-wait-for-start " + node )
851 self.handle.expect("onos-wait-for-start")
852 #NOTE: this timeout is arbitrary"
853 i = self.handle.expect(["\$", pexpect.TIMEOUT], timeout = 120)
854 if i == 0:
855 main.log.info(self.name + ": " + node + " is up")
856 return main.TRUE
857 elif i == 1:
858 #NOTE: since this function won't return until ONOS is ready,
859 # we will kill it on timeout
860 self.handle.sendline("\003") #Control-C
861 self.handle.expect("\$")
862 return main.FALSE
863 except pexpect.EOF:
864 main.log.error(self.name + ": EOF exception found")
865 main.log.error(self.name + ": " + self.handle.before)
866 main.cleanup()
867 main.exit()
868 except:
869 main.log.info(self.name+" ::::::")
870 main.log.error( traceback.print_exc())
871 main.log.info(self.name+" ::::::")
872 main.cleanup()
873 main.exit()
andrewonlab05e362f2014-10-10 00:40:57 -0400874
875
Shreya Shaha73aaad2014-10-27 18:03:09 -0400876 def get_topology(self,topology_output):
Jon Hall77f53ce2014-10-13 18:02:06 -0400877 '''
878 parses the onos:topology output
879 Returns: a topology dict populated by the key values found in
880 the cli command.
881 '''
882
883 try:
884 #call the cli to get the topology summary
Shreya Shaha73aaad2014-10-27 18:03:09 -0400885 #cmdstr = "onos:topology"
886 #cli_result = self.onos_cli(ip, cmdstr)
887 #print "cli_result = ", cli_result
Jon Hall77f53ce2014-10-13 18:02:06 -0400888
889 #Parse the output
890 topology = {}
891 #for line in cli_result.split("\n"):
Shreya Shaha73aaad2014-10-27 18:03:09 -0400892 for line in topology_output.splitlines():
Jon Hall77f53ce2014-10-13 18:02:06 -0400893 if not line.startswith("time="):
894 continue
895 #else
896 print line
897 for var in line.split(","):
Shreya Shaha73aaad2014-10-27 18:03:09 -0400898 #print "'"+var+"'"
899 #print "'"+var.strip()+"'"
Jon Hall77f53ce2014-10-13 18:02:06 -0400900 key, value = var.strip().split("=")
901 topology[key] = value
Shreya Shaha73aaad2014-10-27 18:03:09 -0400902 print "topology = ", topology
Jon Hall77f53ce2014-10-13 18:02:06 -0400903 devices = topology.get('devices', False)
Shreya Shaha73aaad2014-10-27 18:03:09 -0400904 print "devices = ", devices
Jon Hall77f53ce2014-10-13 18:02:06 -0400905 links = topology.get('links', False)
Shreya Shaha73aaad2014-10-27 18:03:09 -0400906 print "links = ", links
Jon Hall77f53ce2014-10-13 18:02:06 -0400907 clusters = topology.get('clusters', False)
Shreya Shaha73aaad2014-10-27 18:03:09 -0400908 print "clusters = ", clusters
Jon Hall77f53ce2014-10-13 18:02:06 -0400909 paths = topology.get('paths', False)
Shreya Shaha73aaad2014-10-27 18:03:09 -0400910 print "paths = ", paths
Jon Hall77f53ce2014-10-13 18:02:06 -0400911
912 return topology
913 except pexpect.EOF:
914 main.log.error(self.name + ": EOF exception found")
915 main.log.error(self.name + ": " + self.handle.before)
916 main.cleanup()
917 main.exit()
918 except:
919 main.log.info(self.name+" ::::::")
920 main.log.error( traceback.print_exc())
921 main.log.info(self.name+" ::::::")
922 main.cleanup()
923 main.exit()
Shreya Shaha73aaad2014-10-27 18:03:09 -0400924
925
Jon Hall77f53ce2014-10-13 18:02:06 -0400926
Shreya Shaha73aaad2014-10-27 18:03:09 -0400927 def check_status(self, topology_result, numoswitch, numolink, log_level="info"):
Jon Hall77f53ce2014-10-13 18:02:06 -0400928 '''
929 Checks the number of swithes & links that ONOS sees against the
930 supplied values. By default this will report to main.log, but the
931 log level can be specifid.
932
933 Params: ip = ip used for the onos cli
934 numoswitch = expected number of switches
935 numlink = expected number of links
936 log_level = level to log to. Currently accepts 'info', 'warn' and 'report'
937
938
939 log_level can
940
941 Returns: main.TRUE if the number of switchs and links are correct,
942 main.FALSE if the numer of switches and links is incorrect,
943 and main.ERROR otherwise
944 '''
945
946 try:
Shreya Shaha73aaad2014-10-27 18:03:09 -0400947 topology = self.get_topology(topology_result)
Jon Hall77f53ce2014-10-13 18:02:06 -0400948 if topology == {}:
949 return main.ERROR
950 output = ""
951 #Is the number of switches is what we expected
952 devices = topology.get('devices',False)
953 links = topology.get('links',False)
954 if devices == False or links == False:
955 return main.ERROR
956 switch_check = ( int(devices) == int(numoswitch) )
957 #Is the number of links is what we expected
958 link_check = ( int(links) == int(numolink) )
959 if (switch_check and link_check):
960 #We expected the correct numbers
961 output = output + "The number of links and switches match "\
962 + "what was expected"
963 result = main.TRUE
964 else:
965 output = output + \
966 "The number of links and switches does not match what was expected"
967 result = main.FALSE
968 output = output + "\n ONOS sees %i devices (%i expected) and %i links (%i expected)"\
969 % ( int(devices), int(numoswitch), int(links), int(numolink) )
970 if log_level == "report":
971 main.log.report(output)
972 elif log_level == "warn":
973 main.log.warn(output)
974 else:
975 main.log.info(output)
976 return result
977 except pexpect.EOF:
978 main.log.error(self.name + ": EOF exception found")
979 main.log.error(self.name + ": " + self.handle.before)
980 main.cleanup()
981 main.exit()
982 except:
983 main.log.info(self.name+" ::::::")
984 main.log.error( traceback.print_exc())
985 main.log.info(self.name+" ::::::")
986 main.cleanup()
987 main.exit()
andrewonlabba44bcf2014-10-16 16:54:41 -0400988
Shreya Shaha73aaad2014-10-27 18:03:09 -0400989
andrewonlabba44bcf2014-10-16 16:54:41 -0400990 def tshark_grep(self, grep, directory, interface='eth0'):
991 '''
992 Required:
993 * grep string
994 * directory to store results
995 Optional:
996 * interface - default: eth0
997 Description:
998 Uses tshark command to grep specific group of packets
999 and stores the results to specified directory.
1000 The timestamp is hardcoded to be in epoch
1001 '''
1002 self.handle.sendline("")
1003 self.handle.expect("\$")
andrewonlabefd7f3d2014-10-21 16:02:31 -04001004 self.handle.sendline("")
andrewonlabba44bcf2014-10-16 16:54:41 -04001005 self.handle.sendline("tshark -i "+str(interface)+
andrewonlabd4940492014-10-24 12:21:27 -04001006 " -t e | grep --line-buffered \""+str(grep)+"\" >"+directory+" &")
andrewonlabba44bcf2014-10-16 16:54:41 -04001007 self.handle.sendline("\r")
1008 self.handle.expect("Capturing on")
1009 self.handle.sendline("\r")
1010 self.handle.expect("\$")
1011
1012 def tshark_stop(self):
1013 '''
1014 Removes wireshark files from /tmp and kills all tshark processes
1015 '''
andrewonlab5ba0d9e2014-10-24 13:32:23 -04001016 #Remove all pcap from previous captures
1017 self.execute(cmd="sudo rm /tmp/wireshark*")
andrewonlabba44bcf2014-10-16 16:54:41 -04001018 self.handle.sendline("")
1019 self.handle.sendline("sudo kill -9 `ps -ef | grep \"tshark -i\" |"+
1020 " grep -v grep | awk '{print $2}'`")
1021 self.handle.sendline("")
1022 main.log.info("Tshark stopped")
1023
andrewonlab0c38a4a2014-10-28 18:35:35 -04001024 def ptpd(self, args):
1025 '''
1026 Initiate ptp with user-specified args.
1027 Required:
1028 * args: specify string of args after command
1029 'sudo ptpd'
1030 '''
1031 try:
1032 self.handle.sendline("sudo ptpd "+str(args))
andrewonlab978dff62014-10-29 16:53:35 -04001033 i = self.handle.expect([
andrewonlab0c38a4a2014-10-28 18:35:35 -04001034 "Multiple",
1035 "Error",
1036 "\$"])
1037 self.handle.expect("\$")
andrewonlabba44bcf2014-10-16 16:54:41 -04001038
andrewonlab0c38a4a2014-10-28 18:35:35 -04001039 if i == 0:
1040 handle = self.handle.before
1041 main.log.info("ptpd returned an error: "+
1042 str(handle))
1043 return handle
1044 elif i == 1:
1045 handle = self.handle.before
1046 main.log.error("ptpd returned an error: "+
1047 str(handle))
1048 return handle
1049 else:
1050 return main.TRUE
1051
1052 except pexpect.EOF:
1053 main.log.error(self.name + ": EOF exception found")
1054 main.log.error(self.name + ": " + self.handle.before)
1055 main.cleanup()
1056 main.exit()
1057 except:
1058 main.log.info(self.name+" ::::::")
1059 main.log.error( traceback.print_exc())
1060 main.log.info(self.name+" ::::::")
1061 main.cleanup()
1062 main.exit()
andrewonlabba44bcf2014-10-16 16:54:41 -04001063
1064