blob: 17b74ec131ba282d4503ea3c29331237c6634749 [file] [log] [blame]
Jon Hall05b2b432014-10-08 19:53:25 -04001#!/usr/bin/env python
andrewonlabe8e56fd2014-10-09 17:12:44 -04002
Jon Hall05b2b432014-10-08 19:53:25 -04003'''
andrewonlabe8e56fd2014-10-09 17:12:44 -04004This driver interacts with ONOS bench, the OSGi platform
5that configures the ONOS nodes. (aka ONOS-next)
6
7Please follow the coding style demonstrated by existing
8functions and document properly.
9
10If you are a contributor to the driver, please
11list your email here for future contact:
12
13jhall@onlab.us
14andrew@onlab.us
15
16OCT 9 2014
17
Jon Hall05b2b432014-10-08 19:53:25 -040018'''
andrewonlabe8e56fd2014-10-09 17:12:44 -040019
andrewonlab7735d852014-10-09 13:02:47 -040020import sys
Jon Hall05b2b432014-10-08 19:53:25 -040021import time
22import pexpect
23import re
24import traceback
andrewonlab7735d852014-10-09 13:02:47 -040025import os.path
andrewonlab6e20c342014-10-10 18:08:48 -040026import pydoc
Jon Hall05b2b432014-10-08 19:53:25 -040027sys.path.append("../")
28from drivers.common.clidriver import CLI
29
30class OnosDriver(CLI):
31
32 def __init__(self):
andrewonlab6e20c342014-10-10 18:08:48 -040033 '''
34 Initialize client
35 '''
Jon Hall05b2b432014-10-08 19:53:25 -040036 super(CLI, self).__init__()
37
38 def connect(self,**connectargs):
39 '''
40 Creates ssh handle for ONOS "bench".
41 '''
42 try:
43 for key in connectargs:
44 vars(self)[key] = connectargs[key]
45 self.home = "~/ONOS"
46 for key in self.options:
47 if key == "home":
48 self.home = self.options['home']
49 break
50
51
52 self.name = self.options['name']
Jon Hallea7818b2014-10-09 14:30:59 -040053 self.handle = super(OnosDriver,self).connect(
54 user_name = self.user_name,
55 ip_address = self.ip_address,
56 port = self.port,
57 pwd = self.pwd,
58 home = self.home)
Jon Hallea7818b2014-10-09 14:30:59 -040059
60 self.handle.sendline("cd "+ self.home)
61 self.handle.expect("\$")
Jon Hall05b2b432014-10-08 19:53:25 -040062 if self.handle:
63 return self.handle
64 else :
65 main.log.info("NO ONOS HANDLE")
66 return main.FALSE
67 except pexpect.EOF:
68 main.log.error(self.name + ": EOF exception found")
69 main.log.error(self.name + ": " + self.handle.before)
70 main.cleanup()
71 main.exit()
72 except:
73 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
74 main.log.error( traceback.print_exc() )
75 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
76 main.cleanup()
77 main.exit()
78
79 def disconnect(self):
80 '''
81 Called when Test is complete to disconnect the ONOS handle.
82 '''
83 response = ''
84 try:
Jon Hallf8d10982014-10-22 12:23:38 -040085 self.handle.sendline("\n")
86 self.handle.expect("\$")
Jon Hall05b2b432014-10-08 19:53:25 -040087 self.handle.sendline("exit")
88 self.handle.expect("closed")
89 except pexpect.EOF:
90 main.log.error(self.name + ": EOF exception found")
91 main.log.error(self.name + ": " + self.handle.before)
92 except:
93 main.log.error(self.name + ": Connection failed to the host")
94 response = main.FALSE
95 return response
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -040096
97 def onos_package(self):
98 '''
99 Produce a self-contained tar.gz file that can be deployed
100 and executed on any platform with Java 7 JRE.
101 '''
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400102
103 try:
104 self.handle.sendline("onos-package")
Jon Hallea7818b2014-10-09 14:30:59 -0400105 self.handle.expect("onos-package")
andrewonlab0748d2a2014-10-09 13:24:17 -0400106 self.handle.expect("tar.gz",timeout=10)
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400107 handle = str(self.handle.before)
108 main.log.info("onos-package command returned: "+
109 handle)
andrewonlab0748d2a2014-10-09 13:24:17 -0400110 #As long as the sendline does not time out,
111 #return true. However, be careful to interpret
112 #the results of the onos-package command return
113 return main.TRUE
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400114
andrewonlab7735d852014-10-09 13:02:47 -0400115 except pexpect.EOF:
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400116 main.log.error(self.name + ": EOF exception found")
117 main.log.error(self.name + ": " + self.handle.before)
118 except:
119 main.log.error("Failed to package ONOS")
120 main.cleanup()
121 main.exit()
122
Jon Hallde9d9aa2014-10-08 20:36:02 -0400123 def clean_install(self):
124 '''
125 Runs mvn clean install in the root of the ONOS directory.
126 This will clean all ONOS artifacts then compile each module
andrew@onlab.us9e2cd0f2014-10-08 20:32:32 -0400127
Jon Hallde9d9aa2014-10-08 20:36:02 -0400128 Returns: main.TRUE on success
129 On Failure, exits the test
130 '''
131 try:
Jon Hallea7818b2014-10-09 14:30:59 -0400132 main.log.info("Running 'mvn clean install' on " + str(self.name) +
133 ". This may take some time.")
134 self.handle.sendline("cd "+ self.home)
135 self.handle.expect("\$")
136
137 self.handle.sendline("\n")
138 self.handle.expect("\$")
Jon Hallde9d9aa2014-10-08 20:36:02 -0400139 self.handle.sendline("mvn clean install")
Jon Hallea7818b2014-10-09 14:30:59 -0400140 self.handle.expect("mvn clean install")
Jon Hallde9d9aa2014-10-08 20:36:02 -0400141 while 1:
142 i=self.handle.expect([
143 'There\sis\sinsufficient\smemory\sfor\sthe\sJava\s\
144 Runtime\sEnvironment\sto\scontinue',
145 'BUILD\sFAILURE',
146 'BUILD\sSUCCESS',
147 'ONOS\$',
148 pexpect.TIMEOUT],timeout=600)
149 if i == 0:
150 main.log.error(self.name + ":There is insufficient memory \
151 for the Java Runtime Environment to continue.")
152 #return main.FALSE
153 main.cleanup()
154 main.exit()
155 if i == 1:
156 main.log.error(self.name + ": Build failure!")
157 #return main.FALSE
158 main.cleanup()
159 main.exit()
160 elif i == 2:
161 main.log.info(self.name + ": Build success!")
162 elif i == 3:
163 main.log.info(self.name + ": Build complete")
Jon Hallf8ef52c2014-10-09 19:37:33 -0400164 #Print the build time
165 for line in self.handle.before.splitlines():
166 if "Total time:" in line:
167 main.log.info(line)
Jon Hallea7818b2014-10-09 14:30:59 -0400168 self.handle.sendline("\n")
Jon Hallde9d9aa2014-10-08 20:36:02 -0400169 self.handle.expect("\$", timeout=60)
170 return main.TRUE
171 elif i == 4:
172 main.log.error(self.name + ": mvn clean install TIMEOUT!")
173 #return main.FALSE
174 main.cleanup()
175 main.exit()
176 else:
177 main.log.error(self.name + ": unexpected response from \
178 mvn clean install")
179 #return main.FALSE
180 main.cleanup()
181 main.exit()
182 except pexpect.EOF:
183 main.log.error(self.name + ": EOF exception found")
184 main.log.error(self.name + ": " + self.handle.before)
185 main.cleanup()
186 main.exit()
187 except:
188 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
189 main.log.error( traceback.print_exc() )
190 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
191 main.cleanup()
192 main.exit()
Jon Hallacabffd2014-10-09 12:36:53 -0400193
194 def git_pull(self, comp1=""):
195 '''
196 Assumes that "git pull" works without login
197
198 This function will perform a git pull on the ONOS instance.
199 If used as git_pull("NODE") it will do git pull + NODE. This is
200 for the purpose of pulling from other nodes if necessary.
201
202 Otherwise, this function will perform a git pull in the
203 ONOS repository. If it has any problems, it will return main.ERROR
204 If it successfully does a git_pull, it will return a 1.
205 If it has no updates, it will return a 0.
206
207 '''
208 try:
209 # main.log.info(self.name + ": Stopping ONOS")
210 #self.stop()
211 self.handle.sendline("cd " + self.home)
212 self.handle.expect("ONOS\$")
213 if comp1=="":
214 self.handle.sendline("git pull")
215 else:
216 self.handle.sendline("git pull " + comp1)
217
218 uptodate = 0
219 i=self.handle.expect(['fatal',
220 'Username\sfor\s(.*):\s',
221 '\sfile(s*) changed,\s',
222 'Already up-to-date',
223 'Aborting',
224 'You\sare\snot\scurrently\son\sa\sbranch',
225 'You\sasked\sme\sto\spull\swithout\stelling\sme\swhich\sbranch\syou',
226 'Pull\sis\snot\spossible\sbecause\syou\shave\sunmerged\sfiles',
227 pexpect.TIMEOUT],
228 timeout=300)
229 #debug
230 #main.log.report(self.name +": \n"+"git pull response: " + str(self.handle.before) + str(self.handle.after))
231 if i==0:
232 main.log.error(self.name + ": Git pull had some issue...")
233 return main.ERROR
234 elif i==1:
235 main.log.error(self.name + ": Git Pull Asking for username. ")
236 return main.ERROR
237 elif i==2:
238 main.log.info(self.name + ": Git Pull - pulling repository now")
239 self.handle.expect("ONOS\$", 120)
Jon Hall77f53ce2014-10-13 18:02:06 -0400240 return main.TRUE
Jon Hallacabffd2014-10-09 12:36:53 -0400241 elif i==3:
242 main.log.info(self.name + ": Git Pull - Already up to date")
Jon Hall77f53ce2014-10-13 18:02:06 -0400243 return main.TRUE
Jon Hallacabffd2014-10-09 12:36:53 -0400244 elif i==4:
245 main.log.info(self.name + ": Git Pull - Aborting... Are there conflicting git files?")
246 return main.ERROR
247 elif i==5:
248 main.log.info(self.name + ": Git Pull - You are not currently on a branch so git pull failed!")
249 return main.ERROR
250 elif i==6:
251 main.log.info(self.name + ": Git Pull - You have not configured an upstream branch to pull from. Git pull failed!")
252 return main.ERROR
253 elif i==7:
254 main.log.info(self.name + ": Git Pull - Pull is not possible because you have unmerged files.")
255 return main.ERROR
256 elif i==8:
257 main.log.error(self.name + ": Git Pull - TIMEOUT")
258 main.log.error(self.name + " Response was: " + str(self.handle.before))
259 return main.ERROR
260 else:
261 main.log.error(self.name + ": Git Pull - Unexpected response, check for pull errors")
262 return main.ERROR
263 except pexpect.EOF:
264 main.log.error(self.name + ": EOF exception found")
265 main.log.error(self.name + ": " + self.handle.before)
266 main.cleanup()
267 main.exit()
268 except:
269 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
270 main.log.error( traceback.print_exc() )
271 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
272 main.cleanup()
273 main.exit()
274
275 def git_checkout(self, branch="master"):
276 '''
277 Assumes that "git pull" works without login
278
279 This function will perform a git git checkout on the ONOS instance.
280 If used as git_checkout("branch") it will do git checkout of the "branch".
281
282 Otherwise, this function will perform a git checkout of the master
283 branch of the ONOS repository. If it has any problems, it will return
284 main.ERROR.
285 If the branch was already the specified branch, or the git checkout was
286 successful then the function will return main.TRUE.
287
288 '''
289 try:
290 # main.log.info(self.name + ": Stopping ONOS")
291 #self.stop()
292 self.handle.sendline("cd " + self.home)
293 self.handle.expect("ONOS\$")
294 if branch != 'master':
295 #self.handle.sendline('git stash')
296 #self.handle.expect('ONOS\$')
297 #print "After issuing git stash cmnd: ", self.handle.before
298 cmd = "git checkout "+branch
299 print "checkout cmd = ", cmd
300 self.handle.sendline(cmd)
301 uptodate = 0
302 i=self.handle.expect(['fatal',
303 'Username\sfor\s(.*):\s',
304 'Already\son\s\'',
305 'Switched\sto\sbranch\s\'',
306 pexpect.TIMEOUT],timeout=60)
307 else:
308 #self.handle.sendline('git stash apply')
309 #self.handle.expect('ONOS\$')
310 #print "After issuing git stash apply cmnd: ", self.handle.before
311 cmd = "git checkout "+branch
312 print "checkout cmd = ", cmd
313 self.handle.sendline(cmd)
314 uptodate = 0
315 switchedToMaster = 0
316 i=self.handle.expect(['fatal',
317 'Username\sfor\s(.*):\s',
318 'Already\son\s\'master\'',
319 'Switched\sto\sbranch\s\'master\'',
320 pexpect.TIMEOUT],timeout=60)
321
322
323 if i==0:
324 main.log.error(self.name + ": Git checkout had some issue...")
325 return main.ERROR
326 elif i==1:
327 main.log.error(self.name + ": Git checkout Asking for username!!! Bad!")
328 return main.ERROR
329 elif i==2:
330 main.log.info(self.name + ": Git Checkout %s : Already on this branch" %branch)
331 self.handle.expect("ONOS\$")
332 print "after checkout cmd = ", self.handle.before
333 switchedToMaster = 1
334 return main.TRUE
335 elif i==3:
336 main.log.info(self.name + ": Git checkout %s - Switched to this branch" %branch)
337 self.handle.expect("ONOS\$")
338 print "after checkout cmd = ", self.handle.before
339 switchedToMaster = 1
340 return main.TRUE
341 elif i==4:
342 main.log.error(self.name + ": Git Checkout- TIMEOUT")
343 main.log.error(self.name + " Response was: " + str(self.handle.before))
344 return main.ERROR
345 else:
346 main.log.error(self.name + ": Git Checkout - Unexpected response, check for pull errors")
347 return main.ERROR
348
349 except pexpect.EOF:
350 main.log.error(self.name + ": EOF exception found")
351 main.log.error(self.name + ": " + self.handle.before)
352 main.cleanup()
353 main.exit()
354 except:
355 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
356 main.log.error( traceback.print_exc() )
357 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
358 main.cleanup()
359 main.exit()
andrewonlab95ca1462014-10-09 14:04:24 -0400360
Jon Hall45ec0922014-10-10 19:33:49 -0400361 def get_version(self):
362 '''
363 Writes the COMMIT number to the report to be parsed by Jenkins data collecter.
364 '''
365 try:
366 self.handle.sendline("export TERM=xterm-256color")
367 self.handle.expect("xterm-256color")
368 self.handle.expect("\$")
369 self.handle.sendline("cd " + self.home + "; git log -1 --pretty=fuller --decorate=short | grep -A 5 \"commit\" --color=never; cd \.\.")
370 self.handle.expect("cd ..")
371 self.handle.expect("\$")
372 response=(self.name +": \n"+ str(self.handle.before + self.handle.after))
373 lines=response.splitlines()
374 for line in lines:
375 print line
376 return lines[2]
377 except pexpect.EOF:
378 main.log.error(self.name + ": EOF exception found")
379 main.log.error(self.name + ": " + self.handle.before)
380 main.cleanup()
381 main.exit()
382 except:
383 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
384 main.log.error( traceback.print_exc() )
385 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
386 main.cleanup()
387 main.exit()
388
andrewonlabba44bcf2014-10-16 16:54:41 -0400389 def create_cell_file(self, bench_ip, file_name, mn_ip_addrs,
andrewonlab3f0a4af2014-10-17 12:25:14 -0400390 extra_feature_string, *onos_ip_addrs):
andrewonlab94282092014-10-10 13:00:11 -0400391 '''
392 Creates a cell file based on arguments
393 Required:
394 * Bench IP address (bench_ip)
395 - Needed to copy the cell file over
396 * File name of the cell file (file_name)
397 * Mininet IP address (mn_ip_addrs)
398 - Note that only 1 ip address is
399 supported currently
400 * ONOS IP addresses (onos_ip_addrs)
401 - Must be passed in as last arguments
402
403 NOTE: Assumes cells are located at:
404 ~/<self.home>/tools/test/cells/
405 '''
406
407 #Variable initialization
408 cell_directory = self.home + "/tools/test/cells/"
409 #We want to create the cell file in the dependencies directory
410 #of TestON first, then copy over to ONOS bench
411 temp_directory = "/tmp/"
412 #Create the cell file in the directory for writing (w+)
413 cell_file = open(temp_directory+file_name , 'w+')
andrewonlabd4940492014-10-24 12:21:27 -0400414
415 comment = ""
416 comment_string = "#"+ comment
andrewonlab7e4d2d32014-10-15 13:23:21 -0400417 #Feature string is hardcoded environment variables
418 #That you may wish to use by default on startup.
419 #Note that you may not want certain features listed
420 #on here.
andrewonlabba44bcf2014-10-16 16:54:41 -0400421 core_feature_string = "export ONOS_FEATURES=webconsole,onos-api,"+\
422 "onos-cli,onos-openflow,onos-app-mobility,onos-app-tvue,"+\
423 "onos-app-proxyarp,"+extra_feature_string
andrewonlab94282092014-10-10 13:00:11 -0400424 mn_string = "export OCN="
425 onos_string = "export OC"
426 temp_count = 1
427
428 #Create ONOS_NIC ip address prefix
429 temp_onos_ip = onos_ip_addrs[0]
430 temp_list = []
431 temp_list = temp_onos_ip.split(".")
andrewonlab7e4d2d32014-10-15 13:23:21 -0400432 #Omit last element of list to format for NIC
andrewonlab94282092014-10-10 13:00:11 -0400433 temp_list = temp_list[:-1]
434 #Structure the nic string ip
andrewonlabd4940492014-10-24 12:21:27 -0400435 nic_addr = ".".join(temp_list) + ".*"
andrewonlab94282092014-10-10 13:00:11 -0400436 onos_nic_string = "export ONOS_NIC="+nic_addr
437
438 try:
439 #Start writing to file
andrewonlabd4940492014-10-24 12:21:27 -0400440 cell_file.write(onos_nic_string + "\n")
andrewonlab94282092014-10-10 13:00:11 -0400441
442 for arg in onos_ip_addrs:
443 #For each argument in onos_ip_addrs, write to file
444 #Output should look like the following:
andrewonlabd4940492014-10-24 12:21:27 -0400445 # export OC1="10.128.20.11"
446 # export OC2="10.128.20.12"
andrewonlab94282092014-10-10 13:00:11 -0400447 cell_file.write(onos_string + str(temp_count) +
andrewonlabd4940492014-10-24 12:21:27 -0400448 "=" + "\"" + arg + "\"" + "\n" )
andrewonlab94282092014-10-10 13:00:11 -0400449 temp_count = temp_count + 1
450
andrewonlabd4940492014-10-24 12:21:27 -0400451 cell_file.write(mn_string +"\""+ mn_ip_addrs +"\""+ "\n")
452 cell_file.write(core_feature_string + "\n")
andrewonlab94282092014-10-10 13:00:11 -0400453 cell_file.close()
454
455 #We use os.system to send the command to TestON cluster
456 #to account for the case in which TestON is not located
457 #on the same cluster as the ONOS bench
458 #Note that even if TestON is located on the same cluster
459 #as ONOS bench, you must setup passwordless ssh
andrewonlab7e4d2d32014-10-15 13:23:21 -0400460 #between TestON and ONOS bench in order to automate the test.
andrewonlab94282092014-10-10 13:00:11 -0400461 os.system("scp "+temp_directory+file_name+
462 " admin@"+bench_ip+":"+cell_directory)
463
andrewonlab2a6c9342014-10-16 13:40:15 -0400464 return main.TRUE
465
andrewonlab94282092014-10-10 13:00:11 -0400466 except pexpect.EOF:
467 main.log.error(self.name + ": EOF exception found")
468 main.log.error(self.name + ": " + self.handle.before)
469 main.cleanup()
470 main.exit()
471 except:
472 main.log.info(self.name + ":::::::::")
473 main.log.error( traceback.print_exc() )
474 main.log.info(":::::::")
475 main.cleanup()
476 main.exit()
477
andrewonlab95ca1462014-10-09 14:04:24 -0400478 def set_cell(self, cellname):
479 '''
480 Calls 'cell <name>' to set the environment variables on ONOSbench
481 '''
482 try:
483 if not cellname:
484 main.log.error("Must define cellname")
485 main.cleanup()
486 main.exit()
487 else:
488 self.handle.sendline("cell "+str(cellname))
489 #Expect the cellname in the ONOS_CELL variable.
490 #Note that this variable name is subject to change
491 # and that this driver will have to change accordingly
492 self.handle.expect("ONOS_CELL="+str(cellname))
493 handle_before = self.handle.before
494 handle_after = self.handle.after
andrewonlabc03bf6c2014-10-09 14:56:18 -0400495 #Get the rest of the handle
496 self.handle.sendline("")
497 self.handle.expect("\$")
498 handle_more = self.handle.before
andrewonlab95ca1462014-10-09 14:04:24 -0400499
500 main.log.info("Cell call returned: "+handle_before+
andrewonlabc03bf6c2014-10-09 14:56:18 -0400501 handle_after + handle_more)
andrewonlab95ca1462014-10-09 14:04:24 -0400502
503 return main.TRUE
504
505 except pexpect.EOF:
506 main.log.error(self.name + ": EOF exception found")
507 main.log.error(self.name + ": " + self.handle.before)
508 main.cleanup()
509 main.exit()
510 except:
511 main.log.info(self.name+" ::::::")
512 main.log.error( traceback.print_exc())
513 main.log.info(self.name+" ::::::")
514 main.cleanup()
515 main.exit()
516
andrewonlabc03bf6c2014-10-09 14:56:18 -0400517 def verify_cell(self):
518 '''
519 Calls 'onos-verify-cell' to check for cell installation
520 '''
andrewonlab8d0d7d72014-10-09 16:33:15 -0400521 #TODO: Add meaningful expect value
522
andrewonlabc03bf6c2014-10-09 14:56:18 -0400523 try:
524 #Clean handle by sending empty and expecting $
525 self.handle.sendline("")
526 self.handle.expect("\$")
527 self.handle.sendline("onos-verify-cell")
528 self.handle.expect("\$")
529 handle_before = self.handle.before
530 handle_after = self.handle.after
531 #Get the rest of the handle
532 self.handle.sendline("")
533 self.handle.expect("\$")
534 handle_more = self.handle.before
535
536 main.log.info("Verify cell returned: "+handle_before+
537 handle_after + handle_more)
538
539 return main.TRUE
Jon Hall7993bfc2014-10-09 16:30:14 -0400540 except pexpect.EOF:
541 main.log.error(self.name + ": EOF exception found")
542 main.log.error(self.name + ": " + self.handle.before)
543 main.cleanup()
544 main.exit()
545 except:
546 main.log.info(self.name+" ::::::")
547 main.log.error( traceback.print_exc())
548 main.log.info(self.name+" ::::::")
549 main.cleanup()
550 main.exit()
551
andrewonlab05e362f2014-10-10 00:40:57 -0400552 def onos_cli(self, ONOS_ip, cmdstr):
553 '''
554 Uses 'onos' command to send various ONOS CLI arguments.
555 Required:
556 * ONOS_ip: specify the ip of the cell machine
andrewonlab94282092014-10-10 13:00:11 -0400557 * cmdstr: specify the command string to send
andrewonlab6e20c342014-10-10 18:08:48 -0400558
559 This function is intended to expose the entire karaf
560 CLI commands for ONOS. Try to use this function first
561 before attempting to write a ONOS CLI specific driver
562 function.
563 You can see a list of available 'cmdstr' arguments
564 by starting onos, and typing in 'onos' to enter the
565 onos> CLI. Then, type 'help' to see the list of
566 available commands.
andrewonlab05e362f2014-10-10 00:40:57 -0400567 '''
568 try:
569 if not ONOS_ip:
570 main.log.error("You must specify the IP address")
571 return main.FALSE
572 if not cmdstr:
573 main.log.error("You must specify the command string")
574 return main.FALSE
575
576 cmdstr = str(cmdstr)
577 self.handle.sendline("")
578 self.handle.expect("\$")
579
580 self.handle.sendline("onos -w " + ONOS_ip + " " + cmdstr)
581 self.handle.expect("\$")
582
583 handle_before = str(self.handle.before)
584 handle_after = str(self.handle.after)
585
586 self.handle.sendline("")
587 self.handle.expect("\$")
588 handle_more = str(self.handle.before)
589
590 main.log.info("Command sent successfully")
591
andrewonlab94282092014-10-10 13:00:11 -0400592 #Obtain return handle that consists of result from
593 #the onos command. The string may need to be
594 #configured further.
andrewonlab05e362f2014-10-10 00:40:57 -0400595 return_string = handle_before + handle_after + handle_more
andrewonlab05e362f2014-10-10 00:40:57 -0400596 return return_string
597
598 except pexpect.EOF:
599 main.log.error(self.name + ": EOF exception found")
600 main.log.error(self.name + ": " + self.handle.before)
601 main.cleanup()
602 main.exit()
603 except:
604 main.log.info(self.name+" ::::::")
605 main.log.error( traceback.print_exc())
606 main.log.info(self.name+" ::::::")
607 main.cleanup()
608 main.exit()
Jon Hall7993bfc2014-10-09 16:30:14 -0400609
610 def onos_install(self, options="-f", node = ""):
611 '''
612 Installs ONOS bits on the designated cell machine.
613 If -f option is provided, it also forces an uninstall.
614 Presently, install also includes onos-push-bits and
615 onos-config within.
616 The node option allows you to selectively only push the jar
617 files to certain onos nodes
618
619 Returns: main.TRUE on success and main.FALSE on failure
620 '''
621 try:
622 self.handle.sendline("onos-install " + options + " " + node)
623 self.handle.expect("onos-install ")
624 #NOTE: this timeout may need to change depending on the network and size of ONOS
625 i=self.handle.expect(["Network\sis\sunreachable",
626 "onos\sstart/running,\sprocess",
627 pexpect.TIMEOUT],timeout=60)
628
629
630 if i == 0:
631 main.log.warn("Network is unreachable")
632 return main.FALSE
633 elif i == 1:
634 main.log.info("ONOS was installed on the VM and started")
635 return main.TRUE
636 elif i == 2:
637 main.log.info("Installation of ONOS on the VM timed out")
638 return main.FALSE
andrewonlabc03bf6c2014-10-09 14:56:18 -0400639
640 except pexpect.EOF:
641 main.log.error(self.name + ": EOF exception found")
642 main.log.error(self.name + ": " + self.handle.before)
643 main.cleanup()
644 main.exit()
645 except:
646 main.log.info(self.name+" ::::::")
647 main.log.error( traceback.print_exc())
648 main.log.info(self.name+" ::::::")
649 main.cleanup()
650 main.exit()
andrewonlab95ca1462014-10-09 14:04:24 -0400651
andrewonlab8d0d7d72014-10-09 16:33:15 -0400652 def onos_start(self, node_ip):
653 '''
654 Calls onos command: 'onos-service [<node-ip>] start'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400655 This command is a remote management of the ONOS upstart daemon
andrewonlab8d0d7d72014-10-09 16:33:15 -0400656 '''
657
658 try:
659 self.handle.sendline("")
660 self.handle.expect("\$")
661 self.handle.sendline("onos-service "+str(node_ip)+
662 " start")
663 i = self.handle.expect([
664 "Job\sis\salready\srunning",
665 "start/running",
666 "Unknown\sinstance",
Shreya Shahd01153d2014-10-23 15:08:56 -0400667 pexpect.TIMEOUT],timeout=120)
andrewonlab8d0d7d72014-10-09 16:33:15 -0400668
669 if i == 0:
670 main.log.info("Service is already running")
671 return main.TRUE
672 elif i == 1:
673 main.log.info("ONOS service started")
674 return main.TRUE
675 else:
676 main.log.error("ONOS service failed to start")
677 main.cleanup()
678 main.exit()
andrewonlab8d0d7d72014-10-09 16:33:15 -0400679 except pexpect.EOF:
680 main.log.error(self.name + ": EOF exception found")
681 main.log.error(self.name + ": " + self.handle.before)
682 main.cleanup()
683 main.exit()
684 except:
685 main.log.info(self.name+" ::::::")
686 main.log.error( traceback.print_exc())
687 main.log.info(self.name+" ::::::")
688 main.cleanup()
689 main.exit()
690
andrewonlab2b30bd32014-10-09 16:48:55 -0400691 def onos_stop(self, node_ip):
692 '''
693 Calls onos command: 'onos-service [<node-ip>] stop'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400694 This command is a remote management of the ONOS upstart daemon
andrewonlab2b30bd32014-10-09 16:48:55 -0400695 '''
696 try:
697 self.handle.sendline("")
698 self.handle.expect("\$")
699 self.handle.sendline("onos-service "+str(node_ip)+
700 " stop")
701 i = self.handle.expect([
702 "stop/waiting",
703 "Unknown\sinstance",
704 pexpect.TIMEOUT],timeout=60)
705
706 if i == 0:
707 main.log.info("ONOS service stopped")
708 return main.TRUE
709 elif i == 1:
710 main.log.info("Unknown ONOS instance specified: "+
711 str(node_ip))
712 return main.FALSE
713 else:
714 main.log.error("ONOS service failed to stop")
715 return main.FALSE
716
717 except pexpect.EOF:
718 main.log.error(self.name + ": EOF exception found")
719 main.log.error(self.name + ": " + self.handle.before)
720 main.cleanup()
721 main.exit()
722 except:
723 main.log.info(self.name+" ::::::")
724 main.log.error( traceback.print_exc())
725 main.log.info(self.name+" ::::::")
726 main.cleanup()
727 main.exit()
728
andrewonlabc8d47972014-10-09 16:52:36 -0400729 def onos_uninstall(self):
730 '''
731 Calls the command: 'onos-uninstall'
andrewonlabe8e56fd2014-10-09 17:12:44 -0400732 Uninstalls ONOS from the designated cell machine, stopping
733 if needed
andrewonlabc8d47972014-10-09 16:52:36 -0400734 '''
735 try:
736 self.handle.sendline("")
737 self.handle.expect("\$")
738 self.handle.sendline("onos-uninstall")
739 self.handle.expect("\$")
740
andrewonlab84727452014-10-09 18:15:36 -0400741 main.log.info("ONOS cell machine was uninstalled")
andrewonlabc8d47972014-10-09 16:52:36 -0400742 #onos-uninstall command does not return any text
743 return main.TRUE
744
745 except pexpect.EOF:
746 main.log.error(self.name + ": EOF exception found")
747 main.log.error(self.name + ": " + self.handle.before)
748 main.cleanup()
749 main.exit()
750 except:
751 main.log.info(self.name+" ::::::")
752 main.log.error( traceback.print_exc())
753 main.log.info(self.name+" ::::::")
754 main.cleanup()
755 main.exit()
andrewonlab2b30bd32014-10-09 16:48:55 -0400756
andrewonlabe8e56fd2014-10-09 17:12:44 -0400757 def onos_kill(self, node_ip):
758 '''
759 Calls the command: 'onos-kill [<node-ip>]'
760 "Remotely, and unceremoniously kills the ONOS instance running on
761 the specified cell machine" - Tom V
762 '''
763
764 try:
765 self.handle.sendline("")
766 self.handle.expect("\$")
767 self.handle.sendline("onos-kill " + str(node_ip))
768 i = self.handle.expect([
769 "\$",
770 "No\sroute\sto\shost",
771 "password:",
772 pexpect.TIMEOUT], timeout=20)
773
774 if i == 0:
775 main.log.info("ONOS instance "+str(node_ip)+" was killed")
776 return main.TRUE
777 elif i == 1:
778 main.log.info("No route to host")
779 return main.FALSE
780 elif i == 2:
781 main.log.info("Passwordless login for host: "+str(node_ip)+
782 " not configured")
783 return main.FALSE
784 else:
785 main.log.info("ONOS instasnce was not killed")
786 return main.FALSE
787
788 except pexpect.EOF:
789 main.log.error(self.name + ": EOF exception found")
790 main.log.error(self.name + ": " + self.handle.before)
791 main.cleanup()
792 main.exit()
793 except:
794 main.log.info(self.name+" ::::::")
795 main.log.error( traceback.print_exc())
796 main.log.info(self.name+" ::::::")
797 main.cleanup()
798 main.exit()
799
andrewonlab94282092014-10-10 13:00:11 -0400800 def onos_start_network(self, mntopo):
801 '''
802 Calls the command 'onos-start-network [<mininet-topo>]
803 "remotely starts the specified topology on the cell's
804 mininet machine against all controllers configured in the
805 cell."
806 * Specify mininet topology file name for mntopo
807 * Topo files should be placed at:
808 ~/<your-onos-directory>/tools/test/topos
809
810 NOTE: This function will take you to the mininet prompt
811 '''
812 try:
813 if not mntopo:
814 main.log.error("You must specify a topo file to execute")
815 return main.FALSE
816
817 mntopo = str(mntopo)
818 self.handle.sendline("")
819 self.handle.expect("\$")
820
821 self.handle.sendline("onos-start-network " + mntopo)
822 self.handle.expect("mininet>")
823 main.log.info("Network started, entered mininet prompt")
824
825 #TODO: Think about whether return is necessary or not
826
827 except pexpect.EOF:
828 main.log.error(self.name + ": EOF exception found")
829 main.log.error(self.name + ": " + self.handle.before)
830 main.cleanup()
831 main.exit()
832 except:
833 main.log.info(self.name+" ::::::")
834 main.log.error( traceback.print_exc())
835 main.log.info(self.name+" ::::::")
836 main.cleanup()
837 main.exit()
838
839
Jon Hall7993bfc2014-10-09 16:30:14 -0400840 def isup(self, node = ""):
841 '''
Jon Hall77f53ce2014-10-13 18:02:06 -0400842 Run's onos-wait-for-start which only returns once ONOS is at run
843 level 100(ready for use)
andrewonlab8d0d7d72014-10-09 16:33:15 -0400844
Jon Hall7993bfc2014-10-09 16:30:14 -0400845 Returns: main.TRUE if ONOS is running and main.FALSE on timeout
846 '''
847 try:
848 self.handle.sendline("onos-wait-for-start " + node )
849 self.handle.expect("onos-wait-for-start")
850 #NOTE: this timeout is arbitrary"
851 i = self.handle.expect(["\$", pexpect.TIMEOUT], timeout = 120)
852 if i == 0:
853 main.log.info(self.name + ": " + node + " is up")
854 return main.TRUE
855 elif i == 1:
856 #NOTE: since this function won't return until ONOS is ready,
857 # we will kill it on timeout
858 self.handle.sendline("\003") #Control-C
859 self.handle.expect("\$")
860 return main.FALSE
861 except pexpect.EOF:
862 main.log.error(self.name + ": EOF exception found")
863 main.log.error(self.name + ": " + self.handle.before)
864 main.cleanup()
865 main.exit()
866 except:
867 main.log.info(self.name+" ::::::")
868 main.log.error( traceback.print_exc())
869 main.log.info(self.name+" ::::::")
870 main.cleanup()
871 main.exit()
andrewonlab05e362f2014-10-10 00:40:57 -0400872
873
Jon Hall77f53ce2014-10-13 18:02:06 -0400874 def get_topology(self, ip):
875 '''
876 parses the onos:topology output
877 Returns: a topology dict populated by the key values found in
878 the cli command.
879 '''
880
881 try:
882 #call the cli to get the topology summary
883 cmdstr = "onos:topology"
884 cli_result = self.onos_cli(ip, cmdstr)
885
886
887 #Parse the output
888 topology = {}
889 #for line in cli_result.split("\n"):
890 for line in cli_result.splitlines():
891 if not line.startswith("time="):
892 continue
893 #else
894 print line
895 for var in line.split(","):
896 print "'"+var+"'"
897 print "'"+var.strip()+"'"
898 key, value = var.strip().split("=")
899 topology[key] = value
900 print topology
901 devices = topology.get('devices', False)
902 print devices
903 links = topology.get('links', False)
904 print links
905 clusters = topology.get('clusters', False)
906 print clusters
907 paths = topology.get('paths', False)
908 print paths
909
910 return topology
911 except pexpect.EOF:
912 main.log.error(self.name + ": EOF exception found")
913 main.log.error(self.name + ": " + self.handle.before)
914 main.cleanup()
915 main.exit()
916 except:
917 main.log.info(self.name+" ::::::")
918 main.log.error( traceback.print_exc())
919 main.log.info(self.name+" ::::::")
920 main.cleanup()
921 main.exit()
922
923 def check_status(self, ip, numoswitch, numolink, log_level="info"):
924 '''
925 Checks the number of swithes & links that ONOS sees against the
926 supplied values. By default this will report to main.log, but the
927 log level can be specifid.
928
929 Params: ip = ip used for the onos cli
930 numoswitch = expected number of switches
931 numlink = expected number of links
932 log_level = level to log to. Currently accepts 'info', 'warn' and 'report'
933
934
935 log_level can
936
937 Returns: main.TRUE if the number of switchs and links are correct,
938 main.FALSE if the numer of switches and links is incorrect,
939 and main.ERROR otherwise
940 '''
941
942 try:
943 topology = self.get_topology(ip)
944 if topology == {}:
945 return main.ERROR
946 output = ""
947 #Is the number of switches is what we expected
948 devices = topology.get('devices',False)
949 links = topology.get('links',False)
950 if devices == False or links == False:
951 return main.ERROR
952 switch_check = ( int(devices) == int(numoswitch) )
953 #Is the number of links is what we expected
954 link_check = ( int(links) == int(numolink) )
955 if (switch_check and link_check):
956 #We expected the correct numbers
957 output = output + "The number of links and switches match "\
958 + "what was expected"
959 result = main.TRUE
960 else:
961 output = output + \
962 "The number of links and switches does not match what was expected"
963 result = main.FALSE
964 output = output + "\n ONOS sees %i devices (%i expected) and %i links (%i expected)"\
965 % ( int(devices), int(numoswitch), int(links), int(numolink) )
966 if log_level == "report":
967 main.log.report(output)
968 elif log_level == "warn":
969 main.log.warn(output)
970 else:
971 main.log.info(output)
972 return result
973 except pexpect.EOF:
974 main.log.error(self.name + ": EOF exception found")
975 main.log.error(self.name + ": " + self.handle.before)
976 main.cleanup()
977 main.exit()
978 except:
979 main.log.info(self.name+" ::::::")
980 main.log.error( traceback.print_exc())
981 main.log.info(self.name+" ::::::")
982 main.cleanup()
983 main.exit()
andrewonlabba44bcf2014-10-16 16:54:41 -0400984
985 def tshark_grep(self, grep, directory, interface='eth0'):
986 '''
987 Required:
988 * grep string
989 * directory to store results
990 Optional:
991 * interface - default: eth0
992 Description:
993 Uses tshark command to grep specific group of packets
994 and stores the results to specified directory.
995 The timestamp is hardcoded to be in epoch
996 '''
997 self.handle.sendline("")
998 self.handle.expect("\$")
andrewonlabefd7f3d2014-10-21 16:02:31 -0400999 self.handle.sendline("")
andrewonlabba44bcf2014-10-16 16:54:41 -04001000 self.handle.sendline("tshark -i "+str(interface)+
andrewonlabd4940492014-10-24 12:21:27 -04001001 " -t e | grep --line-buffered \""+str(grep)+"\" >"+directory+" &")
andrewonlabba44bcf2014-10-16 16:54:41 -04001002 self.handle.sendline("\r")
1003 self.handle.expect("Capturing on")
1004 self.handle.sendline("\r")
1005 self.handle.expect("\$")
1006
1007 def tshark_stop(self):
1008 '''
1009 Removes wireshark files from /tmp and kills all tshark processes
1010 '''
andrewonlab5ba0d9e2014-10-24 13:32:23 -04001011 #Remove all pcap from previous captures
1012 self.execute(cmd="sudo rm /tmp/wireshark*")
andrewonlabba44bcf2014-10-16 16:54:41 -04001013 self.handle.sendline("")
1014 self.handle.sendline("sudo kill -9 `ps -ef | grep \"tshark -i\" |"+
1015 " grep -v grep | awk '{print $2}'`")
1016 self.handle.sendline("")
1017 main.log.info("Tshark stopped")
1018
1019
1020
1021