blob: 2e7ffa3526c0c50ce88bdfd4b1b127e0b6edd928 [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
204 If it successfully does a git_pull, it will return a 1.
205 If it has no updates, it will return a 0.
206
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)
Jon Hall77f53ce2014-10-13 18:02:06 -0400240 return main.TRUE
Jon Hallacabffd2014-10-09 12:36:53 -0400241 elif i==3:
242 main.log.info(self.name + ": Git Pull - Already up to date")
Jon Hall77f53ce2014-10-13 18:02:06 -0400243 return main.TRUE
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("\$")
369 self.handle.sendline("cd " + self.home + "; git log -1 --pretty=fuller --decorate=short | grep -A 5 \"commit\" --color=never; cd \.\.")
370 self.handle.expect("cd ..")
371 self.handle.expect("\$")
372 response=(self.name +": \n"+ str(self.handle.before + self.handle.after))
373 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+')
414
andrewonlab7e4d2d32014-10-15 13:23:21 -0400415 #Feature string is hardcoded environment variables
416 #That you may wish to use by default on startup.
417 #Note that you may not want certain features listed
418 #on here.
andrewonlabba44bcf2014-10-16 16:54:41 -0400419 core_feature_string = "export ONOS_FEATURES=webconsole,onos-api,"+\
420 "onos-cli,onos-openflow,onos-app-mobility,onos-app-tvue,"+\
421 "onos-app-proxyarp,"+extra_feature_string
andrewonlab94282092014-10-10 13:00:11 -0400422 mn_string = "export OCN="
423 onos_string = "export OC"
424 temp_count = 1
425
426 #Create ONOS_NIC ip address prefix
427 temp_onos_ip = onos_ip_addrs[0]
428 temp_list = []
429 temp_list = temp_onos_ip.split(".")
andrewonlab7e4d2d32014-10-15 13:23:21 -0400430 #Omit last element of list to format for NIC
andrewonlab94282092014-10-10 13:00:11 -0400431 temp_list = temp_list[:-1]
432 #Structure the nic string ip
433 nic_addr = ".".join(temp_list) + ".*\n"
434 onos_nic_string = "export ONOS_NIC="+nic_addr
435
436 try:
437 #Start writing to file
andrewonlabdca78032014-10-16 17:03:04 -0400438 cell_file.write(core_feature_string + "\n")
andrewonlab94282092014-10-10 13:00:11 -0400439 cell_file.write(onos_nic_string)
440 cell_file.write(mn_string +"'"+ mn_ip_addrs +"'"+ "\n")
441
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:
445 # export OC1='10.128.20.11'
446 # export OC2='10.128.20.12'
447 cell_file.write(onos_string + str(temp_count) +
448 "=" + "'" + arg + "'" + "\n" )
449 temp_count = temp_count + 1
450
451 cell_file.close()
452
453 #We use os.system to send the command to TestON cluster
454 #to account for the case in which TestON is not located
455 #on the same cluster as the ONOS bench
456 #Note that even if TestON is located on the same cluster
457 #as ONOS bench, you must setup passwordless ssh
andrewonlab7e4d2d32014-10-15 13:23:21 -0400458 #between TestON and ONOS bench in order to automate the test.
andrewonlab94282092014-10-10 13:00:11 -0400459 os.system("scp "+temp_directory+file_name+
460 " admin@"+bench_ip+":"+cell_directory)
461
andrewonlab2a6c9342014-10-16 13:40:15 -0400462 return main.TRUE
463
andrewonlab94282092014-10-10 13:00:11 -0400464 except pexpect.EOF:
465 main.log.error(self.name + ": EOF exception found")
466 main.log.error(self.name + ": " + self.handle.before)
467 main.cleanup()
468 main.exit()
469 except:
470 main.log.info(self.name + ":::::::::")
471 main.log.error( traceback.print_exc() )
472 main.log.info(":::::::")
473 main.cleanup()
474 main.exit()
475
andrewonlab95ca1462014-10-09 14:04:24 -0400476 def set_cell(self, cellname):
477 '''
478 Calls 'cell <name>' to set the environment variables on ONOSbench
479 '''
480 try:
481 if not cellname:
482 main.log.error("Must define cellname")
483 main.cleanup()
484 main.exit()
485 else:
486 self.handle.sendline("cell "+str(cellname))
487 #Expect the cellname in the ONOS_CELL variable.
488 #Note that this variable name is subject to change
489 # and that this driver will have to change accordingly
490 self.handle.expect("ONOS_CELL="+str(cellname))
491 handle_before = self.handle.before
492 handle_after = self.handle.after
andrewonlabc03bf6c2014-10-09 14:56:18 -0400493 #Get the rest of the handle
494 self.handle.sendline("")
495 self.handle.expect("\$")
496 handle_more = self.handle.before
andrewonlab95ca1462014-10-09 14:04:24 -0400497
498 main.log.info("Cell call returned: "+handle_before+
andrewonlabc03bf6c2014-10-09 14:56:18 -0400499 handle_after + handle_more)
andrewonlab95ca1462014-10-09 14:04:24 -0400500
501 return main.TRUE
502
503 except pexpect.EOF:
504 main.log.error(self.name + ": EOF exception found")
505 main.log.error(self.name + ": " + self.handle.before)
506 main.cleanup()
507 main.exit()
508 except:
509 main.log.info(self.name+" ::::::")
510 main.log.error( traceback.print_exc())
511 main.log.info(self.name+" ::::::")
512 main.cleanup()
513 main.exit()
514
andrewonlabc03bf6c2014-10-09 14:56:18 -0400515 def verify_cell(self):
516 '''
517 Calls 'onos-verify-cell' to check for cell installation
518 '''
andrewonlab8d0d7d72014-10-09 16:33:15 -0400519 #TODO: Add meaningful expect value
520
andrewonlabc03bf6c2014-10-09 14:56:18 -0400521 try:
522 #Clean handle by sending empty and expecting $
523 self.handle.sendline("")
524 self.handle.expect("\$")
525 self.handle.sendline("onos-verify-cell")
526 self.handle.expect("\$")
527 handle_before = self.handle.before
528 handle_after = self.handle.after
529 #Get the rest of the handle
530 self.handle.sendline("")
531 self.handle.expect("\$")
532 handle_more = self.handle.before
533
534 main.log.info("Verify cell returned: "+handle_before+
535 handle_after + handle_more)
536
537 return main.TRUE
Jon Hall7993bfc2014-10-09 16:30:14 -0400538 except pexpect.EOF:
539 main.log.error(self.name + ": EOF exception found")
540 main.log.error(self.name + ": " + self.handle.before)
541 main.cleanup()
542 main.exit()
543 except:
544 main.log.info(self.name+" ::::::")
545 main.log.error( traceback.print_exc())
546 main.log.info(self.name+" ::::::")
547 main.cleanup()
548 main.exit()
549
andrewonlab05e362f2014-10-10 00:40:57 -0400550 def onos_cli(self, ONOS_ip, cmdstr):
551 '''
552 Uses 'onos' command to send various ONOS CLI arguments.
553 Required:
554 * ONOS_ip: specify the ip of the cell machine
andrewonlab94282092014-10-10 13:00:11 -0400555 * cmdstr: specify the command string to send
andrewonlab6e20c342014-10-10 18:08:48 -0400556
557 This function is intended to expose the entire karaf
558 CLI commands for ONOS. Try to use this function first
559 before attempting to write a ONOS CLI specific driver
560 function.
561 You can see a list of available 'cmdstr' arguments
562 by starting onos, and typing in 'onos' to enter the
563 onos> CLI. Then, type 'help' to see the list of
564 available commands.
andrewonlab05e362f2014-10-10 00:40:57 -0400565 '''
566 try:
567 if not ONOS_ip:
568 main.log.error("You must specify the IP address")
569 return main.FALSE
570 if not cmdstr:
571 main.log.error("You must specify the command string")
572 return main.FALSE
573
574 cmdstr = str(cmdstr)
575 self.handle.sendline("")
576 self.handle.expect("\$")
577
578 self.handle.sendline("onos -w " + ONOS_ip + " " + cmdstr)
579 self.handle.expect("\$")
580
581 handle_before = str(self.handle.before)
582 handle_after = str(self.handle.after)
583
584 self.handle.sendline("")
585 self.handle.expect("\$")
586 handle_more = str(self.handle.before)
587
588 main.log.info("Command sent successfully")
589
andrewonlab94282092014-10-10 13:00:11 -0400590 #Obtain return handle that consists of result from
591 #the onos command. The string may need to be
592 #configured further.
andrewonlab05e362f2014-10-10 00:40:57 -0400593 return_string = handle_before + handle_after + handle_more
andrewonlab05e362f2014-10-10 00:40:57 -0400594 return return_string
595
596 except pexpect.EOF:
597 main.log.error(self.name + ": EOF exception found")
598 main.log.error(self.name + ": " + self.handle.before)
599 main.cleanup()
600 main.exit()
601 except:
602 main.log.info(self.name+" ::::::")
603 main.log.error( traceback.print_exc())
604 main.log.info(self.name+" ::::::")
605 main.cleanup()
606 main.exit()
Jon Hall7993bfc2014-10-09 16:30:14 -0400607
608 def onos_install(self, options="-f", node = ""):
609 '''
610 Installs ONOS bits on the designated cell machine.
611 If -f option is provided, it also forces an uninstall.
612 Presently, install also includes onos-push-bits and
613 onos-config within.
614 The node option allows you to selectively only push the jar
615 files to certain onos nodes
616
617 Returns: main.TRUE on success and main.FALSE on failure
618 '''
619 try:
620 self.handle.sendline("onos-install " + options + " " + node)
621 self.handle.expect("onos-install ")
622 #NOTE: this timeout may need to change depending on the network and size of ONOS
623 i=self.handle.expect(["Network\sis\sunreachable",
624 "onos\sstart/running,\sprocess",
625 pexpect.TIMEOUT],timeout=60)
626
627
628 if i == 0:
629 main.log.warn("Network is unreachable")
630 return main.FALSE
631 elif i == 1:
632 main.log.info("ONOS was installed on the VM and started")
633 return main.TRUE
634 elif i == 2:
635 main.log.info("Installation of ONOS on the VM timed out")
636 return main.FALSE
andrewonlabc03bf6c2014-10-09 14:56:18 -0400637
638 except pexpect.EOF:
639 main.log.error(self.name + ": EOF exception found")
640 main.log.error(self.name + ": " + self.handle.before)
641 main.cleanup()
642 main.exit()
643 except:
644 main.log.info(self.name+" ::::::")
645 main.log.error( traceback.print_exc())
646 main.log.info(self.name+" ::::::")
647 main.cleanup()
648 main.exit()
andrewonlab95ca1462014-10-09 14:04:24 -0400649
andrewonlab8d0d7d72014-10-09 16:33:15 -0400650 def onos_start(self, node_ip):
651 '''
652 Calls onos command: 'onos-service [<node-ip>] start'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400653 This command is a remote management of the ONOS upstart daemon
andrewonlab8d0d7d72014-10-09 16:33:15 -0400654 '''
655
656 try:
657 self.handle.sendline("")
658 self.handle.expect("\$")
659 self.handle.sendline("onos-service "+str(node_ip)+
660 " start")
661 i = self.handle.expect([
662 "Job\sis\salready\srunning",
663 "start/running",
664 "Unknown\sinstance",
665 pexpect.TIMEOUT],timeout=60)
666
667 if i == 0:
668 main.log.info("Service is already running")
669 return main.TRUE
670 elif i == 1:
671 main.log.info("ONOS service started")
672 return main.TRUE
673 else:
674 main.log.error("ONOS service failed to start")
675 main.cleanup()
676 main.exit()
andrewonlab8d0d7d72014-10-09 16:33:15 -0400677 except pexpect.EOF:
678 main.log.error(self.name + ": EOF exception found")
679 main.log.error(self.name + ": " + self.handle.before)
680 main.cleanup()
681 main.exit()
682 except:
683 main.log.info(self.name+" ::::::")
684 main.log.error( traceback.print_exc())
685 main.log.info(self.name+" ::::::")
686 main.cleanup()
687 main.exit()
688
andrewonlab2b30bd32014-10-09 16:48:55 -0400689 def onos_stop(self, node_ip):
690 '''
691 Calls onos command: 'onos-service [<node-ip>] stop'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400692 This command is a remote management of the ONOS upstart daemon
andrewonlab2b30bd32014-10-09 16:48:55 -0400693 '''
694 try:
695 self.handle.sendline("")
696 self.handle.expect("\$")
697 self.handle.sendline("onos-service "+str(node_ip)+
698 " stop")
699 i = self.handle.expect([
700 "stop/waiting",
701 "Unknown\sinstance",
702 pexpect.TIMEOUT],timeout=60)
703
704 if i == 0:
705 main.log.info("ONOS service stopped")
706 return main.TRUE
707 elif i == 1:
708 main.log.info("Unknown ONOS instance specified: "+
709 str(node_ip))
710 return main.FALSE
711 else:
712 main.log.error("ONOS service failed to stop")
713 return main.FALSE
714
715 except pexpect.EOF:
716 main.log.error(self.name + ": EOF exception found")
717 main.log.error(self.name + ": " + self.handle.before)
718 main.cleanup()
719 main.exit()
720 except:
721 main.log.info(self.name+" ::::::")
722 main.log.error( traceback.print_exc())
723 main.log.info(self.name+" ::::::")
724 main.cleanup()
725 main.exit()
726
andrewonlabc8d47972014-10-09 16:52:36 -0400727 def onos_uninstall(self):
728 '''
729 Calls the command: 'onos-uninstall'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400730 Uninstalls ONOS from the designated cell machine, stopping
731 if needed
andrewonlabc8d47972014-10-09 16:52:36 -0400732 '''
733 try:
734 self.handle.sendline("")
735 self.handle.expect("\$")
736 self.handle.sendline("onos-uninstall")
737 self.handle.expect("\$")
738
andrewonlab84727452014-10-09 18:15:36 -0400739 main.log.info("ONOS cell machine was uninstalled")
andrewonlabc8d47972014-10-09 16:52:36 -0400740 #onos-uninstall command does not return any text
741 return main.TRUE
742
743 except pexpect.EOF:
744 main.log.error(self.name + ": EOF exception found")
745 main.log.error(self.name + ": " + self.handle.before)
746 main.cleanup()
747 main.exit()
748 except:
749 main.log.info(self.name+" ::::::")
750 main.log.error( traceback.print_exc())
751 main.log.info(self.name+" ::::::")
752 main.cleanup()
753 main.exit()
andrewonlab2b30bd32014-10-09 16:48:55 -0400754
andrewonlabe8e56fd2014-10-09 17:12:44 -0400755 def onos_kill(self, node_ip):
756 '''
757 Calls the command: 'onos-kill [<node-ip>]'
758 "Remotely, and unceremoniously kills the ONOS instance running on
759 the specified cell machine" - Tom V
760 '''
761
762 try:
763 self.handle.sendline("")
764 self.handle.expect("\$")
765 self.handle.sendline("onos-kill " + str(node_ip))
766 i = self.handle.expect([
767 "\$",
768 "No\sroute\sto\shost",
769 "password:",
770 pexpect.TIMEOUT], timeout=20)
771
772 if i == 0:
773 main.log.info("ONOS instance "+str(node_ip)+" was killed")
774 return main.TRUE
775 elif i == 1:
776 main.log.info("No route to host")
777 return main.FALSE
778 elif i == 2:
779 main.log.info("Passwordless login for host: "+str(node_ip)+
780 " not configured")
781 return main.FALSE
782 else:
783 main.log.info("ONOS instasnce was not killed")
784 return main.FALSE
785
786 except pexpect.EOF:
787 main.log.error(self.name + ": EOF exception found")
788 main.log.error(self.name + ": " + self.handle.before)
789 main.cleanup()
790 main.exit()
791 except:
792 main.log.info(self.name+" ::::::")
793 main.log.error( traceback.print_exc())
794 main.log.info(self.name+" ::::::")
795 main.cleanup()
796 main.exit()
797
andrewonlab94282092014-10-10 13:00:11 -0400798 def onos_start_network(self, mntopo):
799 '''
800 Calls the command 'onos-start-network [<mininet-topo>]
801 "remotely starts the specified topology on the cell's
802 mininet machine against all controllers configured in the
803 cell."
804 * Specify mininet topology file name for mntopo
805 * Topo files should be placed at:
806 ~/<your-onos-directory>/tools/test/topos
807
808 NOTE: This function will take you to the mininet prompt
809 '''
810 try:
811 if not mntopo:
812 main.log.error("You must specify a topo file to execute")
813 return main.FALSE
814
815 mntopo = str(mntopo)
816 self.handle.sendline("")
817 self.handle.expect("\$")
818
819 self.handle.sendline("onos-start-network " + mntopo)
820 self.handle.expect("mininet>")
821 main.log.info("Network started, entered mininet prompt")
822
823 #TODO: Think about whether return is necessary or not
824
825 except pexpect.EOF:
826 main.log.error(self.name + ": EOF exception found")
827 main.log.error(self.name + ": " + self.handle.before)
828 main.cleanup()
829 main.exit()
830 except:
831 main.log.info(self.name+" ::::::")
832 main.log.error( traceback.print_exc())
833 main.log.info(self.name+" ::::::")
834 main.cleanup()
835 main.exit()
836
837
Jon Hall7993bfc2014-10-09 16:30:14 -0400838 def isup(self, node = ""):
839 '''
Jon Hall77f53ce2014-10-13 18:02:06 -0400840 Run's onos-wait-for-start which only returns once ONOS is at run
841 level 100(ready for use)
andrewonlab8d0d7d72014-10-09 16:33:15 -0400842
Jon Hall7993bfc2014-10-09 16:30:14 -0400843 Returns: main.TRUE if ONOS is running and main.FALSE on timeout
844 '''
845 try:
846 self.handle.sendline("onos-wait-for-start " + node )
847 self.handle.expect("onos-wait-for-start")
848 #NOTE: this timeout is arbitrary"
849 i = self.handle.expect(["\$", pexpect.TIMEOUT], timeout = 120)
850 if i == 0:
851 main.log.info(self.name + ": " + node + " is up")
852 return main.TRUE
853 elif i == 1:
854 #NOTE: since this function won't return until ONOS is ready,
855 # we will kill it on timeout
856 self.handle.sendline("\003") #Control-C
857 self.handle.expect("\$")
858 return main.FALSE
859 except pexpect.EOF:
860 main.log.error(self.name + ": EOF exception found")
861 main.log.error(self.name + ": " + self.handle.before)
862 main.cleanup()
863 main.exit()
864 except:
865 main.log.info(self.name+" ::::::")
866 main.log.error( traceback.print_exc())
867 main.log.info(self.name+" ::::::")
868 main.cleanup()
869 main.exit()
andrewonlab05e362f2014-10-10 00:40:57 -0400870
871
Jon Hall77f53ce2014-10-13 18:02:06 -0400872 def get_topology(self, ip):
873 '''
874 parses the onos:topology output
875 Returns: a topology dict populated by the key values found in
876 the cli command.
877 '''
878
879 try:
880 #call the cli to get the topology summary
881 cmdstr = "onos:topology"
882 cli_result = self.onos_cli(ip, cmdstr)
883
884
885 #Parse the output
886 topology = {}
887 #for line in cli_result.split("\n"):
888 for line in cli_result.splitlines():
889 if not line.startswith("time="):
890 continue
891 #else
892 print line
893 for var in line.split(","):
894 print "'"+var+"'"
895 print "'"+var.strip()+"'"
896 key, value = var.strip().split("=")
897 topology[key] = value
898 print topology
899 devices = topology.get('devices', False)
900 print devices
901 links = topology.get('links', False)
902 print links
903 clusters = topology.get('clusters', False)
904 print clusters
905 paths = topology.get('paths', False)
906 print paths
907
908 return topology
909 except pexpect.EOF:
910 main.log.error(self.name + ": EOF exception found")
911 main.log.error(self.name + ": " + self.handle.before)
912 main.cleanup()
913 main.exit()
914 except:
915 main.log.info(self.name+" ::::::")
916 main.log.error( traceback.print_exc())
917 main.log.info(self.name+" ::::::")
918 main.cleanup()
919 main.exit()
920
921 def check_status(self, ip, numoswitch, numolink, log_level="info"):
922 '''
923 Checks the number of swithes & links that ONOS sees against the
924 supplied values. By default this will report to main.log, but the
925 log level can be specifid.
926
927 Params: ip = ip used for the onos cli
928 numoswitch = expected number of switches
929 numlink = expected number of links
930 log_level = level to log to. Currently accepts 'info', 'warn' and 'report'
931
932
933 log_level can
934
935 Returns: main.TRUE if the number of switchs and links are correct,
936 main.FALSE if the numer of switches and links is incorrect,
937 and main.ERROR otherwise
938 '''
939
940 try:
941 topology = self.get_topology(ip)
942 if topology == {}:
943 return main.ERROR
944 output = ""
945 #Is the number of switches is what we expected
946 devices = topology.get('devices',False)
947 links = topology.get('links',False)
948 if devices == False or links == False:
949 return main.ERROR
950 switch_check = ( int(devices) == int(numoswitch) )
951 #Is the number of links is what we expected
952 link_check = ( int(links) == int(numolink) )
953 if (switch_check and link_check):
954 #We expected the correct numbers
955 output = output + "The number of links and switches match "\
956 + "what was expected"
957 result = main.TRUE
958 else:
959 output = output + \
960 "The number of links and switches does not match what was expected"
961 result = main.FALSE
962 output = output + "\n ONOS sees %i devices (%i expected) and %i links (%i expected)"\
963 % ( int(devices), int(numoswitch), int(links), int(numolink) )
964 if log_level == "report":
965 main.log.report(output)
966 elif log_level == "warn":
967 main.log.warn(output)
968 else:
969 main.log.info(output)
970 return result
971 except pexpect.EOF:
972 main.log.error(self.name + ": EOF exception found")
973 main.log.error(self.name + ": " + self.handle.before)
974 main.cleanup()
975 main.exit()
976 except:
977 main.log.info(self.name+" ::::::")
978 main.log.error( traceback.print_exc())
979 main.log.info(self.name+" ::::::")
980 main.cleanup()
981 main.exit()
andrewonlabba44bcf2014-10-16 16:54:41 -0400982
983 def tshark_grep(self, grep, directory, interface='eth0'):
984 '''
985 Required:
986 * grep string
987 * directory to store results
988 Optional:
989 * interface - default: eth0
990 Description:
991 Uses tshark command to grep specific group of packets
992 and stores the results to specified directory.
993 The timestamp is hardcoded to be in epoch
994 '''
995 self.handle.sendline("")
996 self.handle.expect("\$")
andrewonlabefd7f3d2014-10-21 16:02:31 -0400997 self.handle.sendline("")
andrewonlabba44bcf2014-10-16 16:54:41 -0400998 self.handle.sendline("tshark -i "+str(interface)+
andrewonlabefd7f3d2014-10-21 16:02:31 -0400999 " -t e | grep --line-buffered \""+str(grep)+"\" > "+directory+" &")
andrewonlabba44bcf2014-10-16 16:54:41 -04001000 self.handle.sendline("\r")
1001 self.handle.expect("Capturing on")
1002 self.handle.sendline("\r")
1003 self.handle.expect("\$")
1004
1005 def tshark_stop(self):
1006 '''
1007 Removes wireshark files from /tmp and kills all tshark processes
1008 '''
1009 self.execute(cmd="rm /tmp/wireshark*")
1010 self.handle.sendline("")
1011 self.handle.sendline("sudo kill -9 `ps -ef | grep \"tshark -i\" |"+
1012 " grep -v grep | awk '{print $2}'`")
1013 self.handle.sendline("")
1014 main.log.info("Tshark stopped")
1015
1016
1017
1018