blob: 5532b8a9d209d66d9f8a7400c1b1e447c4459a56 [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:
85 self.handle.sendline("exit")
86 self.handle.expect("closed")
87 except pexpect.EOF:
88 main.log.error(self.name + ": EOF exception found")
89 main.log.error(self.name + ": " + self.handle.before)
90 except:
91 main.log.error(self.name + ": Connection failed to the host")
92 response = main.FALSE
93 return response
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -040094
95 def onos_package(self):
96 '''
97 Produce a self-contained tar.gz file that can be deployed
98 and executed on any platform with Java 7 JRE.
99 '''
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400100
101 try:
102 self.handle.sendline("onos-package")
Jon Hallea7818b2014-10-09 14:30:59 -0400103 self.handle.expect("onos-package")
andrewonlab0748d2a2014-10-09 13:24:17 -0400104 self.handle.expect("tar.gz",timeout=10)
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400105 handle = str(self.handle.before)
106 main.log.info("onos-package command returned: "+
107 handle)
andrewonlab0748d2a2014-10-09 13:24:17 -0400108 #As long as the sendline does not time out,
109 #return true. However, be careful to interpret
110 #the results of the onos-package command return
111 return main.TRUE
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400112
andrewonlab7735d852014-10-09 13:02:47 -0400113 except pexpect.EOF:
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400114 main.log.error(self.name + ": EOF exception found")
115 main.log.error(self.name + ": " + self.handle.before)
116 except:
117 main.log.error("Failed to package ONOS")
118 main.cleanup()
119 main.exit()
120
Jon Hallde9d9aa2014-10-08 20:36:02 -0400121 def clean_install(self):
122 '''
123 Runs mvn clean install in the root of the ONOS directory.
124 This will clean all ONOS artifacts then compile each module
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400125
Jon Hallde9d9aa2014-10-08 20:36:02 -0400126 Returns: main.TRUE on success
127 On Failure, exits the test
128 '''
129 try:
Jon Hallea7818b2014-10-09 14:30:59 -0400130 main.log.info("Running 'mvn clean install' on " + str(self.name) +
131 ". This may take some time.")
132 self.handle.sendline("cd "+ self.home)
133 self.handle.expect("\$")
134
135 self.handle.sendline("\n")
136 self.handle.expect("\$")
Jon Hallde9d9aa2014-10-08 20:36:02 -0400137 self.handle.sendline("mvn clean install")
Jon Hallea7818b2014-10-09 14:30:59 -0400138 self.handle.expect("mvn clean install")
Jon Hallde9d9aa2014-10-08 20:36:02 -0400139 while 1:
140 i=self.handle.expect([
141 'There\sis\sinsufficient\smemory\sfor\sthe\sJava\s\
142 Runtime\sEnvironment\sto\scontinue',
143 'BUILD\sFAILURE',
144 'BUILD\sSUCCESS',
145 'ONOS\$',
146 pexpect.TIMEOUT],timeout=600)
147 if i == 0:
148 main.log.error(self.name + ":There is insufficient memory \
149 for the Java Runtime Environment to continue.")
150 #return main.FALSE
151 main.cleanup()
152 main.exit()
153 if i == 1:
154 main.log.error(self.name + ": Build failure!")
155 #return main.FALSE
156 main.cleanup()
157 main.exit()
158 elif i == 2:
159 main.log.info(self.name + ": Build success!")
160 elif i == 3:
161 main.log.info(self.name + ": Build complete")
Jon Hallf8ef52c2014-10-09 19:37:33 -0400162 #Print the build time
163 for line in self.handle.before.splitlines():
164 if "Total time:" in line:
165 main.log.info(line)
Jon Hallea7818b2014-10-09 14:30:59 -0400166 self.handle.sendline("\n")
Jon Hallde9d9aa2014-10-08 20:36:02 -0400167 self.handle.expect("\$", timeout=60)
168 return main.TRUE
169 elif i == 4:
170 main.log.error(self.name + ": mvn clean install TIMEOUT!")
171 #return main.FALSE
172 main.cleanup()
173 main.exit()
174 else:
175 main.log.error(self.name + ": unexpected response from \
176 mvn clean install")
177 #return main.FALSE
178 main.cleanup()
179 main.exit()
180 except pexpect.EOF:
181 main.log.error(self.name + ": EOF exception found")
182 main.log.error(self.name + ": " + self.handle.before)
183 main.cleanup()
184 main.exit()
185 except:
186 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
187 main.log.error( traceback.print_exc() )
188 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
189 main.cleanup()
190 main.exit()
Jon Hallacabffd2014-10-09 12:36:53 -0400191
192 def git_pull(self, comp1=""):
193 '''
194 Assumes that "git pull" works without login
195
196 This function will perform a git pull on the ONOS instance.
197 If used as git_pull("NODE") it will do git pull + NODE. This is
198 for the purpose of pulling from other nodes if necessary.
199
200 Otherwise, this function will perform a git pull in the
201 ONOS repository. If it has any problems, it will return main.ERROR
202 If it successfully does a git_pull, it will return a 1.
203 If it has no updates, it will return a 0.
204
205 '''
206 try:
207 # main.log.info(self.name + ": Stopping ONOS")
208 #self.stop()
209 self.handle.sendline("cd " + self.home)
210 self.handle.expect("ONOS\$")
211 if comp1=="":
212 self.handle.sendline("git pull")
213 else:
214 self.handle.sendline("git pull " + comp1)
215
216 uptodate = 0
217 i=self.handle.expect(['fatal',
218 'Username\sfor\s(.*):\s',
219 '\sfile(s*) changed,\s',
220 'Already up-to-date',
221 'Aborting',
222 'You\sare\snot\scurrently\son\sa\sbranch',
223 'You\sasked\sme\sto\spull\swithout\stelling\sme\swhich\sbranch\syou',
224 'Pull\sis\snot\spossible\sbecause\syou\shave\sunmerged\sfiles',
225 pexpect.TIMEOUT],
226 timeout=300)
227 #debug
228 #main.log.report(self.name +": \n"+"git pull response: " + str(self.handle.before) + str(self.handle.after))
229 if i==0:
230 main.log.error(self.name + ": Git pull had some issue...")
231 return main.ERROR
232 elif i==1:
233 main.log.error(self.name + ": Git Pull Asking for username. ")
234 return main.ERROR
235 elif i==2:
236 main.log.info(self.name + ": Git Pull - pulling repository now")
237 self.handle.expect("ONOS\$", 120)
Jon Hall77f53ce2014-10-13 18:02:06 -0400238 return main.TRUE
Jon Hallacabffd2014-10-09 12:36:53 -0400239 elif i==3:
240 main.log.info(self.name + ": Git Pull - Already up to date")
Jon Hall77f53ce2014-10-13 18:02:06 -0400241 return main.TRUE
Jon Hallacabffd2014-10-09 12:36:53 -0400242 elif i==4:
243 main.log.info(self.name + ": Git Pull - Aborting... Are there conflicting git files?")
244 return main.ERROR
245 elif i==5:
246 main.log.info(self.name + ": Git Pull - You are not currently on a branch so git pull failed!")
247 return main.ERROR
248 elif i==6:
249 main.log.info(self.name + ": Git Pull - You have not configured an upstream branch to pull from. Git pull failed!")
250 return main.ERROR
251 elif i==7:
252 main.log.info(self.name + ": Git Pull - Pull is not possible because you have unmerged files.")
253 return main.ERROR
254 elif i==8:
255 main.log.error(self.name + ": Git Pull - TIMEOUT")
256 main.log.error(self.name + " Response was: " + str(self.handle.before))
257 return main.ERROR
258 else:
259 main.log.error(self.name + ": Git Pull - Unexpected response, check for pull errors")
260 return main.ERROR
261 except pexpect.EOF:
262 main.log.error(self.name + ": EOF exception found")
263 main.log.error(self.name + ": " + self.handle.before)
264 main.cleanup()
265 main.exit()
266 except:
267 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
268 main.log.error( traceback.print_exc() )
269 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
270 main.cleanup()
271 main.exit()
272
273 def git_checkout(self, branch="master"):
274 '''
275 Assumes that "git pull" works without login
276
277 This function will perform a git git checkout on the ONOS instance.
278 If used as git_checkout("branch") it will do git checkout of the "branch".
279
280 Otherwise, this function will perform a git checkout of the master
281 branch of the ONOS repository. If it has any problems, it will return
282 main.ERROR.
283 If the branch was already the specified branch, or the git checkout was
284 successful then the function will return main.TRUE.
285
286 '''
287 try:
288 # main.log.info(self.name + ": Stopping ONOS")
289 #self.stop()
290 self.handle.sendline("cd " + self.home)
291 self.handle.expect("ONOS\$")
292 if branch != 'master':
293 #self.handle.sendline('git stash')
294 #self.handle.expect('ONOS\$')
295 #print "After issuing git stash cmnd: ", self.handle.before
296 cmd = "git checkout "+branch
297 print "checkout cmd = ", cmd
298 self.handle.sendline(cmd)
299 uptodate = 0
300 i=self.handle.expect(['fatal',
301 'Username\sfor\s(.*):\s',
302 'Already\son\s\'',
303 'Switched\sto\sbranch\s\'',
304 pexpect.TIMEOUT],timeout=60)
305 else:
306 #self.handle.sendline('git stash apply')
307 #self.handle.expect('ONOS\$')
308 #print "After issuing git stash apply cmnd: ", self.handle.before
309 cmd = "git checkout "+branch
310 print "checkout cmd = ", cmd
311 self.handle.sendline(cmd)
312 uptodate = 0
313 switchedToMaster = 0
314 i=self.handle.expect(['fatal',
315 'Username\sfor\s(.*):\s',
316 'Already\son\s\'master\'',
317 'Switched\sto\sbranch\s\'master\'',
318 pexpect.TIMEOUT],timeout=60)
319
320
321 if i==0:
322 main.log.error(self.name + ": Git checkout had some issue...")
323 return main.ERROR
324 elif i==1:
325 main.log.error(self.name + ": Git checkout Asking for username!!! Bad!")
326 return main.ERROR
327 elif i==2:
328 main.log.info(self.name + ": Git Checkout %s : Already on this branch" %branch)
329 self.handle.expect("ONOS\$")
330 print "after checkout cmd = ", self.handle.before
331 switchedToMaster = 1
332 return main.TRUE
333 elif i==3:
334 main.log.info(self.name + ": Git checkout %s - Switched to this branch" %branch)
335 self.handle.expect("ONOS\$")
336 print "after checkout cmd = ", self.handle.before
337 switchedToMaster = 1
338 return main.TRUE
339 elif i==4:
340 main.log.error(self.name + ": Git Checkout- TIMEOUT")
341 main.log.error(self.name + " Response was: " + str(self.handle.before))
342 return main.ERROR
343 else:
344 main.log.error(self.name + ": Git Checkout - Unexpected response, check for pull errors")
345 return main.ERROR
346
347 except pexpect.EOF:
348 main.log.error(self.name + ": EOF exception found")
349 main.log.error(self.name + ": " + self.handle.before)
350 main.cleanup()
351 main.exit()
352 except:
353 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
354 main.log.error( traceback.print_exc() )
355 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
356 main.cleanup()
357 main.exit()
andrewonlab95ca1462014-10-09 14:04:24 -0400358
Jon Hall45ec0922014-10-10 19:33:49 -0400359 def get_version(self):
360 '''
361 Writes the COMMIT number to the report to be parsed by Jenkins data collecter.
362 '''
363 try:
364 self.handle.sendline("export TERM=xterm-256color")
365 self.handle.expect("xterm-256color")
366 self.handle.expect("\$")
367 self.handle.sendline("cd " + self.home + "; git log -1 --pretty=fuller --decorate=short | grep -A 5 \"commit\" --color=never; cd \.\.")
368 self.handle.expect("cd ..")
369 self.handle.expect("\$")
370 response=(self.name +": \n"+ str(self.handle.before + self.handle.after))
371 lines=response.splitlines()
372 for line in lines:
373 print line
374 return lines[2]
375 except pexpect.EOF:
376 main.log.error(self.name + ": EOF exception found")
377 main.log.error(self.name + ": " + self.handle.before)
378 main.cleanup()
379 main.exit()
380 except:
381 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
382 main.log.error( traceback.print_exc() )
383 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
384 main.cleanup()
385 main.exit()
386
andrewonlab94282092014-10-10 13:00:11 -0400387 def create_cell_file(self, bench_ip, file_name, mn_ip_addrs, *onos_ip_addrs):
388 '''
389 Creates a cell file based on arguments
390 Required:
391 * Bench IP address (bench_ip)
392 - Needed to copy the cell file over
393 * File name of the cell file (file_name)
394 * Mininet IP address (mn_ip_addrs)
395 - Note that only 1 ip address is
396 supported currently
397 * ONOS IP addresses (onos_ip_addrs)
398 - Must be passed in as last arguments
399
400 NOTE: Assumes cells are located at:
401 ~/<self.home>/tools/test/cells/
402 '''
403
404 #Variable initialization
405 cell_directory = self.home + "/tools/test/cells/"
406 #We want to create the cell file in the dependencies directory
407 #of TestON first, then copy over to ONOS bench
408 temp_directory = "/tmp/"
409 #Create the cell file in the directory for writing (w+)
410 cell_file = open(temp_directory+file_name , 'w+')
411
andrewonlab7e4d2d32014-10-15 13:23:21 -0400412 #Feature string is hardcoded environment variables
413 #That you may wish to use by default on startup.
414 #Note that you may not want certain features listed
415 #on here.
andrewonlab94282092014-10-10 13:00:11 -0400416 feature_string = "export ONOS_FEATURES=webconsole,onos-api,"+\
417 "onos-core-trivial,onos-cli,onos-openflow,"+\
418 "onos-app-fwd,onos-app-mobility,onos-app-tvue,"+\
419 "onos-app-proxyarp"
420 mn_string = "export OCN="
421 onos_string = "export OC"
422 temp_count = 1
423
424 #Create ONOS_NIC ip address prefix
425 temp_onos_ip = onos_ip_addrs[0]
426 temp_list = []
427 temp_list = temp_onos_ip.split(".")
andrewonlab7e4d2d32014-10-15 13:23:21 -0400428 #Omit last element of list to format for NIC
andrewonlab94282092014-10-10 13:00:11 -0400429 temp_list = temp_list[:-1]
430 #Structure the nic string ip
431 nic_addr = ".".join(temp_list) + ".*\n"
432 onos_nic_string = "export ONOS_NIC="+nic_addr
433
434 try:
435 #Start writing to file
436 cell_file.write(feature_string + "\n")
437 cell_file.write(onos_nic_string)
438 cell_file.write(mn_string +"'"+ mn_ip_addrs +"'"+ "\n")
439
440 for arg in onos_ip_addrs:
441 #For each argument in onos_ip_addrs, write to file
442 #Output should look like the following:
443 # export OC1='10.128.20.11'
444 # export OC2='10.128.20.12'
445 cell_file.write(onos_string + str(temp_count) +
446 "=" + "'" + arg + "'" + "\n" )
447 temp_count = temp_count + 1
448
449 cell_file.close()
450
451 #We use os.system to send the command to TestON cluster
452 #to account for the case in which TestON is not located
453 #on the same cluster as the ONOS bench
454 #Note that even if TestON is located on the same cluster
455 #as ONOS bench, you must setup passwordless ssh
andrewonlab7e4d2d32014-10-15 13:23:21 -0400456 #between TestON and ONOS bench in order to automate the test.
andrewonlab94282092014-10-10 13:00:11 -0400457 os.system("scp "+temp_directory+file_name+
458 " admin@"+bench_ip+":"+cell_directory)
459
andrewonlab2a6c9342014-10-16 13:40:15 -0400460 return main.TRUE
461
andrewonlab94282092014-10-10 13:00:11 -0400462 except pexpect.EOF:
463 main.log.error(self.name + ": EOF exception found")
464 main.log.error(self.name + ": " + self.handle.before)
465 main.cleanup()
466 main.exit()
467 except:
468 main.log.info(self.name + ":::::::::")
469 main.log.error( traceback.print_exc() )
470 main.log.info(":::::::")
471 main.cleanup()
472 main.exit()
473
andrewonlab95ca1462014-10-09 14:04:24 -0400474 def set_cell(self, cellname):
475 '''
476 Calls 'cell <name>' to set the environment variables on ONOSbench
477 '''
478 try:
479 if not cellname:
480 main.log.error("Must define cellname")
481 main.cleanup()
482 main.exit()
483 else:
484 self.handle.sendline("cell "+str(cellname))
485 #Expect the cellname in the ONOS_CELL variable.
486 #Note that this variable name is subject to change
487 # and that this driver will have to change accordingly
488 self.handle.expect("ONOS_CELL="+str(cellname))
489 handle_before = self.handle.before
490 handle_after = self.handle.after
andrewonlabc03bf6c2014-10-09 14:56:18 -0400491 #Get the rest of the handle
492 self.handle.sendline("")
493 self.handle.expect("\$")
494 handle_more = self.handle.before
andrewonlab95ca1462014-10-09 14:04:24 -0400495
496 main.log.info("Cell call returned: "+handle_before+
andrewonlabc03bf6c2014-10-09 14:56:18 -0400497 handle_after + handle_more)
andrewonlab95ca1462014-10-09 14:04:24 -0400498
499 return main.TRUE
500
501 except pexpect.EOF:
502 main.log.error(self.name + ": EOF exception found")
503 main.log.error(self.name + ": " + self.handle.before)
504 main.cleanup()
505 main.exit()
506 except:
507 main.log.info(self.name+" ::::::")
508 main.log.error( traceback.print_exc())
509 main.log.info(self.name+" ::::::")
510 main.cleanup()
511 main.exit()
512
andrewonlabc03bf6c2014-10-09 14:56:18 -0400513 def verify_cell(self):
514 '''
515 Calls 'onos-verify-cell' to check for cell installation
516 '''
andrewonlab8d0d7d72014-10-09 16:33:15 -0400517 #TODO: Add meaningful expect value
518
andrewonlabc03bf6c2014-10-09 14:56:18 -0400519 try:
520 #Clean handle by sending empty and expecting $
521 self.handle.sendline("")
522 self.handle.expect("\$")
523 self.handle.sendline("onos-verify-cell")
524 self.handle.expect("\$")
525 handle_before = self.handle.before
526 handle_after = self.handle.after
527 #Get the rest of the handle
528 self.handle.sendline("")
529 self.handle.expect("\$")
530 handle_more = self.handle.before
531
532 main.log.info("Verify cell returned: "+handle_before+
533 handle_after + handle_more)
534
535 return main.TRUE
Jon Hall7993bfc2014-10-09 16:30:14 -0400536 except pexpect.EOF:
537 main.log.error(self.name + ": EOF exception found")
538 main.log.error(self.name + ": " + self.handle.before)
539 main.cleanup()
540 main.exit()
541 except:
542 main.log.info(self.name+" ::::::")
543 main.log.error( traceback.print_exc())
544 main.log.info(self.name+" ::::::")
545 main.cleanup()
546 main.exit()
547
andrewonlab05e362f2014-10-10 00:40:57 -0400548 def onos_cli(self, ONOS_ip, cmdstr):
549 '''
550 Uses 'onos' command to send various ONOS CLI arguments.
551 Required:
552 * ONOS_ip: specify the ip of the cell machine
andrewonlab94282092014-10-10 13:00:11 -0400553 * cmdstr: specify the command string to send
andrewonlab6e20c342014-10-10 18:08:48 -0400554
555 This function is intended to expose the entire karaf
556 CLI commands for ONOS. Try to use this function first
557 before attempting to write a ONOS CLI specific driver
558 function.
559 You can see a list of available 'cmdstr' arguments
560 by starting onos, and typing in 'onos' to enter the
561 onos> CLI. Then, type 'help' to see the list of
562 available commands.
andrewonlab05e362f2014-10-10 00:40:57 -0400563 '''
564 try:
565 if not ONOS_ip:
566 main.log.error("You must specify the IP address")
567 return main.FALSE
568 if not cmdstr:
569 main.log.error("You must specify the command string")
570 return main.FALSE
571
572 cmdstr = str(cmdstr)
573 self.handle.sendline("")
574 self.handle.expect("\$")
575
576 self.handle.sendline("onos -w " + ONOS_ip + " " + cmdstr)
577 self.handle.expect("\$")
578
579 handle_before = str(self.handle.before)
580 handle_after = str(self.handle.after)
581
582 self.handle.sendline("")
583 self.handle.expect("\$")
584 handle_more = str(self.handle.before)
585
586 main.log.info("Command sent successfully")
587
andrewonlab94282092014-10-10 13:00:11 -0400588 #Obtain return handle that consists of result from
589 #the onos command. The string may need to be
590 #configured further.
andrewonlab05e362f2014-10-10 00:40:57 -0400591 return_string = handle_before + handle_after + handle_more
andrewonlab05e362f2014-10-10 00:40:57 -0400592 return return_string
593
594 except pexpect.EOF:
595 main.log.error(self.name + ": EOF exception found")
596 main.log.error(self.name + ": " + self.handle.before)
597 main.cleanup()
598 main.exit()
599 except:
600 main.log.info(self.name+" ::::::")
601 main.log.error( traceback.print_exc())
602 main.log.info(self.name+" ::::::")
603 main.cleanup()
604 main.exit()
Jon Hall7993bfc2014-10-09 16:30:14 -0400605
606 def onos_install(self, options="-f", node = ""):
607 '''
608 Installs ONOS bits on the designated cell machine.
609 If -f option is provided, it also forces an uninstall.
610 Presently, install also includes onos-push-bits and
611 onos-config within.
612 The node option allows you to selectively only push the jar
613 files to certain onos nodes
614
615 Returns: main.TRUE on success and main.FALSE on failure
616 '''
617 try:
618 self.handle.sendline("onos-install " + options + " " + node)
619 self.handle.expect("onos-install ")
620 #NOTE: this timeout may need to change depending on the network and size of ONOS
621 i=self.handle.expect(["Network\sis\sunreachable",
622 "onos\sstart/running,\sprocess",
623 pexpect.TIMEOUT],timeout=60)
624
625
626 if i == 0:
627 main.log.warn("Network is unreachable")
628 return main.FALSE
629 elif i == 1:
630 main.log.info("ONOS was installed on the VM and started")
631 return main.TRUE
632 elif i == 2:
633 main.log.info("Installation of ONOS on the VM timed out")
634 return main.FALSE
andrewonlabc03bf6c2014-10-09 14:56:18 -0400635
636 except pexpect.EOF:
637 main.log.error(self.name + ": EOF exception found")
638 main.log.error(self.name + ": " + self.handle.before)
639 main.cleanup()
640 main.exit()
641 except:
642 main.log.info(self.name+" ::::::")
643 main.log.error( traceback.print_exc())
644 main.log.info(self.name+" ::::::")
645 main.cleanup()
646 main.exit()
andrewonlab95ca1462014-10-09 14:04:24 -0400647
andrewonlab8d0d7d72014-10-09 16:33:15 -0400648 def onos_start(self, node_ip):
649 '''
650 Calls onos command: 'onos-service [<node-ip>] start'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400651 This command is a remote management of the ONOS upstart daemon
andrewonlab8d0d7d72014-10-09 16:33:15 -0400652 '''
653
654 try:
655 self.handle.sendline("")
656 self.handle.expect("\$")
657 self.handle.sendline("onos-service "+str(node_ip)+
658 " start")
659 i = self.handle.expect([
660 "Job\sis\salready\srunning",
661 "start/running",
662 "Unknown\sinstance",
663 pexpect.TIMEOUT],timeout=60)
664
665 if i == 0:
666 main.log.info("Service is already running")
667 return main.TRUE
668 elif i == 1:
669 main.log.info("ONOS service started")
670 return main.TRUE
671 else:
672 main.log.error("ONOS service failed to start")
673 main.cleanup()
674 main.exit()
andrewonlab8d0d7d72014-10-09 16:33:15 -0400675 except pexpect.EOF:
676 main.log.error(self.name + ": EOF exception found")
677 main.log.error(self.name + ": " + self.handle.before)
678 main.cleanup()
679 main.exit()
680 except:
681 main.log.info(self.name+" ::::::")
682 main.log.error( traceback.print_exc())
683 main.log.info(self.name+" ::::::")
684 main.cleanup()
685 main.exit()
686
andrewonlab2b30bd32014-10-09 16:48:55 -0400687 def onos_stop(self, node_ip):
688 '''
689 Calls onos command: 'onos-service [<node-ip>] stop'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400690 This command is a remote management of the ONOS upstart daemon
andrewonlab2b30bd32014-10-09 16:48:55 -0400691 '''
692 try:
693 self.handle.sendline("")
694 self.handle.expect("\$")
695 self.handle.sendline("onos-service "+str(node_ip)+
696 " stop")
697 i = self.handle.expect([
698 "stop/waiting",
699 "Unknown\sinstance",
700 pexpect.TIMEOUT],timeout=60)
701
702 if i == 0:
703 main.log.info("ONOS service stopped")
704 return main.TRUE
705 elif i == 1:
706 main.log.info("Unknown ONOS instance specified: "+
707 str(node_ip))
708 return main.FALSE
709 else:
710 main.log.error("ONOS service failed to stop")
711 return main.FALSE
712
713 except pexpect.EOF:
714 main.log.error(self.name + ": EOF exception found")
715 main.log.error(self.name + ": " + self.handle.before)
716 main.cleanup()
717 main.exit()
718 except:
719 main.log.info(self.name+" ::::::")
720 main.log.error( traceback.print_exc())
721 main.log.info(self.name+" ::::::")
722 main.cleanup()
723 main.exit()
724
andrewonlabc8d47972014-10-09 16:52:36 -0400725 def onos_uninstall(self):
726 '''
727 Calls the command: 'onos-uninstall'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400728 Uninstalls ONOS from the designated cell machine, stopping
729 if needed
andrewonlabc8d47972014-10-09 16:52:36 -0400730 '''
731 try:
732 self.handle.sendline("")
733 self.handle.expect("\$")
734 self.handle.sendline("onos-uninstall")
735 self.handle.expect("\$")
736
andrewonlab84727452014-10-09 18:15:36 -0400737 main.log.info("ONOS cell machine was uninstalled")
andrewonlabc8d47972014-10-09 16:52:36 -0400738 #onos-uninstall command does not return any text
739 return main.TRUE
740
741 except pexpect.EOF:
742 main.log.error(self.name + ": EOF exception found")
743 main.log.error(self.name + ": " + self.handle.before)
744 main.cleanup()
745 main.exit()
746 except:
747 main.log.info(self.name+" ::::::")
748 main.log.error( traceback.print_exc())
749 main.log.info(self.name+" ::::::")
750 main.cleanup()
751 main.exit()
andrewonlab2b30bd32014-10-09 16:48:55 -0400752
andrewonlabe8e56fd2014-10-09 17:12:44 -0400753 def onos_kill(self, node_ip):
754 '''
755 Calls the command: 'onos-kill [<node-ip>]'
756 "Remotely, and unceremoniously kills the ONOS instance running on
757 the specified cell machine" - Tom V
758 '''
759
760 try:
761 self.handle.sendline("")
762 self.handle.expect("\$")
763 self.handle.sendline("onos-kill " + str(node_ip))
764 i = self.handle.expect([
765 "\$",
766 "No\sroute\sto\shost",
767 "password:",
768 pexpect.TIMEOUT], timeout=20)
769
770 if i == 0:
771 main.log.info("ONOS instance "+str(node_ip)+" was killed")
772 return main.TRUE
773 elif i == 1:
774 main.log.info("No route to host")
775 return main.FALSE
776 elif i == 2:
777 main.log.info("Passwordless login for host: "+str(node_ip)+
778 " not configured")
779 return main.FALSE
780 else:
781 main.log.info("ONOS instasnce was not killed")
782 return main.FALSE
783
784 except pexpect.EOF:
785 main.log.error(self.name + ": EOF exception found")
786 main.log.error(self.name + ": " + self.handle.before)
787 main.cleanup()
788 main.exit()
789 except:
790 main.log.info(self.name+" ::::::")
791 main.log.error( traceback.print_exc())
792 main.log.info(self.name+" ::::::")
793 main.cleanup()
794 main.exit()
795
andrewonlab94282092014-10-10 13:00:11 -0400796 def onos_start_network(self, mntopo):
797 '''
798 Calls the command 'onos-start-network [<mininet-topo>]
799 "remotely starts the specified topology on the cell's
800 mininet machine against all controllers configured in the
801 cell."
802 * Specify mininet topology file name for mntopo
803 * Topo files should be placed at:
804 ~/<your-onos-directory>/tools/test/topos
805
806 NOTE: This function will take you to the mininet prompt
807 '''
808 try:
809 if not mntopo:
810 main.log.error("You must specify a topo file to execute")
811 return main.FALSE
812
813 mntopo = str(mntopo)
814 self.handle.sendline("")
815 self.handle.expect("\$")
816
817 self.handle.sendline("onos-start-network " + mntopo)
818 self.handle.expect("mininet>")
819 main.log.info("Network started, entered mininet prompt")
820
821 #TODO: Think about whether return is necessary or not
822
823 except pexpect.EOF:
824 main.log.error(self.name + ": EOF exception found")
825 main.log.error(self.name + ": " + self.handle.before)
826 main.cleanup()
827 main.exit()
828 except:
829 main.log.info(self.name+" ::::::")
830 main.log.error( traceback.print_exc())
831 main.log.info(self.name+" ::::::")
832 main.cleanup()
833 main.exit()
834
835
Jon Hall7993bfc2014-10-09 16:30:14 -0400836 def isup(self, node = ""):
837 '''
Jon Hall77f53ce2014-10-13 18:02:06 -0400838 Run's onos-wait-for-start which only returns once ONOS is at run
839 level 100(ready for use)
andrewonlab8d0d7d72014-10-09 16:33:15 -0400840
Jon Hall7993bfc2014-10-09 16:30:14 -0400841 Returns: main.TRUE if ONOS is running and main.FALSE on timeout
842 '''
843 try:
844 self.handle.sendline("onos-wait-for-start " + node )
845 self.handle.expect("onos-wait-for-start")
846 #NOTE: this timeout is arbitrary"
847 i = self.handle.expect(["\$", pexpect.TIMEOUT], timeout = 120)
848 if i == 0:
849 main.log.info(self.name + ": " + node + " is up")
850 return main.TRUE
851 elif i == 1:
852 #NOTE: since this function won't return until ONOS is ready,
853 # we will kill it on timeout
854 self.handle.sendline("\003") #Control-C
855 self.handle.expect("\$")
856 return main.FALSE
857 except pexpect.EOF:
858 main.log.error(self.name + ": EOF exception found")
859 main.log.error(self.name + ": " + self.handle.before)
860 main.cleanup()
861 main.exit()
862 except:
863 main.log.info(self.name+" ::::::")
864 main.log.error( traceback.print_exc())
865 main.log.info(self.name+" ::::::")
866 main.cleanup()
867 main.exit()
andrewonlab05e362f2014-10-10 00:40:57 -0400868
869
Jon Hall77f53ce2014-10-13 18:02:06 -0400870 def get_topology(self, ip):
871 '''
872 parses the onos:topology output
873 Returns: a topology dict populated by the key values found in
874 the cli command.
875 '''
876
877 try:
878 #call the cli to get the topology summary
879 cmdstr = "onos:topology"
880 cli_result = self.onos_cli(ip, cmdstr)
881
882
883 #Parse the output
884 topology = {}
885 #for line in cli_result.split("\n"):
886 for line in cli_result.splitlines():
887 if not line.startswith("time="):
888 continue
889 #else
890 print line
891 for var in line.split(","):
892 print "'"+var+"'"
893 print "'"+var.strip()+"'"
894 key, value = var.strip().split("=")
895 topology[key] = value
896 print topology
897 devices = topology.get('devices', False)
898 print devices
899 links = topology.get('links', False)
900 print links
901 clusters = topology.get('clusters', False)
902 print clusters
903 paths = topology.get('paths', False)
904 print paths
905
906 return topology
907 except pexpect.EOF:
908 main.log.error(self.name + ": EOF exception found")
909 main.log.error(self.name + ": " + self.handle.before)
910 main.cleanup()
911 main.exit()
912 except:
913 main.log.info(self.name+" ::::::")
914 main.log.error( traceback.print_exc())
915 main.log.info(self.name+" ::::::")
916 main.cleanup()
917 main.exit()
918
919 def check_status(self, ip, numoswitch, numolink, log_level="info"):
920 '''
921 Checks the number of swithes & links that ONOS sees against the
922 supplied values. By default this will report to main.log, but the
923 log level can be specifid.
924
925 Params: ip = ip used for the onos cli
926 numoswitch = expected number of switches
927 numlink = expected number of links
928 log_level = level to log to. Currently accepts 'info', 'warn' and 'report'
929
930
931 log_level can
932
933 Returns: main.TRUE if the number of switchs and links are correct,
934 main.FALSE if the numer of switches and links is incorrect,
935 and main.ERROR otherwise
936 '''
937
938 try:
939 topology = self.get_topology(ip)
940 if topology == {}:
941 return main.ERROR
942 output = ""
943 #Is the number of switches is what we expected
944 devices = topology.get('devices',False)
945 links = topology.get('links',False)
946 if devices == False or links == False:
947 return main.ERROR
948 switch_check = ( int(devices) == int(numoswitch) )
949 #Is the number of links is what we expected
950 link_check = ( int(links) == int(numolink) )
951 if (switch_check and link_check):
952 #We expected the correct numbers
953 output = output + "The number of links and switches match "\
954 + "what was expected"
955 result = main.TRUE
956 else:
957 output = output + \
958 "The number of links and switches does not match what was expected"
959 result = main.FALSE
960 output = output + "\n ONOS sees %i devices (%i expected) and %i links (%i expected)"\
961 % ( int(devices), int(numoswitch), int(links), int(numolink) )
962 if log_level == "report":
963 main.log.report(output)
964 elif log_level == "warn":
965 main.log.warn(output)
966 else:
967 main.log.info(output)
968 return result
969 except pexpect.EOF:
970 main.log.error(self.name + ": EOF exception found")
971 main.log.error(self.name + ": " + self.handle.before)
972 main.cleanup()
973 main.exit()
974 except:
975 main.log.info(self.name+" ::::::")
976 main.log.error( traceback.print_exc())
977 main.log.info(self.name+" ::::::")
978 main.cleanup()
979 main.exit()