blob: 05597f5531c14a908698f0f81666d9010b5b7de3 [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
412 #Feature string is pre-defined environment variable
413 #that is required in the file
414 feature_string = "export ONOS_FEATURES=webconsole,onos-api,"+\
415 "onos-core-trivial,onos-cli,onos-openflow,"+\
416 "onos-app-fwd,onos-app-mobility,onos-app-tvue,"+\
417 "onos-app-proxyarp"
418 mn_string = "export OCN="
419 onos_string = "export OC"
420 temp_count = 1
421
422 #Create ONOS_NIC ip address prefix
423 temp_onos_ip = onos_ip_addrs[0]
424 temp_list = []
425 temp_list = temp_onos_ip.split(".")
426 #Omit last element of list
427 temp_list = temp_list[:-1]
428 #Structure the nic string ip
429 nic_addr = ".".join(temp_list) + ".*\n"
430 onos_nic_string = "export ONOS_NIC="+nic_addr
431
432 try:
433 #Start writing to file
434 cell_file.write(feature_string + "\n")
435 cell_file.write(onos_nic_string)
436 cell_file.write(mn_string +"'"+ mn_ip_addrs +"'"+ "\n")
437
438 for arg in onos_ip_addrs:
439 #For each argument in onos_ip_addrs, write to file
440 #Output should look like the following:
441 # export OC1='10.128.20.11'
442 # export OC2='10.128.20.12'
443 cell_file.write(onos_string + str(temp_count) +
444 "=" + "'" + arg + "'" + "\n" )
445 temp_count = temp_count + 1
446
447 cell_file.close()
448
449 #We use os.system to send the command to TestON cluster
450 #to account for the case in which TestON is not located
451 #on the same cluster as the ONOS bench
452 #Note that even if TestON is located on the same cluster
453 #as ONOS bench, you must setup passwordless ssh
454 #in order to automate the test.
455 os.system("scp "+temp_directory+file_name+
456 " admin@"+bench_ip+":"+cell_directory)
457
458 except pexpect.EOF:
459 main.log.error(self.name + ": EOF exception found")
460 main.log.error(self.name + ": " + self.handle.before)
461 main.cleanup()
462 main.exit()
463 except:
464 main.log.info(self.name + ":::::::::")
465 main.log.error( traceback.print_exc() )
466 main.log.info(":::::::")
467 main.cleanup()
468 main.exit()
469
andrewonlab95ca1462014-10-09 14:04:24 -0400470 def set_cell(self, cellname):
471 '''
472 Calls 'cell <name>' to set the environment variables on ONOSbench
473 '''
474 try:
475 if not cellname:
476 main.log.error("Must define cellname")
477 main.cleanup()
478 main.exit()
479 else:
480 self.handle.sendline("cell "+str(cellname))
481 #Expect the cellname in the ONOS_CELL variable.
482 #Note that this variable name is subject to change
483 # and that this driver will have to change accordingly
484 self.handle.expect("ONOS_CELL="+str(cellname))
485 handle_before = self.handle.before
486 handle_after = self.handle.after
andrewonlabc03bf6c2014-10-09 14:56:18 -0400487 #Get the rest of the handle
488 self.handle.sendline("")
489 self.handle.expect("\$")
490 handle_more = self.handle.before
andrewonlab95ca1462014-10-09 14:04:24 -0400491
492 main.log.info("Cell call returned: "+handle_before+
andrewonlabc03bf6c2014-10-09 14:56:18 -0400493 handle_after + handle_more)
andrewonlab95ca1462014-10-09 14:04:24 -0400494
495 return main.TRUE
496
497 except pexpect.EOF:
498 main.log.error(self.name + ": EOF exception found")
499 main.log.error(self.name + ": " + self.handle.before)
500 main.cleanup()
501 main.exit()
502 except:
503 main.log.info(self.name+" ::::::")
504 main.log.error( traceback.print_exc())
505 main.log.info(self.name+" ::::::")
506 main.cleanup()
507 main.exit()
508
andrewonlabc03bf6c2014-10-09 14:56:18 -0400509 def verify_cell(self):
510 '''
511 Calls 'onos-verify-cell' to check for cell installation
512 '''
andrewonlab8d0d7d72014-10-09 16:33:15 -0400513 #TODO: Add meaningful expect value
514
andrewonlabc03bf6c2014-10-09 14:56:18 -0400515 try:
516 #Clean handle by sending empty and expecting $
517 self.handle.sendline("")
518 self.handle.expect("\$")
519 self.handle.sendline("onos-verify-cell")
520 self.handle.expect("\$")
521 handle_before = self.handle.before
522 handle_after = self.handle.after
523 #Get the rest of the handle
524 self.handle.sendline("")
525 self.handle.expect("\$")
526 handle_more = self.handle.before
527
528 main.log.info("Verify cell returned: "+handle_before+
529 handle_after + handle_more)
530
531 return main.TRUE
Jon Hall7993bfc2014-10-09 16:30:14 -0400532 except pexpect.EOF:
533 main.log.error(self.name + ": EOF exception found")
534 main.log.error(self.name + ": " + self.handle.before)
535 main.cleanup()
536 main.exit()
537 except:
538 main.log.info(self.name+" ::::::")
539 main.log.error( traceback.print_exc())
540 main.log.info(self.name+" ::::::")
541 main.cleanup()
542 main.exit()
543
andrewonlab05e362f2014-10-10 00:40:57 -0400544 def onos_cli(self, ONOS_ip, cmdstr):
545 '''
546 Uses 'onos' command to send various ONOS CLI arguments.
547 Required:
548 * ONOS_ip: specify the ip of the cell machine
andrewonlab94282092014-10-10 13:00:11 -0400549 * cmdstr: specify the command string to send
andrewonlab6e20c342014-10-10 18:08:48 -0400550
551 This function is intended to expose the entire karaf
552 CLI commands for ONOS. Try to use this function first
553 before attempting to write a ONOS CLI specific driver
554 function.
555 You can see a list of available 'cmdstr' arguments
556 by starting onos, and typing in 'onos' to enter the
557 onos> CLI. Then, type 'help' to see the list of
558 available commands.
andrewonlab05e362f2014-10-10 00:40:57 -0400559 '''
560 try:
561 if not ONOS_ip:
562 main.log.error("You must specify the IP address")
563 return main.FALSE
564 if not cmdstr:
565 main.log.error("You must specify the command string")
566 return main.FALSE
567
568 cmdstr = str(cmdstr)
569 self.handle.sendline("")
570 self.handle.expect("\$")
571
572 self.handle.sendline("onos -w " + ONOS_ip + " " + cmdstr)
573 self.handle.expect("\$")
574
575 handle_before = str(self.handle.before)
576 handle_after = str(self.handle.after)
577
578 self.handle.sendline("")
579 self.handle.expect("\$")
580 handle_more = str(self.handle.before)
581
582 main.log.info("Command sent successfully")
583
andrewonlab94282092014-10-10 13:00:11 -0400584 #Obtain return handle that consists of result from
585 #the onos command. The string may need to be
586 #configured further.
andrewonlab05e362f2014-10-10 00:40:57 -0400587 return_string = handle_before + handle_after + handle_more
andrewonlab05e362f2014-10-10 00:40:57 -0400588 return return_string
589
590 except pexpect.EOF:
591 main.log.error(self.name + ": EOF exception found")
592 main.log.error(self.name + ": " + self.handle.before)
593 main.cleanup()
594 main.exit()
595 except:
596 main.log.info(self.name+" ::::::")
597 main.log.error( traceback.print_exc())
598 main.log.info(self.name+" ::::::")
599 main.cleanup()
600 main.exit()
Jon Hall7993bfc2014-10-09 16:30:14 -0400601
602 def onos_install(self, options="-f", node = ""):
603 '''
604 Installs ONOS bits on the designated cell machine.
605 If -f option is provided, it also forces an uninstall.
606 Presently, install also includes onos-push-bits and
607 onos-config within.
608 The node option allows you to selectively only push the jar
609 files to certain onos nodes
610
611 Returns: main.TRUE on success and main.FALSE on failure
612 '''
613 try:
614 self.handle.sendline("onos-install " + options + " " + node)
615 self.handle.expect("onos-install ")
616 #NOTE: this timeout may need to change depending on the network and size of ONOS
617 i=self.handle.expect(["Network\sis\sunreachable",
618 "onos\sstart/running,\sprocess",
619 pexpect.TIMEOUT],timeout=60)
620
621
622 if i == 0:
623 main.log.warn("Network is unreachable")
624 return main.FALSE
625 elif i == 1:
626 main.log.info("ONOS was installed on the VM and started")
627 return main.TRUE
628 elif i == 2:
629 main.log.info("Installation of ONOS on the VM timed out")
630 return main.FALSE
andrewonlabc03bf6c2014-10-09 14:56:18 -0400631
632 except pexpect.EOF:
633 main.log.error(self.name + ": EOF exception found")
634 main.log.error(self.name + ": " + self.handle.before)
635 main.cleanup()
636 main.exit()
637 except:
638 main.log.info(self.name+" ::::::")
639 main.log.error( traceback.print_exc())
640 main.log.info(self.name+" ::::::")
641 main.cleanup()
642 main.exit()
andrewonlab95ca1462014-10-09 14:04:24 -0400643
andrewonlab8d0d7d72014-10-09 16:33:15 -0400644 def onos_start(self, node_ip):
645 '''
646 Calls onos command: 'onos-service [<node-ip>] start'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400647 This command is a remote management of the ONOS upstart daemon
andrewonlab8d0d7d72014-10-09 16:33:15 -0400648 '''
649
650 try:
651 self.handle.sendline("")
652 self.handle.expect("\$")
653 self.handle.sendline("onos-service "+str(node_ip)+
654 " start")
655 i = self.handle.expect([
656 "Job\sis\salready\srunning",
657 "start/running",
658 "Unknown\sinstance",
659 pexpect.TIMEOUT],timeout=60)
660
661 if i == 0:
662 main.log.info("Service is already running")
663 return main.TRUE
664 elif i == 1:
665 main.log.info("ONOS service started")
666 return main.TRUE
667 else:
668 main.log.error("ONOS service failed to start")
669 main.cleanup()
670 main.exit()
andrewonlab8d0d7d72014-10-09 16:33:15 -0400671 except pexpect.EOF:
672 main.log.error(self.name + ": EOF exception found")
673 main.log.error(self.name + ": " + self.handle.before)
674 main.cleanup()
675 main.exit()
676 except:
677 main.log.info(self.name+" ::::::")
678 main.log.error( traceback.print_exc())
679 main.log.info(self.name+" ::::::")
680 main.cleanup()
681 main.exit()
682
andrewonlab2b30bd32014-10-09 16:48:55 -0400683 def onos_stop(self, node_ip):
684 '''
685 Calls onos command: 'onos-service [<node-ip>] stop'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400686 This command is a remote management of the ONOS upstart daemon
andrewonlab2b30bd32014-10-09 16:48:55 -0400687 '''
688 try:
689 self.handle.sendline("")
690 self.handle.expect("\$")
691 self.handle.sendline("onos-service "+str(node_ip)+
692 " stop")
693 i = self.handle.expect([
694 "stop/waiting",
695 "Unknown\sinstance",
696 pexpect.TIMEOUT],timeout=60)
697
698 if i == 0:
699 main.log.info("ONOS service stopped")
700 return main.TRUE
701 elif i == 1:
702 main.log.info("Unknown ONOS instance specified: "+
703 str(node_ip))
704 return main.FALSE
705 else:
706 main.log.error("ONOS service failed to stop")
707 return main.FALSE
708
709 except pexpect.EOF:
710 main.log.error(self.name + ": EOF exception found")
711 main.log.error(self.name + ": " + self.handle.before)
712 main.cleanup()
713 main.exit()
714 except:
715 main.log.info(self.name+" ::::::")
716 main.log.error( traceback.print_exc())
717 main.log.info(self.name+" ::::::")
718 main.cleanup()
719 main.exit()
720
andrewonlabc8d47972014-10-09 16:52:36 -0400721 def onos_uninstall(self):
722 '''
723 Calls the command: 'onos-uninstall'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400724 Uninstalls ONOS from the designated cell machine, stopping
725 if needed
andrewonlabc8d47972014-10-09 16:52:36 -0400726 '''
727 try:
728 self.handle.sendline("")
729 self.handle.expect("\$")
730 self.handle.sendline("onos-uninstall")
731 self.handle.expect("\$")
732
andrewonlab84727452014-10-09 18:15:36 -0400733 main.log.info("ONOS cell machine was uninstalled")
andrewonlabc8d47972014-10-09 16:52:36 -0400734 #onos-uninstall command does not return any text
735 return main.TRUE
736
737 except pexpect.EOF:
738 main.log.error(self.name + ": EOF exception found")
739 main.log.error(self.name + ": " + self.handle.before)
740 main.cleanup()
741 main.exit()
742 except:
743 main.log.info(self.name+" ::::::")
744 main.log.error( traceback.print_exc())
745 main.log.info(self.name+" ::::::")
746 main.cleanup()
747 main.exit()
andrewonlab2b30bd32014-10-09 16:48:55 -0400748
andrewonlabe8e56fd2014-10-09 17:12:44 -0400749 def onos_kill(self, node_ip):
750 '''
751 Calls the command: 'onos-kill [<node-ip>]'
752 "Remotely, and unceremoniously kills the ONOS instance running on
753 the specified cell machine" - Tom V
754 '''
755
756 try:
757 self.handle.sendline("")
758 self.handle.expect("\$")
759 self.handle.sendline("onos-kill " + str(node_ip))
760 i = self.handle.expect([
761 "\$",
762 "No\sroute\sto\shost",
763 "password:",
764 pexpect.TIMEOUT], timeout=20)
765
766 if i == 0:
767 main.log.info("ONOS instance "+str(node_ip)+" was killed")
768 return main.TRUE
769 elif i == 1:
770 main.log.info("No route to host")
771 return main.FALSE
772 elif i == 2:
773 main.log.info("Passwordless login for host: "+str(node_ip)+
774 " not configured")
775 return main.FALSE
776 else:
777 main.log.info("ONOS instasnce was not killed")
778 return main.FALSE
779
780 except pexpect.EOF:
781 main.log.error(self.name + ": EOF exception found")
782 main.log.error(self.name + ": " + self.handle.before)
783 main.cleanup()
784 main.exit()
785 except:
786 main.log.info(self.name+" ::::::")
787 main.log.error( traceback.print_exc())
788 main.log.info(self.name+" ::::::")
789 main.cleanup()
790 main.exit()
791
andrewonlab94282092014-10-10 13:00:11 -0400792 def onos_start_network(self, mntopo):
793 '''
794 Calls the command 'onos-start-network [<mininet-topo>]
795 "remotely starts the specified topology on the cell's
796 mininet machine against all controllers configured in the
797 cell."
798 * Specify mininet topology file name for mntopo
799 * Topo files should be placed at:
800 ~/<your-onos-directory>/tools/test/topos
801
802 NOTE: This function will take you to the mininet prompt
803 '''
804 try:
805 if not mntopo:
806 main.log.error("You must specify a topo file to execute")
807 return main.FALSE
808
809 mntopo = str(mntopo)
810 self.handle.sendline("")
811 self.handle.expect("\$")
812
813 self.handle.sendline("onos-start-network " + mntopo)
814 self.handle.expect("mininet>")
815 main.log.info("Network started, entered mininet prompt")
816
817 #TODO: Think about whether return is necessary or not
818
819 except pexpect.EOF:
820 main.log.error(self.name + ": EOF exception found")
821 main.log.error(self.name + ": " + self.handle.before)
822 main.cleanup()
823 main.exit()
824 except:
825 main.log.info(self.name+" ::::::")
826 main.log.error( traceback.print_exc())
827 main.log.info(self.name+" ::::::")
828 main.cleanup()
829 main.exit()
830
831
Jon Hall7993bfc2014-10-09 16:30:14 -0400832 def isup(self, node = ""):
833 '''
Jon Hall77f53ce2014-10-13 18:02:06 -0400834 Run's onos-wait-for-start which only returns once ONOS is at run
835 level 100(ready for use)
andrewonlab8d0d7d72014-10-09 16:33:15 -0400836
Jon Hall7993bfc2014-10-09 16:30:14 -0400837 Returns: main.TRUE if ONOS is running and main.FALSE on timeout
838 '''
839 try:
840 self.handle.sendline("onos-wait-for-start " + node )
841 self.handle.expect("onos-wait-for-start")
842 #NOTE: this timeout is arbitrary"
843 i = self.handle.expect(["\$", pexpect.TIMEOUT], timeout = 120)
844 if i == 0:
845 main.log.info(self.name + ": " + node + " is up")
846 return main.TRUE
847 elif i == 1:
848 #NOTE: since this function won't return until ONOS is ready,
849 # we will kill it on timeout
850 self.handle.sendline("\003") #Control-C
851 self.handle.expect("\$")
852 return main.FALSE
853 except pexpect.EOF:
854 main.log.error(self.name + ": EOF exception found")
855 main.log.error(self.name + ": " + self.handle.before)
856 main.cleanup()
857 main.exit()
858 except:
859 main.log.info(self.name+" ::::::")
860 main.log.error( traceback.print_exc())
861 main.log.info(self.name+" ::::::")
862 main.cleanup()
863 main.exit()
andrewonlab05e362f2014-10-10 00:40:57 -0400864
865
Jon Hall77f53ce2014-10-13 18:02:06 -0400866 def get_topology(self, ip):
867 '''
868 parses the onos:topology output
869 Returns: a topology dict populated by the key values found in
870 the cli command.
871 '''
872
873 try:
874 #call the cli to get the topology summary
875 cmdstr = "onos:topology"
876 cli_result = self.onos_cli(ip, cmdstr)
877
878
879 #Parse the output
880 topology = {}
881 #for line in cli_result.split("\n"):
882 for line in cli_result.splitlines():
883 if not line.startswith("time="):
884 continue
885 #else
886 print line
887 for var in line.split(","):
888 print "'"+var+"'"
889 print "'"+var.strip()+"'"
890 key, value = var.strip().split("=")
891 topology[key] = value
892 print topology
893 devices = topology.get('devices', False)
894 print devices
895 links = topology.get('links', False)
896 print links
897 clusters = topology.get('clusters', False)
898 print clusters
899 paths = topology.get('paths', False)
900 print paths
901
902 return topology
903 except pexpect.EOF:
904 main.log.error(self.name + ": EOF exception found")
905 main.log.error(self.name + ": " + self.handle.before)
906 main.cleanup()
907 main.exit()
908 except:
909 main.log.info(self.name+" ::::::")
910 main.log.error( traceback.print_exc())
911 main.log.info(self.name+" ::::::")
912 main.cleanup()
913 main.exit()
914
915 def check_status(self, ip, numoswitch, numolink, log_level="info"):
916 '''
917 Checks the number of swithes & links that ONOS sees against the
918 supplied values. By default this will report to main.log, but the
919 log level can be specifid.
920
921 Params: ip = ip used for the onos cli
922 numoswitch = expected number of switches
923 numlink = expected number of links
924 log_level = level to log to. Currently accepts 'info', 'warn' and 'report'
925
926
927 log_level can
928
929 Returns: main.TRUE if the number of switchs and links are correct,
930 main.FALSE if the numer of switches and links is incorrect,
931 and main.ERROR otherwise
932 '''
933
934 try:
935 topology = self.get_topology(ip)
936 if topology == {}:
937 return main.ERROR
938 output = ""
939 #Is the number of switches is what we expected
940 devices = topology.get('devices',False)
941 links = topology.get('links',False)
942 if devices == False or links == False:
943 return main.ERROR
944 switch_check = ( int(devices) == int(numoswitch) )
945 #Is the number of links is what we expected
946 link_check = ( int(links) == int(numolink) )
947 if (switch_check and link_check):
948 #We expected the correct numbers
949 output = output + "The number of links and switches match "\
950 + "what was expected"
951 result = main.TRUE
952 else:
953 output = output + \
954 "The number of links and switches does not match what was expected"
955 result = main.FALSE
956 output = output + "\n ONOS sees %i devices (%i expected) and %i links (%i expected)"\
957 % ( int(devices), int(numoswitch), int(links), int(numolink) )
958 if log_level == "report":
959 main.log.report(output)
960 elif log_level == "warn":
961 main.log.warn(output)
962 else:
963 main.log.info(output)
964 return result
965 except pexpect.EOF:
966 main.log.error(self.name + ": EOF exception found")
967 main.log.error(self.name + ": " + self.handle.before)
968 main.cleanup()
969 main.exit()
970 except:
971 main.log.info(self.name+" ::::::")
972 main.log.error( traceback.print_exc())
973 main.log.info(self.name+" ::::::")
974 main.cleanup()
975 main.exit()