blob: 03f49bec69f04509211144795950dedb6910a264 [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
230 #main.log.report(self.name +": \n"+"git pull response: " + str(self.handle.before) + str(self.handle.after))
231 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:
290 # main.log.info(self.name + ": Stopping ONOS")
291 #self.stop()
292 self.handle.sendline("cd " + self.home)
293 self.handle.expect("ONOS\$")
294 if branch != 'master':
295 #self.handle.sendline('git stash')
296 #self.handle.expect('ONOS\$')
297 #print "After issuing git stash cmnd: ", self.handle.before
298 cmd = "git checkout "+branch
299 print "checkout cmd = ", cmd
300 self.handle.sendline(cmd)
301 uptodate = 0
302 i=self.handle.expect(['fatal',
303 'Username\sfor\s(.*):\s',
304 'Already\son\s\'',
305 'Switched\sto\sbranch\s\'',
306 pexpect.TIMEOUT],timeout=60)
307 else:
308 #self.handle.sendline('git stash apply')
309 #self.handle.expect('ONOS\$')
310 #print "After issuing git stash apply cmnd: ", self.handle.before
311 cmd = "git checkout "+branch
312 print "checkout cmd = ", cmd
313 self.handle.sendline(cmd)
314 uptodate = 0
315 switchedToMaster = 0
316 i=self.handle.expect(['fatal',
317 'Username\sfor\s(.*):\s',
318 'Already\son\s\'master\'',
319 'Switched\sto\sbranch\s\'master\'',
320 pexpect.TIMEOUT],timeout=60)
321
322
323 if i==0:
324 main.log.error(self.name + ": Git checkout had some issue...")
325 return main.ERROR
326 elif i==1:
327 main.log.error(self.name + ": Git checkout Asking for username!!! Bad!")
328 return main.ERROR
329 elif i==2:
330 main.log.info(self.name + ": Git Checkout %s : Already on this branch" %branch)
331 self.handle.expect("ONOS\$")
332 print "after checkout cmd = ", self.handle.before
333 switchedToMaster = 1
334 return main.TRUE
335 elif i==3:
336 main.log.info(self.name + ": Git checkout %s - Switched to this branch" %branch)
337 self.handle.expect("ONOS\$")
338 print "after checkout cmd = ", self.handle.before
339 switchedToMaster = 1
340 return main.TRUE
341 elif i==4:
342 main.log.error(self.name + ": Git Checkout- TIMEOUT")
343 main.log.error(self.name + " Response was: " + str(self.handle.before))
344 return main.ERROR
345 else:
346 main.log.error(self.name + ": Git Checkout - Unexpected response, check for pull errors")
347 return main.ERROR
348
349 except pexpect.EOF:
350 main.log.error(self.name + ": EOF exception found")
351 main.log.error(self.name + ": " + self.handle.before)
352 main.cleanup()
353 main.exit()
354 except:
355 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
356 main.log.error( traceback.print_exc() )
357 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
358 main.cleanup()
359 main.exit()
andrewonlab95ca1462014-10-09 14:04:24 -0400360
Jon Hall45ec0922014-10-10 19:33:49 -0400361 def get_version(self):
362 '''
363 Writes the COMMIT number to the report to be parsed by Jenkins data collecter.
364 '''
365 try:
366 self.handle.sendline("export TERM=xterm-256color")
367 self.handle.expect("xterm-256color")
368 self.handle.expect("\$")
Jon Hall42db6dc2014-10-24 19:03:48 -0400369 self.handle.sendline("\n")
370 self.handle.expect("\$")
371 self.handle.sendline("cd " + self.home + "; git log -1 --pretty=fuller --decorate=short | grep -A 6 \"commit\" --color=never")
372 self.handle.expect("--color=never")
Jon Hall45ec0922014-10-10 19:33:49 -0400373 self.handle.expect("\$")
374 response=(self.name +": \n"+ str(self.handle.before + self.handle.after))
Jon Hall42db6dc2014-10-24 19:03:48 -0400375 self.handle.sendline("cd " + self.home)
376 self.handle.expect("\$")
Jon Hall45ec0922014-10-10 19:33:49 -0400377 lines=response.splitlines()
378 for line in lines:
shahshreyaeaea39a2014-11-06 13:37:02 -0800379 print "line = ",line
380 returnValue = lines[2]+lines[4]
381 return returnValue
Jon Hall45ec0922014-10-10 19:33:49 -0400382 except pexpect.EOF:
383 main.log.error(self.name + ": EOF exception found")
384 main.log.error(self.name + ": " + self.handle.before)
385 main.cleanup()
386 main.exit()
387 except:
388 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
389 main.log.error( traceback.print_exc() )
390 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
391 main.cleanup()
392 main.exit()
393
andrewonlabba44bcf2014-10-16 16:54:41 -0400394 def create_cell_file(self, bench_ip, file_name, mn_ip_addrs,
andrewonlab3f0a4af2014-10-17 12:25:14 -0400395 extra_feature_string, *onos_ip_addrs):
andrewonlab94282092014-10-10 13:00:11 -0400396 '''
397 Creates a cell file based on arguments
398 Required:
399 * Bench IP address (bench_ip)
400 - Needed to copy the cell file over
401 * File name of the cell file (file_name)
402 * Mininet IP address (mn_ip_addrs)
403 - Note that only 1 ip address is
404 supported currently
405 * ONOS IP addresses (onos_ip_addrs)
406 - Must be passed in as last arguments
407
408 NOTE: Assumes cells are located at:
409 ~/<self.home>/tools/test/cells/
410 '''
411
412 #Variable initialization
413 cell_directory = self.home + "/tools/test/cells/"
414 #We want to create the cell file in the dependencies directory
415 #of TestON first, then copy over to ONOS bench
416 temp_directory = "/tmp/"
417 #Create the cell file in the directory for writing (w+)
418 cell_file = open(temp_directory+file_name , 'w+')
andrewonlabd4940492014-10-24 12:21:27 -0400419
420 comment = ""
421 comment_string = "#"+ comment
andrewonlab7e4d2d32014-10-15 13:23:21 -0400422 #Feature string is hardcoded environment variables
423 #That you may wish to use by default on startup.
424 #Note that you may not want certain features listed
425 #on here.
andrewonlabba44bcf2014-10-16 16:54:41 -0400426 core_feature_string = "export ONOS_FEATURES=webconsole,onos-api,"+\
427 "onos-cli,onos-openflow,onos-app-mobility,onos-app-tvue,"+\
428 "onos-app-proxyarp,"+extra_feature_string
andrewonlab94282092014-10-10 13:00:11 -0400429 mn_string = "export OCN="
430 onos_string = "export OC"
431 temp_count = 1
432
433 #Create ONOS_NIC ip address prefix
434 temp_onos_ip = onos_ip_addrs[0]
435 temp_list = []
436 temp_list = temp_onos_ip.split(".")
andrewonlab7e4d2d32014-10-15 13:23:21 -0400437 #Omit last element of list to format for NIC
andrewonlab94282092014-10-10 13:00:11 -0400438 temp_list = temp_list[:-1]
439 #Structure the nic string ip
andrewonlabd4940492014-10-24 12:21:27 -0400440 nic_addr = ".".join(temp_list) + ".*"
andrewonlab94282092014-10-10 13:00:11 -0400441 onos_nic_string = "export ONOS_NIC="+nic_addr
442
443 try:
444 #Start writing to file
andrewonlabd4940492014-10-24 12:21:27 -0400445 cell_file.write(onos_nic_string + "\n")
andrewonlab94282092014-10-10 13:00:11 -0400446
447 for arg in onos_ip_addrs:
448 #For each argument in onos_ip_addrs, write to file
449 #Output should look like the following:
andrewonlabd4940492014-10-24 12:21:27 -0400450 # export OC1="10.128.20.11"
451 # export OC2="10.128.20.12"
andrewonlab94282092014-10-10 13:00:11 -0400452 cell_file.write(onos_string + str(temp_count) +
andrewonlabd4940492014-10-24 12:21:27 -0400453 "=" + "\"" + arg + "\"" + "\n" )
andrewonlab94282092014-10-10 13:00:11 -0400454 temp_count = temp_count + 1
455
andrewonlabd4940492014-10-24 12:21:27 -0400456 cell_file.write(mn_string +"\""+ mn_ip_addrs +"\""+ "\n")
457 cell_file.write(core_feature_string + "\n")
andrewonlab94282092014-10-10 13:00:11 -0400458 cell_file.close()
459
460 #We use os.system to send the command to TestON cluster
461 #to account for the case in which TestON is not located
462 #on the same cluster as the ONOS bench
463 #Note that even if TestON is located on the same cluster
464 #as ONOS bench, you must setup passwordless ssh
andrewonlab7e4d2d32014-10-15 13:23:21 -0400465 #between TestON and ONOS bench in order to automate the test.
andrewonlab94282092014-10-10 13:00:11 -0400466 os.system("scp "+temp_directory+file_name+
467 " admin@"+bench_ip+":"+cell_directory)
468
andrewonlab2a6c9342014-10-16 13:40:15 -0400469 return main.TRUE
470
andrewonlab94282092014-10-10 13:00:11 -0400471 except pexpect.EOF:
472 main.log.error(self.name + ": EOF exception found")
473 main.log.error(self.name + ": " + self.handle.before)
474 main.cleanup()
475 main.exit()
476 except:
477 main.log.info(self.name + ":::::::::")
478 main.log.error( traceback.print_exc() )
479 main.log.info(":::::::")
480 main.cleanup()
481 main.exit()
482
andrewonlab95ca1462014-10-09 14:04:24 -0400483 def set_cell(self, cellname):
484 '''
485 Calls 'cell <name>' to set the environment variables on ONOSbench
486 '''
487 try:
488 if not cellname:
489 main.log.error("Must define cellname")
490 main.cleanup()
491 main.exit()
492 else:
493 self.handle.sendline("cell "+str(cellname))
494 #Expect the cellname in the ONOS_CELL variable.
495 #Note that this variable name is subject to change
496 # and that this driver will have to change accordingly
497 self.handle.expect("ONOS_CELL="+str(cellname))
498 handle_before = self.handle.before
499 handle_after = self.handle.after
andrewonlabc03bf6c2014-10-09 14:56:18 -0400500 #Get the rest of the handle
501 self.handle.sendline("")
502 self.handle.expect("\$")
503 handle_more = self.handle.before
andrewonlab95ca1462014-10-09 14:04:24 -0400504
505 main.log.info("Cell call returned: "+handle_before+
andrewonlabc03bf6c2014-10-09 14:56:18 -0400506 handle_after + handle_more)
andrewonlab95ca1462014-10-09 14:04:24 -0400507
508 return main.TRUE
509
510 except pexpect.EOF:
511 main.log.error(self.name + ": EOF exception found")
512 main.log.error(self.name + ": " + self.handle.before)
513 main.cleanup()
514 main.exit()
515 except:
516 main.log.info(self.name+" ::::::")
517 main.log.error( traceback.print_exc())
518 main.log.info(self.name+" ::::::")
519 main.cleanup()
520 main.exit()
521
andrewonlabc03bf6c2014-10-09 14:56:18 -0400522 def verify_cell(self):
523 '''
524 Calls 'onos-verify-cell' to check for cell installation
525 '''
andrewonlab8d0d7d72014-10-09 16:33:15 -0400526 #TODO: Add meaningful expect value
527
andrewonlabc03bf6c2014-10-09 14:56:18 -0400528 try:
529 #Clean handle by sending empty and expecting $
530 self.handle.sendline("")
531 self.handle.expect("\$")
532 self.handle.sendline("onos-verify-cell")
533 self.handle.expect("\$")
534 handle_before = self.handle.before
535 handle_after = self.handle.after
536 #Get the rest of the handle
537 self.handle.sendline("")
538 self.handle.expect("\$")
539 handle_more = self.handle.before
540
541 main.log.info("Verify cell returned: "+handle_before+
542 handle_after + handle_more)
543
544 return main.TRUE
Jon Hall7993bfc2014-10-09 16:30:14 -0400545 except pexpect.EOF:
546 main.log.error(self.name + ": EOF exception found")
547 main.log.error(self.name + ": " + self.handle.before)
548 main.cleanup()
549 main.exit()
550 except:
551 main.log.info(self.name+" ::::::")
552 main.log.error( traceback.print_exc())
553 main.log.info(self.name+" ::::::")
554 main.cleanup()
555 main.exit()
556
andrewonlab05e362f2014-10-10 00:40:57 -0400557 def onos_cli(self, ONOS_ip, cmdstr):
558 '''
559 Uses 'onos' command to send various ONOS CLI arguments.
560 Required:
561 * ONOS_ip: specify the ip of the cell machine
andrewonlab94282092014-10-10 13:00:11 -0400562 * cmdstr: specify the command string to send
andrewonlab6e20c342014-10-10 18:08:48 -0400563
564 This function is intended to expose the entire karaf
565 CLI commands for ONOS. Try to use this function first
566 before attempting to write a ONOS CLI specific driver
567 function.
568 You can see a list of available 'cmdstr' arguments
569 by starting onos, and typing in 'onos' to enter the
570 onos> CLI. Then, type 'help' to see the list of
571 available commands.
andrewonlab05e362f2014-10-10 00:40:57 -0400572 '''
573 try:
574 if not ONOS_ip:
575 main.log.error("You must specify the IP address")
576 return main.FALSE
577 if not cmdstr:
578 main.log.error("You must specify the command string")
579 return main.FALSE
580
581 cmdstr = str(cmdstr)
582 self.handle.sendline("")
583 self.handle.expect("\$")
584
585 self.handle.sendline("onos -w " + ONOS_ip + " " + cmdstr)
586 self.handle.expect("\$")
587
Shreya Shaha73aaad2014-10-27 18:03:09 -0400588 handle_before = self.handle.before
589 print "handle_before = ", self.handle.before
andrewonlab05e362f2014-10-10 00:40:57 -0400590 handle_after = str(self.handle.after)
591
Shreya Shaha73aaad2014-10-27 18:03:09 -0400592 #self.handle.sendline("")
593 #self.handle.expect("\$")
594 #handle_more = str(self.handle.before)
andrewonlab05e362f2014-10-10 00:40:57 -0400595
596 main.log.info("Command sent successfully")
597
andrewonlab94282092014-10-10 13:00:11 -0400598 #Obtain return handle that consists of result from
599 #the onos command. The string may need to be
600 #configured further.
Shreya Shaha73aaad2014-10-27 18:03:09 -0400601 #return_string = handle_before + handle_after
602 return_string = handle_before
603 print "return_string = ", return_string
andrewonlab05e362f2014-10-10 00:40:57 -0400604 return return_string
605
606 except pexpect.EOF:
607 main.log.error(self.name + ": EOF exception found")
608 main.log.error(self.name + ": " + self.handle.before)
609 main.cleanup()
610 main.exit()
611 except:
612 main.log.info(self.name+" ::::::")
613 main.log.error( traceback.print_exc())
614 main.log.info(self.name+" ::::::")
615 main.cleanup()
616 main.exit()
Jon Hall7993bfc2014-10-09 16:30:14 -0400617
618 def onos_install(self, options="-f", node = ""):
619 '''
620 Installs ONOS bits on the designated cell machine.
621 If -f option is provided, it also forces an uninstall.
622 Presently, install also includes onos-push-bits and
623 onos-config within.
624 The node option allows you to selectively only push the jar
625 files to certain onos nodes
626
627 Returns: main.TRUE on success and main.FALSE on failure
628 '''
629 try:
630 self.handle.sendline("onos-install " + options + " " + node)
631 self.handle.expect("onos-install ")
632 #NOTE: this timeout may need to change depending on the network and size of ONOS
633 i=self.handle.expect(["Network\sis\sunreachable",
634 "onos\sstart/running,\sprocess",
635 pexpect.TIMEOUT],timeout=60)
636
Jon Hall7993bfc2014-10-09 16:30:14 -0400637 if i == 0:
638 main.log.warn("Network is unreachable")
639 return main.FALSE
640 elif i == 1:
Jon Hall42db6dc2014-10-24 19:03:48 -0400641 main.log.info("ONOS was installed on " + node + " and started")
Jon Hall7993bfc2014-10-09 16:30:14 -0400642 return main.TRUE
643 elif i == 2:
Jon Hall42db6dc2014-10-24 19:03:48 -0400644 main.log.info("Installation of ONOS on " + node + " timed out")
Jon Hall7993bfc2014-10-09 16:30:14 -0400645 return main.FALSE
andrewonlabc03bf6c2014-10-09 14:56:18 -0400646
647 except pexpect.EOF:
648 main.log.error(self.name + ": EOF exception found")
649 main.log.error(self.name + ": " + self.handle.before)
650 main.cleanup()
651 main.exit()
652 except:
653 main.log.info(self.name+" ::::::")
654 main.log.error( traceback.print_exc())
655 main.log.info(self.name+" ::::::")
656 main.cleanup()
657 main.exit()
andrewonlab95ca1462014-10-09 14:04:24 -0400658
andrewonlab8d0d7d72014-10-09 16:33:15 -0400659 def onos_start(self, node_ip):
660 '''
661 Calls onos command: 'onos-service [<node-ip>] start'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400662 This command is a remote management of the ONOS upstart daemon
andrewonlab8d0d7d72014-10-09 16:33:15 -0400663 '''
664
665 try:
666 self.handle.sendline("")
667 self.handle.expect("\$")
668 self.handle.sendline("onos-service "+str(node_ip)+
669 " start")
670 i = self.handle.expect([
671 "Job\sis\salready\srunning",
672 "start/running",
673 "Unknown\sinstance",
Shreya Shahd01153d2014-10-23 15:08:56 -0400674 pexpect.TIMEOUT],timeout=120)
andrewonlab8d0d7d72014-10-09 16:33:15 -0400675
676 if i == 0:
677 main.log.info("Service is already running")
678 return main.TRUE
679 elif i == 1:
680 main.log.info("ONOS service started")
681 return main.TRUE
682 else:
683 main.log.error("ONOS service failed to start")
684 main.cleanup()
685 main.exit()
andrewonlab8d0d7d72014-10-09 16:33:15 -0400686 except pexpect.EOF:
687 main.log.error(self.name + ": EOF exception found")
688 main.log.error(self.name + ": " + self.handle.before)
689 main.cleanup()
690 main.exit()
691 except:
692 main.log.info(self.name+" ::::::")
693 main.log.error( traceback.print_exc())
694 main.log.info(self.name+" ::::::")
695 main.cleanup()
696 main.exit()
697
andrewonlab2b30bd32014-10-09 16:48:55 -0400698 def onos_stop(self, node_ip):
699 '''
700 Calls onos command: 'onos-service [<node-ip>] stop'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400701 This command is a remote management of the ONOS upstart daemon
andrewonlab2b30bd32014-10-09 16:48:55 -0400702 '''
703 try:
704 self.handle.sendline("")
705 self.handle.expect("\$")
706 self.handle.sendline("onos-service "+str(node_ip)+
707 " stop")
708 i = self.handle.expect([
709 "stop/waiting",
710 "Unknown\sinstance",
711 pexpect.TIMEOUT],timeout=60)
712
713 if i == 0:
714 main.log.info("ONOS service stopped")
715 return main.TRUE
716 elif i == 1:
717 main.log.info("Unknown ONOS instance specified: "+
718 str(node_ip))
719 return main.FALSE
720 else:
721 main.log.error("ONOS service failed to stop")
722 return main.FALSE
723
724 except pexpect.EOF:
725 main.log.error(self.name + ": EOF exception found")
726 main.log.error(self.name + ": " + self.handle.before)
727 main.cleanup()
728 main.exit()
729 except:
730 main.log.info(self.name+" ::::::")
731 main.log.error( traceback.print_exc())
732 main.log.info(self.name+" ::::::")
733 main.cleanup()
734 main.exit()
735
andrewonlabc8d47972014-10-09 16:52:36 -0400736 def onos_uninstall(self):
737 '''
738 Calls the command: 'onos-uninstall'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400739 Uninstalls ONOS from the designated cell machine, stopping
740 if needed
andrewonlabc8d47972014-10-09 16:52:36 -0400741 '''
742 try:
743 self.handle.sendline("")
744 self.handle.expect("\$")
745 self.handle.sendline("onos-uninstall")
746 self.handle.expect("\$")
747
andrewonlab84727452014-10-09 18:15:36 -0400748 main.log.info("ONOS cell machine was uninstalled")
andrewonlabc8d47972014-10-09 16:52:36 -0400749 #onos-uninstall command does not return any text
750 return main.TRUE
751
752 except pexpect.EOF:
753 main.log.error(self.name + ": EOF exception found")
754 main.log.error(self.name + ": " + self.handle.before)
755 main.cleanup()
756 main.exit()
757 except:
758 main.log.info(self.name+" ::::::")
759 main.log.error( traceback.print_exc())
760 main.log.info(self.name+" ::::::")
761 main.cleanup()
762 main.exit()
andrewonlab2b30bd32014-10-09 16:48:55 -0400763
andrewonlabe8e56fd2014-10-09 17:12:44 -0400764 def onos_kill(self, node_ip):
765 '''
766 Calls the command: 'onos-kill [<node-ip>]'
767 "Remotely, and unceremoniously kills the ONOS instance running on
768 the specified cell machine" - Tom V
769 '''
770
771 try:
772 self.handle.sendline("")
773 self.handle.expect("\$")
774 self.handle.sendline("onos-kill " + str(node_ip))
775 i = self.handle.expect([
776 "\$",
777 "No\sroute\sto\shost",
778 "password:",
779 pexpect.TIMEOUT], timeout=20)
780
781 if i == 0:
782 main.log.info("ONOS instance "+str(node_ip)+" was killed")
783 return main.TRUE
784 elif i == 1:
785 main.log.info("No route to host")
786 return main.FALSE
787 elif i == 2:
788 main.log.info("Passwordless login for host: "+str(node_ip)+
789 " not configured")
790 return main.FALSE
791 else:
792 main.log.info("ONOS instasnce was not killed")
793 return main.FALSE
794
795 except pexpect.EOF:
796 main.log.error(self.name + ": EOF exception found")
797 main.log.error(self.name + ": " + self.handle.before)
798 main.cleanup()
799 main.exit()
800 except:
801 main.log.info(self.name+" ::::::")
802 main.log.error( traceback.print_exc())
803 main.log.info(self.name+" ::::::")
804 main.cleanup()
805 main.exit()
806
andrewonlab94282092014-10-10 13:00:11 -0400807 def onos_start_network(self, mntopo):
808 '''
809 Calls the command 'onos-start-network [<mininet-topo>]
810 "remotely starts the specified topology on the cell's
811 mininet machine against all controllers configured in the
812 cell."
813 * Specify mininet topology file name for mntopo
814 * Topo files should be placed at:
815 ~/<your-onos-directory>/tools/test/topos
816
817 NOTE: This function will take you to the mininet prompt
818 '''
819 try:
820 if not mntopo:
821 main.log.error("You must specify a topo file to execute")
822 return main.FALSE
823
824 mntopo = str(mntopo)
825 self.handle.sendline("")
826 self.handle.expect("\$")
827
828 self.handle.sendline("onos-start-network " + mntopo)
829 self.handle.expect("mininet>")
830 main.log.info("Network started, entered mininet prompt")
831
832 #TODO: Think about whether return is necessary or not
833
834 except pexpect.EOF:
835 main.log.error(self.name + ": EOF exception found")
836 main.log.error(self.name + ": " + self.handle.before)
837 main.cleanup()
838 main.exit()
839 except:
840 main.log.info(self.name+" ::::::")
841 main.log.error( traceback.print_exc())
842 main.log.info(self.name+" ::::::")
843 main.cleanup()
844 main.exit()
845
846
Jon Hall7993bfc2014-10-09 16:30:14 -0400847 def isup(self, node = ""):
848 '''
Jon Hall77f53ce2014-10-13 18:02:06 -0400849 Run's onos-wait-for-start which only returns once ONOS is at run
850 level 100(ready for use)
andrewonlab8d0d7d72014-10-09 16:33:15 -0400851
Jon Hall7993bfc2014-10-09 16:30:14 -0400852 Returns: main.TRUE if ONOS is running and main.FALSE on timeout
853 '''
854 try:
855 self.handle.sendline("onos-wait-for-start " + node )
856 self.handle.expect("onos-wait-for-start")
857 #NOTE: this timeout is arbitrary"
858 i = self.handle.expect(["\$", pexpect.TIMEOUT], timeout = 120)
859 if i == 0:
860 main.log.info(self.name + ": " + node + " is up")
861 return main.TRUE
862 elif i == 1:
863 #NOTE: since this function won't return until ONOS is ready,
864 # we will kill it on timeout
865 self.handle.sendline("\003") #Control-C
866 self.handle.expect("\$")
867 return main.FALSE
868 except pexpect.EOF:
869 main.log.error(self.name + ": EOF exception found")
870 main.log.error(self.name + ": " + self.handle.before)
871 main.cleanup()
872 main.exit()
873 except:
874 main.log.info(self.name+" ::::::")
875 main.log.error( traceback.print_exc())
876 main.log.info(self.name+" ::::::")
877 main.cleanup()
878 main.exit()
andrewonlab05e362f2014-10-10 00:40:57 -0400879
880
Shreya Shaha73aaad2014-10-27 18:03:09 -0400881 def get_topology(self,topology_output):
Jon Hall77f53ce2014-10-13 18:02:06 -0400882 '''
883 parses the onos:topology output
884 Returns: a topology dict populated by the key values found in
885 the cli command.
886 '''
887
888 try:
889 #call the cli to get the topology summary
Shreya Shaha73aaad2014-10-27 18:03:09 -0400890 #cmdstr = "onos:topology"
891 #cli_result = self.onos_cli(ip, cmdstr)
892 #print "cli_result = ", cli_result
Jon Hall77f53ce2014-10-13 18:02:06 -0400893
894 #Parse the output
895 topology = {}
896 #for line in cli_result.split("\n"):
Shreya Shaha73aaad2014-10-27 18:03:09 -0400897 for line in topology_output.splitlines():
Jon Hall77f53ce2014-10-13 18:02:06 -0400898 if not line.startswith("time="):
899 continue
900 #else
901 print line
902 for var in line.split(","):
Shreya Shaha73aaad2014-10-27 18:03:09 -0400903 #print "'"+var+"'"
904 #print "'"+var.strip()+"'"
Jon Hall77f53ce2014-10-13 18:02:06 -0400905 key, value = var.strip().split("=")
906 topology[key] = value
Shreya Shaha73aaad2014-10-27 18:03:09 -0400907 print "topology = ", topology
Jon Hall77f53ce2014-10-13 18:02:06 -0400908 devices = topology.get('devices', False)
Shreya Shaha73aaad2014-10-27 18:03:09 -0400909 print "devices = ", devices
Jon Hall77f53ce2014-10-13 18:02:06 -0400910 links = topology.get('links', False)
Shreya Shaha73aaad2014-10-27 18:03:09 -0400911 print "links = ", links
Jon Hall77f53ce2014-10-13 18:02:06 -0400912 clusters = topology.get('clusters', False)
Shreya Shaha73aaad2014-10-27 18:03:09 -0400913 print "clusters = ", clusters
Jon Hall77f53ce2014-10-13 18:02:06 -0400914 paths = topology.get('paths', False)
Shreya Shaha73aaad2014-10-27 18:03:09 -0400915 print "paths = ", paths
Jon Hall77f53ce2014-10-13 18:02:06 -0400916
917 return topology
918 except pexpect.EOF:
919 main.log.error(self.name + ": EOF exception found")
920 main.log.error(self.name + ": " + self.handle.before)
921 main.cleanup()
922 main.exit()
923 except:
924 main.log.info(self.name+" ::::::")
925 main.log.error( traceback.print_exc())
926 main.log.info(self.name+" ::::::")
927 main.cleanup()
928 main.exit()
Shreya Shaha73aaad2014-10-27 18:03:09 -0400929
930
Jon Hall77f53ce2014-10-13 18:02:06 -0400931
Shreya Shaha73aaad2014-10-27 18:03:09 -0400932 def check_status(self, topology_result, numoswitch, numolink, log_level="info"):
Jon Hall77f53ce2014-10-13 18:02:06 -0400933 '''
934 Checks the number of swithes & links that ONOS sees against the
935 supplied values. By default this will report to main.log, but the
936 log level can be specifid.
937
938 Params: ip = ip used for the onos cli
939 numoswitch = expected number of switches
940 numlink = expected number of links
941 log_level = level to log to. Currently accepts 'info', 'warn' and 'report'
942
943
944 log_level can
945
946 Returns: main.TRUE if the number of switchs and links are correct,
947 main.FALSE if the numer of switches and links is incorrect,
948 and main.ERROR otherwise
949 '''
950
951 try:
Shreya Shaha73aaad2014-10-27 18:03:09 -0400952 topology = self.get_topology(topology_result)
Jon Hall77f53ce2014-10-13 18:02:06 -0400953 if topology == {}:
954 return main.ERROR
955 output = ""
956 #Is the number of switches is what we expected
957 devices = topology.get('devices',False)
958 links = topology.get('links',False)
959 if devices == False or links == False:
960 return main.ERROR
961 switch_check = ( int(devices) == int(numoswitch) )
962 #Is the number of links is what we expected
963 link_check = ( int(links) == int(numolink) )
964 if (switch_check and link_check):
965 #We expected the correct numbers
966 output = output + "The number of links and switches match "\
967 + "what was expected"
968 result = main.TRUE
969 else:
970 output = output + \
971 "The number of links and switches does not match what was expected"
972 result = main.FALSE
973 output = output + "\n ONOS sees %i devices (%i expected) and %i links (%i expected)"\
974 % ( int(devices), int(numoswitch), int(links), int(numolink) )
975 if log_level == "report":
976 main.log.report(output)
977 elif log_level == "warn":
978 main.log.warn(output)
979 else:
980 main.log.info(output)
981 return result
982 except pexpect.EOF:
983 main.log.error(self.name + ": EOF exception found")
984 main.log.error(self.name + ": " + self.handle.before)
985 main.cleanup()
986 main.exit()
987 except:
988 main.log.info(self.name+" ::::::")
989 main.log.error( traceback.print_exc())
990 main.log.info(self.name+" ::::::")
991 main.cleanup()
992 main.exit()
andrewonlabba44bcf2014-10-16 16:54:41 -0400993
Shreya Shaha73aaad2014-10-27 18:03:09 -0400994
andrewonlabba44bcf2014-10-16 16:54:41 -0400995 def tshark_grep(self, grep, directory, interface='eth0'):
996 '''
997 Required:
998 * grep string
999 * directory to store results
1000 Optional:
1001 * interface - default: eth0
1002 Description:
1003 Uses tshark command to grep specific group of packets
1004 and stores the results to specified directory.
1005 The timestamp is hardcoded to be in epoch
1006 '''
1007 self.handle.sendline("")
1008 self.handle.expect("\$")
andrewonlabefd7f3d2014-10-21 16:02:31 -04001009 self.handle.sendline("")
andrewonlabba44bcf2014-10-16 16:54:41 -04001010 self.handle.sendline("tshark -i "+str(interface)+
andrewonlabd4940492014-10-24 12:21:27 -04001011 " -t e | grep --line-buffered \""+str(grep)+"\" >"+directory+" &")
andrewonlabba44bcf2014-10-16 16:54:41 -04001012 self.handle.sendline("\r")
1013 self.handle.expect("Capturing on")
1014 self.handle.sendline("\r")
1015 self.handle.expect("\$")
1016
1017 def tshark_stop(self):
1018 '''
1019 Removes wireshark files from /tmp and kills all tshark processes
1020 '''
andrewonlab5ba0d9e2014-10-24 13:32:23 -04001021 #Remove all pcap from previous captures
1022 self.execute(cmd="sudo rm /tmp/wireshark*")
andrewonlabba44bcf2014-10-16 16:54:41 -04001023 self.handle.sendline("")
1024 self.handle.sendline("sudo kill -9 `ps -ef | grep \"tshark -i\" |"+
1025 " grep -v grep | awk '{print $2}'`")
1026 self.handle.sendline("")
1027 main.log.info("Tshark stopped")
1028
andrewonlab0c38a4a2014-10-28 18:35:35 -04001029 def ptpd(self, args):
1030 '''
1031 Initiate ptp with user-specified args.
1032 Required:
1033 * args: specify string of args after command
1034 'sudo ptpd'
1035 '''
1036 try:
1037 self.handle.sendline("sudo ptpd "+str(args))
andrewonlab978dff62014-10-29 16:53:35 -04001038 i = self.handle.expect([
andrewonlab0c38a4a2014-10-28 18:35:35 -04001039 "Multiple",
1040 "Error",
1041 "\$"])
1042 self.handle.expect("\$")
andrewonlabba44bcf2014-10-16 16:54:41 -04001043
andrewonlab0c38a4a2014-10-28 18:35:35 -04001044 if i == 0:
1045 handle = self.handle.before
1046 main.log.info("ptpd returned an error: "+
1047 str(handle))
1048 return handle
1049 elif i == 1:
1050 handle = self.handle.before
1051 main.log.error("ptpd returned an error: "+
1052 str(handle))
1053 return handle
1054 else:
1055 return main.TRUE
1056
1057 except pexpect.EOF:
1058 main.log.error(self.name + ": EOF exception found")
1059 main.log.error(self.name + ": " + self.handle.before)
1060 main.cleanup()
1061 main.exit()
1062 except:
1063 main.log.info(self.name+" ::::::")
1064 main.log.error( traceback.print_exc())
1065 main.log.info(self.name+" ::::::")
1066 main.cleanup()
1067 main.exit()
andrewonlabba44bcf2014-10-16 16:54:41 -04001068
1069