blob: ff13e5da80b50b601efa7e6f207518896dedf889 [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
460 except pexpect.EOF:
461 main.log.error(self.name + ": EOF exception found")
462 main.log.error(self.name + ": " + self.handle.before)
463 main.cleanup()
464 main.exit()
465 except:
466 main.log.info(self.name + ":::::::::")
467 main.log.error( traceback.print_exc() )
468 main.log.info(":::::::")
469 main.cleanup()
470 main.exit()
471
andrewonlab95ca1462014-10-09 14:04:24 -0400472 def set_cell(self, cellname):
473 '''
474 Calls 'cell <name>' to set the environment variables on ONOSbench
475 '''
476 try:
477 if not cellname:
478 main.log.error("Must define cellname")
479 main.cleanup()
480 main.exit()
481 else:
482 self.handle.sendline("cell "+str(cellname))
483 #Expect the cellname in the ONOS_CELL variable.
484 #Note that this variable name is subject to change
485 # and that this driver will have to change accordingly
486 self.handle.expect("ONOS_CELL="+str(cellname))
487 handle_before = self.handle.before
488 handle_after = self.handle.after
andrewonlabc03bf6c2014-10-09 14:56:18 -0400489 #Get the rest of the handle
490 self.handle.sendline("")
491 self.handle.expect("\$")
492 handle_more = self.handle.before
andrewonlab95ca1462014-10-09 14:04:24 -0400493
494 main.log.info("Cell call returned: "+handle_before+
andrewonlabc03bf6c2014-10-09 14:56:18 -0400495 handle_after + handle_more)
andrewonlab95ca1462014-10-09 14:04:24 -0400496
497 return main.TRUE
498
499 except pexpect.EOF:
500 main.log.error(self.name + ": EOF exception found")
501 main.log.error(self.name + ": " + self.handle.before)
502 main.cleanup()
503 main.exit()
504 except:
505 main.log.info(self.name+" ::::::")
506 main.log.error( traceback.print_exc())
507 main.log.info(self.name+" ::::::")
508 main.cleanup()
509 main.exit()
510
andrewonlabc03bf6c2014-10-09 14:56:18 -0400511 def verify_cell(self):
512 '''
513 Calls 'onos-verify-cell' to check for cell installation
514 '''
andrewonlab8d0d7d72014-10-09 16:33:15 -0400515 #TODO: Add meaningful expect value
516
andrewonlabc03bf6c2014-10-09 14:56:18 -0400517 try:
518 #Clean handle by sending empty and expecting $
519 self.handle.sendline("")
520 self.handle.expect("\$")
521 self.handle.sendline("onos-verify-cell")
522 self.handle.expect("\$")
523 handle_before = self.handle.before
524 handle_after = self.handle.after
525 #Get the rest of the handle
526 self.handle.sendline("")
527 self.handle.expect("\$")
528 handle_more = self.handle.before
529
530 main.log.info("Verify cell returned: "+handle_before+
531 handle_after + handle_more)
532
533 return main.TRUE
Jon Hall7993bfc2014-10-09 16:30:14 -0400534 except pexpect.EOF:
535 main.log.error(self.name + ": EOF exception found")
536 main.log.error(self.name + ": " + self.handle.before)
537 main.cleanup()
538 main.exit()
539 except:
540 main.log.info(self.name+" ::::::")
541 main.log.error( traceback.print_exc())
542 main.log.info(self.name+" ::::::")
543 main.cleanup()
544 main.exit()
545
andrewonlab05e362f2014-10-10 00:40:57 -0400546 def onos_cli(self, ONOS_ip, cmdstr):
547 '''
548 Uses 'onos' command to send various ONOS CLI arguments.
549 Required:
550 * ONOS_ip: specify the ip of the cell machine
andrewonlab94282092014-10-10 13:00:11 -0400551 * cmdstr: specify the command string to send
andrewonlab6e20c342014-10-10 18:08:48 -0400552
553 This function is intended to expose the entire karaf
554 CLI commands for ONOS. Try to use this function first
555 before attempting to write a ONOS CLI specific driver
556 function.
557 You can see a list of available 'cmdstr' arguments
558 by starting onos, and typing in 'onos' to enter the
559 onos> CLI. Then, type 'help' to see the list of
560 available commands.
andrewonlab05e362f2014-10-10 00:40:57 -0400561 '''
562 try:
563 if not ONOS_ip:
564 main.log.error("You must specify the IP address")
565 return main.FALSE
566 if not cmdstr:
567 main.log.error("You must specify the command string")
568 return main.FALSE
569
570 cmdstr = str(cmdstr)
571 self.handle.sendline("")
572 self.handle.expect("\$")
573
574 self.handle.sendline("onos -w " + ONOS_ip + " " + cmdstr)
575 self.handle.expect("\$")
576
577 handle_before = str(self.handle.before)
578 handle_after = str(self.handle.after)
579
580 self.handle.sendline("")
581 self.handle.expect("\$")
582 handle_more = str(self.handle.before)
583
584 main.log.info("Command sent successfully")
585
andrewonlab94282092014-10-10 13:00:11 -0400586 #Obtain return handle that consists of result from
587 #the onos command. The string may need to be
588 #configured further.
andrewonlab05e362f2014-10-10 00:40:57 -0400589 return_string = handle_before + handle_after + handle_more
andrewonlab05e362f2014-10-10 00:40:57 -0400590 return return_string
591
592 except pexpect.EOF:
593 main.log.error(self.name + ": EOF exception found")
594 main.log.error(self.name + ": " + self.handle.before)
595 main.cleanup()
596 main.exit()
597 except:
598 main.log.info(self.name+" ::::::")
599 main.log.error( traceback.print_exc())
600 main.log.info(self.name+" ::::::")
601 main.cleanup()
602 main.exit()
Jon Hall7993bfc2014-10-09 16:30:14 -0400603
604 def onos_install(self, options="-f", node = ""):
605 '''
606 Installs ONOS bits on the designated cell machine.
607 If -f option is provided, it also forces an uninstall.
608 Presently, install also includes onos-push-bits and
609 onos-config within.
610 The node option allows you to selectively only push the jar
611 files to certain onos nodes
612
613 Returns: main.TRUE on success and main.FALSE on failure
614 '''
615 try:
616 self.handle.sendline("onos-install " + options + " " + node)
617 self.handle.expect("onos-install ")
618 #NOTE: this timeout may need to change depending on the network and size of ONOS
619 i=self.handle.expect(["Network\sis\sunreachable",
620 "onos\sstart/running,\sprocess",
621 pexpect.TIMEOUT],timeout=60)
622
623
624 if i == 0:
625 main.log.warn("Network is unreachable")
626 return main.FALSE
627 elif i == 1:
628 main.log.info("ONOS was installed on the VM and started")
629 return main.TRUE
630 elif i == 2:
631 main.log.info("Installation of ONOS on the VM timed out")
632 return main.FALSE
andrewonlabc03bf6c2014-10-09 14:56:18 -0400633
634 except pexpect.EOF:
635 main.log.error(self.name + ": EOF exception found")
636 main.log.error(self.name + ": " + self.handle.before)
637 main.cleanup()
638 main.exit()
639 except:
640 main.log.info(self.name+" ::::::")
641 main.log.error( traceback.print_exc())
642 main.log.info(self.name+" ::::::")
643 main.cleanup()
644 main.exit()
andrewonlab95ca1462014-10-09 14:04:24 -0400645
andrewonlab8d0d7d72014-10-09 16:33:15 -0400646 def onos_start(self, node_ip):
647 '''
648 Calls onos command: 'onos-service [<node-ip>] start'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400649 This command is a remote management of the ONOS upstart daemon
andrewonlab8d0d7d72014-10-09 16:33:15 -0400650 '''
651
652 try:
653 self.handle.sendline("")
654 self.handle.expect("\$")
655 self.handle.sendline("onos-service "+str(node_ip)+
656 " start")
657 i = self.handle.expect([
658 "Job\sis\salready\srunning",
659 "start/running",
660 "Unknown\sinstance",
661 pexpect.TIMEOUT],timeout=60)
662
663 if i == 0:
664 main.log.info("Service is already running")
665 return main.TRUE
666 elif i == 1:
667 main.log.info("ONOS service started")
668 return main.TRUE
669 else:
670 main.log.error("ONOS service failed to start")
671 main.cleanup()
672 main.exit()
andrewonlab8d0d7d72014-10-09 16:33:15 -0400673 except pexpect.EOF:
674 main.log.error(self.name + ": EOF exception found")
675 main.log.error(self.name + ": " + self.handle.before)
676 main.cleanup()
677 main.exit()
678 except:
679 main.log.info(self.name+" ::::::")
680 main.log.error( traceback.print_exc())
681 main.log.info(self.name+" ::::::")
682 main.cleanup()
683 main.exit()
684
andrewonlab2b30bd32014-10-09 16:48:55 -0400685 def onos_stop(self, node_ip):
686 '''
687 Calls onos command: 'onos-service [<node-ip>] stop'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400688 This command is a remote management of the ONOS upstart daemon
andrewonlab2b30bd32014-10-09 16:48:55 -0400689 '''
690 try:
691 self.handle.sendline("")
692 self.handle.expect("\$")
693 self.handle.sendline("onos-service "+str(node_ip)+
694 " stop")
695 i = self.handle.expect([
696 "stop/waiting",
697 "Unknown\sinstance",
698 pexpect.TIMEOUT],timeout=60)
699
700 if i == 0:
701 main.log.info("ONOS service stopped")
702 return main.TRUE
703 elif i == 1:
704 main.log.info("Unknown ONOS instance specified: "+
705 str(node_ip))
706 return main.FALSE
707 else:
708 main.log.error("ONOS service failed to stop")
709 return main.FALSE
710
711 except pexpect.EOF:
712 main.log.error(self.name + ": EOF exception found")
713 main.log.error(self.name + ": " + self.handle.before)
714 main.cleanup()
715 main.exit()
716 except:
717 main.log.info(self.name+" ::::::")
718 main.log.error( traceback.print_exc())
719 main.log.info(self.name+" ::::::")
720 main.cleanup()
721 main.exit()
722
andrewonlabc8d47972014-10-09 16:52:36 -0400723 def onos_uninstall(self):
724 '''
725 Calls the command: 'onos-uninstall'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400726 Uninstalls ONOS from the designated cell machine, stopping
727 if needed
andrewonlabc8d47972014-10-09 16:52:36 -0400728 '''
729 try:
730 self.handle.sendline("")
731 self.handle.expect("\$")
732 self.handle.sendline("onos-uninstall")
733 self.handle.expect("\$")
734
andrewonlab84727452014-10-09 18:15:36 -0400735 main.log.info("ONOS cell machine was uninstalled")
andrewonlabc8d47972014-10-09 16:52:36 -0400736 #onos-uninstall command does not return any text
737 return main.TRUE
738
739 except pexpect.EOF:
740 main.log.error(self.name + ": EOF exception found")
741 main.log.error(self.name + ": " + self.handle.before)
742 main.cleanup()
743 main.exit()
744 except:
745 main.log.info(self.name+" ::::::")
746 main.log.error( traceback.print_exc())
747 main.log.info(self.name+" ::::::")
748 main.cleanup()
749 main.exit()
andrewonlab2b30bd32014-10-09 16:48:55 -0400750
andrewonlabe8e56fd2014-10-09 17:12:44 -0400751 def onos_kill(self, node_ip):
752 '''
753 Calls the command: 'onos-kill [<node-ip>]'
754 "Remotely, and unceremoniously kills the ONOS instance running on
755 the specified cell machine" - Tom V
756 '''
757
758 try:
759 self.handle.sendline("")
760 self.handle.expect("\$")
761 self.handle.sendline("onos-kill " + str(node_ip))
762 i = self.handle.expect([
763 "\$",
764 "No\sroute\sto\shost",
765 "password:",
766 pexpect.TIMEOUT], timeout=20)
767
768 if i == 0:
769 main.log.info("ONOS instance "+str(node_ip)+" was killed")
770 return main.TRUE
771 elif i == 1:
772 main.log.info("No route to host")
773 return main.FALSE
774 elif i == 2:
775 main.log.info("Passwordless login for host: "+str(node_ip)+
776 " not configured")
777 return main.FALSE
778 else:
779 main.log.info("ONOS instasnce was not killed")
780 return main.FALSE
781
782 except pexpect.EOF:
783 main.log.error(self.name + ": EOF exception found")
784 main.log.error(self.name + ": " + self.handle.before)
785 main.cleanup()
786 main.exit()
787 except:
788 main.log.info(self.name+" ::::::")
789 main.log.error( traceback.print_exc())
790 main.log.info(self.name+" ::::::")
791 main.cleanup()
792 main.exit()
793
andrewonlab94282092014-10-10 13:00:11 -0400794 def onos_start_network(self, mntopo):
795 '''
796 Calls the command 'onos-start-network [<mininet-topo>]
797 "remotely starts the specified topology on the cell's
798 mininet machine against all controllers configured in the
799 cell."
800 * Specify mininet topology file name for mntopo
801 * Topo files should be placed at:
802 ~/<your-onos-directory>/tools/test/topos
803
804 NOTE: This function will take you to the mininet prompt
805 '''
806 try:
807 if not mntopo:
808 main.log.error("You must specify a topo file to execute")
809 return main.FALSE
810
811 mntopo = str(mntopo)
812 self.handle.sendline("")
813 self.handle.expect("\$")
814
815 self.handle.sendline("onos-start-network " + mntopo)
816 self.handle.expect("mininet>")
817 main.log.info("Network started, entered mininet prompt")
818
819 #TODO: Think about whether return is necessary or not
820
821 except pexpect.EOF:
822 main.log.error(self.name + ": EOF exception found")
823 main.log.error(self.name + ": " + self.handle.before)
824 main.cleanup()
825 main.exit()
826 except:
827 main.log.info(self.name+" ::::::")
828 main.log.error( traceback.print_exc())
829 main.log.info(self.name+" ::::::")
830 main.cleanup()
831 main.exit()
832
833
Jon Hall7993bfc2014-10-09 16:30:14 -0400834 def isup(self, node = ""):
835 '''
Jon Hall77f53ce2014-10-13 18:02:06 -0400836 Run's onos-wait-for-start which only returns once ONOS is at run
837 level 100(ready for use)
andrewonlab8d0d7d72014-10-09 16:33:15 -0400838
Jon Hall7993bfc2014-10-09 16:30:14 -0400839 Returns: main.TRUE if ONOS is running and main.FALSE on timeout
840 '''
841 try:
842 self.handle.sendline("onos-wait-for-start " + node )
843 self.handle.expect("onos-wait-for-start")
844 #NOTE: this timeout is arbitrary"
845 i = self.handle.expect(["\$", pexpect.TIMEOUT], timeout = 120)
846 if i == 0:
847 main.log.info(self.name + ": " + node + " is up")
848 return main.TRUE
849 elif i == 1:
850 #NOTE: since this function won't return until ONOS is ready,
851 # we will kill it on timeout
852 self.handle.sendline("\003") #Control-C
853 self.handle.expect("\$")
854 return main.FALSE
855 except pexpect.EOF:
856 main.log.error(self.name + ": EOF exception found")
857 main.log.error(self.name + ": " + self.handle.before)
858 main.cleanup()
859 main.exit()
860 except:
861 main.log.info(self.name+" ::::::")
862 main.log.error( traceback.print_exc())
863 main.log.info(self.name+" ::::::")
864 main.cleanup()
865 main.exit()
andrewonlab05e362f2014-10-10 00:40:57 -0400866
867
Jon Hall77f53ce2014-10-13 18:02:06 -0400868 def get_topology(self, ip):
869 '''
870 parses the onos:topology output
871 Returns: a topology dict populated by the key values found in
872 the cli command.
873 '''
874
875 try:
876 #call the cli to get the topology summary
877 cmdstr = "onos:topology"
878 cli_result = self.onos_cli(ip, cmdstr)
879
880
881 #Parse the output
882 topology = {}
883 #for line in cli_result.split("\n"):
884 for line in cli_result.splitlines():
885 if not line.startswith("time="):
886 continue
887 #else
888 print line
889 for var in line.split(","):
890 print "'"+var+"'"
891 print "'"+var.strip()+"'"
892 key, value = var.strip().split("=")
893 topology[key] = value
894 print topology
895 devices = topology.get('devices', False)
896 print devices
897 links = topology.get('links', False)
898 print links
899 clusters = topology.get('clusters', False)
900 print clusters
901 paths = topology.get('paths', False)
902 print paths
903
904 return topology
905 except pexpect.EOF:
906 main.log.error(self.name + ": EOF exception found")
907 main.log.error(self.name + ": " + self.handle.before)
908 main.cleanup()
909 main.exit()
910 except:
911 main.log.info(self.name+" ::::::")
912 main.log.error( traceback.print_exc())
913 main.log.info(self.name+" ::::::")
914 main.cleanup()
915 main.exit()
916
917 def check_status(self, ip, numoswitch, numolink, log_level="info"):
918 '''
919 Checks the number of swithes & links that ONOS sees against the
920 supplied values. By default this will report to main.log, but the
921 log level can be specifid.
922
923 Params: ip = ip used for the onos cli
924 numoswitch = expected number of switches
925 numlink = expected number of links
926 log_level = level to log to. Currently accepts 'info', 'warn' and 'report'
927
928
929 log_level can
930
931 Returns: main.TRUE if the number of switchs and links are correct,
932 main.FALSE if the numer of switches and links is incorrect,
933 and main.ERROR otherwise
934 '''
935
936 try:
937 topology = self.get_topology(ip)
938 if topology == {}:
939 return main.ERROR
940 output = ""
941 #Is the number of switches is what we expected
942 devices = topology.get('devices',False)
943 links = topology.get('links',False)
944 if devices == False or links == False:
945 return main.ERROR
946 switch_check = ( int(devices) == int(numoswitch) )
947 #Is the number of links is what we expected
948 link_check = ( int(links) == int(numolink) )
949 if (switch_check and link_check):
950 #We expected the correct numbers
951 output = output + "The number of links and switches match "\
952 + "what was expected"
953 result = main.TRUE
954 else:
955 output = output + \
956 "The number of links and switches does not match what was expected"
957 result = main.FALSE
958 output = output + "\n ONOS sees %i devices (%i expected) and %i links (%i expected)"\
959 % ( int(devices), int(numoswitch), int(links), int(numolink) )
960 if log_level == "report":
961 main.log.report(output)
962 elif log_level == "warn":
963 main.log.warn(output)
964 else:
965 main.log.info(output)
966 return result
967 except pexpect.EOF:
968 main.log.error(self.name + ": EOF exception found")
969 main.log.error(self.name + ": " + self.handle.before)
970 main.cleanup()
971 main.exit()
972 except:
973 main.log.info(self.name+" ::::::")
974 main.log.error( traceback.print_exc())
975 main.log.info(self.name+" ::::::")
976 main.cleanup()
977 main.exit()