1
2
3 """
4 This driver interacts with ONOS bench, the OSGi platform
5 that configures the ONOS nodes. ( aka ONOS-next )
6
7 Please follow the coding style demonstrated by existing
8 functions and document properly.
9
10 If you are a contributor to the driver, please
11 list your email here for future contact:
12
13 jhall@onlab.us
14 andrew@onlab.us
15
16 OCT 9 2014
17
18 """
19 import time
20 import types
21 import pexpect
22 import os
23 import os.path
24 from requests.models import Response
25 from drivers.common.clidriver import CLI
26
27
29
31 """
32 Initialize client
33 """
34 self.name = None
35 self.home = None
36 self.handle = None
37 super( CLI, self ).__init__()
38
39 - def connect( self, **connectargs ):
40 """
41 Creates ssh handle for ONOS "bench".
42 NOTE:
43 The ip_address would come from the topo file using the host tag, the
44 value can be an environment variable as well as a "localhost" to get
45 the ip address needed to ssh to the "bench"
46 """
47 try:
48 for key in connectargs:
49 vars( self )[ key ] = connectargs[ key ]
50 self.home = "~/onos"
51 for key in self.options:
52 if key == "home":
53 self.home = self.options[ 'home' ]
54 break
55 if self.home is None or self.home == "":
56 self.home = "~/onos"
57
58 self.name = self.options[ 'name' ]
59
60
61 for key in self.options:
62 if key == "nodes":
63
64 self.maxNodes = int( self.options[ 'nodes' ] )
65 break
66 self.maxNodes = None
67
68 if self.maxNodes == None or self.maxNodes == "":
69 self.maxNodes = 100
70
71
72
73 self.onosIps = {}
74
75 try:
76 if self.maxNodes:
77 for i in range( self.maxNodes ):
78 envString = "OC" + str( i + 1 )
79
80 if os.getenv( envString ):
81 self.onosIps[ envString ] = os.getenv( envString )
82 else:
83 self.maxNodes = len( self.onosIps )
84 main.log.info( self.name +
85 ": Created cluster data with " +
86 str( self.maxNodes ) +
87 " maximum number" +
88 " of nodes" )
89 break
90
91 if not self.onosIps:
92 main.log.info( "Could not read any environment variable"
93 + " please load a cell file with all" +
94 " onos IP" )
95 self.maxNodes = None
96 else:
97 main.log.info( self.name + ": Found " +
98 str( self.onosIps.values() ) +
99 " ONOS IPs" )
100 except KeyError:
101 main.log.info( "Invalid environment variable" )
102 except Exception as inst:
103 main.log.error( "Uncaught exception: " + str( inst ) )
104
105 try:
106 if os.getenv( str( self.ip_address ) ) != None:
107 self.ip_address = os.getenv( str( self.ip_address ) )
108 else:
109 main.log.info( self.name +
110 ": Trying to connect to " +
111 self.ip_address )
112 except KeyError:
113 main.log.info( "Invalid host name," +
114 " connecting to local host instead" )
115 self.ip_address = 'localhost'
116 except Exception as inst:
117 main.log.error( "Uncaught exception: " + str( inst ) )
118
119 self.handle = super( OnosDriver, self ).connect(
120 user_name=self.user_name,
121 ip_address=self.ip_address,
122 port=self.port,
123 pwd=self.pwd,
124 home=self.home )
125
126 if self.handle:
127 self.handle.sendline( "cd " + self.home )
128 self.handle.expect( "\$" )
129 return self.handle
130 else:
131 main.log.info( "Failed to create ONOS handle" )
132 return main.FALSE
133 except pexpect.EOF:
134 main.log.error( self.name + ": EOF exception found" )
135 main.log.error( self.name + ": " + self.handle.before )
136 main.cleanup()
137 main.exit()
138 except Exception:
139 main.log.exception( self.name + ": Uncaught exception!" )
140 main.cleanup()
141 main.exit()
142
144 """
145 Called when Test is complete to disconnect the ONOS handle.
146 """
147 response = main.TRUE
148 try:
149 if self.handle:
150 self.handle.sendline( "" )
151 self.handle.expect( "\$" )
152 self.handle.sendline( "exit" )
153 self.handle.expect( "closed" )
154 except pexpect.EOF:
155 main.log.error( self.name + ": EOF exception found" )
156 main.log.error( self.name + ": " + self.handle.before )
157 except ValueError:
158 main.log.exception( "Exception in disconnect of " + self.name )
159 response = main.TRUE
160 except Exception:
161 main.log.exception( self.name + ": Connection failed to the host" )
162 response = main.FALSE
163 return response
164
166 """
167 Returns milliseconds since epoch
168
169 When checking multiple nodes in a for loop,
170 around a hundred milliseconds of difference (ascending) is
171 generally acceptable due to calltime of the function.
172 Few seconds, however, is not and it means clocks
173 are off sync.
174 """
175 try:
176 self.handle.sendline( 'date +%s.%N' )
177 self.handle.expect( 'date \+\%s\.\%N' )
178 self.handle.expect( '\$' )
179 epochMs = self.handle.before
180 return epochMs
181 except Exception:
182 main.log.exception( 'Uncaught exception getting epoch time' )
183 main.cleanup()
184 main.exit()
185
187 """
188 Produce a self-contained tar.gz file that can be deployed
189 and executed on any platform with Java 7 JRE.
190 """
191 try:
192 self.handle.sendline( "onos-package" )
193 self.handle.expect( "onos-package" )
194 self.handle.expect( "tar.gz", opTimeout )
195 handle = str( self.handle.before )
196 main.log.info( "onos-package command returned: " +
197 handle )
198
199
200
201 return main.TRUE
202
203 except pexpect.EOF:
204 main.log.error( self.name + ": EOF exception found" )
205 main.log.error( self.name + ": " + self.handle.before )
206 except Exception:
207 main.log.exception( "Failed to package ONOS" )
208 main.cleanup()
209 main.exit()
210
212 """
213 Use the pre defined script to build onos via mvn
214 """
215 try:
216 self.handle.sendline( "onos-build" )
217 self.handle.expect( "onos-build" )
218 i = self.handle.expect( [
219 "BUILD SUCCESS",
220 "ERROR",
221 "BUILD FAILED" ],
222 timeout=120 )
223 handle = str( self.handle.before )
224
225 main.log.info( "onos-build command returned: " +
226 handle )
227
228 if i == 0:
229 return main.TRUE
230 else:
231 return handle
232
233 except pexpect.EOF:
234 main.log.error( self.name + ": EOF exception found" )
235 main.log.error( self.name + ": " + self.handle.before )
236 except Exception:
237 main.log.exception( "Failed to build ONOS" )
238 main.cleanup()
239 main.exit()
240
242 """
243 Runs mvn clean install in the root of the ONOS directory.
244 This will clean all ONOS artifacts then compile each module
245 Optional:
246 skipTest - Does "-DskipTests -Dcheckstyle.skip -U -T 1C" which
247 skip the test. This will make the building faster.
248 Disregarding the credibility of the build
249 Returns: main.TRUE on success
250 On Failure, exits the test
251 """
252 try:
253 main.log.info( "Running 'mvn clean install' on " +
254 str( self.name ) +
255 ". This may take some time." )
256 self.handle.sendline( "cd " + self.home )
257 self.handle.expect( "\$" )
258
259 self.handle.sendline( "" )
260 self.handle.expect( "\$" )
261
262 if not skipTest:
263 self.handle.sendline( "mvn clean install" )
264 self.handle.expect( "mvn clean install" )
265 else:
266 self.handle.sendline( "mvn clean install -DskipTests" +
267 " -Dcheckstyle.skip -U -T 1C" )
268 self.handle.expect( "mvn clean install -DskipTests" +
269 " -Dcheckstyle.skip -U -T 1C" )
270 while True:
271 i = self.handle.expect( [
272 'There\sis\sinsufficient\smemory\sfor\sthe\sJava\s' +
273 'Runtime\sEnvironment\sto\scontinue',
274 'BUILD\sFAILURE',
275 'BUILD\sSUCCESS',
276 'onos\$',
277 'ONOS\$',
278 pexpect.TIMEOUT ], mciTimeout )
279 if i == 0:
280 main.log.error( self.name + ":There is insufficient memory \
281 for the Java Runtime Environment to continue." )
282
283 main.cleanup()
284 main.exit()
285 if i == 1:
286 main.log.error( self.name + ": Build failure!" )
287
288 main.cleanup()
289 main.exit()
290 elif i == 2:
291 main.log.info( self.name + ": Build success!" )
292 elif i == 3 or i == 4:
293 main.log.info( self.name + ": Build complete" )
294
295 for line in self.handle.before.splitlines():
296 if "Total time:" in line:
297 main.log.info( line )
298 self.handle.sendline( "" )
299 self.handle.expect( "\$", timeout=60 )
300 return main.TRUE
301 elif i == 5:
302 main.log.error(
303 self.name +
304 ": mvn clean install TIMEOUT!" )
305
306 main.cleanup()
307 main.exit()
308 else:
309 main.log.error( self.name + ": unexpected response from " +
310 "mvn clean install" )
311
312 main.cleanup()
313 main.exit()
314 except pexpect.EOF:
315 main.log.error( self.name + ": EOF exception found" )
316 main.log.error( self.name + ": " + self.handle.before )
317 main.cleanup()
318 main.exit()
319 except Exception:
320 main.log.exception( self.name + ": Uncaught exception!" )
321 main.cleanup()
322 main.exit()
323
324 - def gitPull( self, comp1="", fastForward=True ):
325 """
326 Assumes that "git pull" works without login
327
328 If the fastForward boolean is set to true, only git pulls that can
329 be fast forwarded will be performed. IE if you have not local commits
330 in your branch.
331
332 This function will perform a git pull on the ONOS instance.
333 If used as gitPull( "NODE" ) it will do git pull + NODE. This is
334 for the purpose of pulling from other nodes if necessary.
335
336 Otherwise, this function will perform a git pull in the
337 ONOS repository. If it has any problems, it will return main.ERROR
338 If it successfully does a gitPull, it will return a 1 ( main.TRUE )
339 If it has no updates, it will return 3.
340
341 """
342 try:
343
344
345 self.handle.sendline( "cd " + self.home )
346 self.handle.expect( self.home + "\$" )
347 cmd = "git pull"
348 if comp1 != "":
349 cmd += ' ' + comp1
350 if fastForward:
351 cmd += ' ' + " --ff-only"
352 self.handle.sendline( cmd )
353 i = self.handle.expect(
354 [
355 'fatal',
356 'Username\sfor\s(.*):\s',
357 '\sfile(s*) changed,\s',
358 'Already up-to-date',
359 'Aborting',
360 'You\sare\snot\scurrently\son\sa\sbranch',
361 'You asked me to pull without telling me which branch you',
362 'Pull is not possible because you have unmerged files',
363 'Please enter a commit message to explain why this merge',
364 'Found a swap file by the name',
365 'Please, commit your changes before you can merge.',
366 pexpect.TIMEOUT ],
367 timeout=300 )
368
369
370
371
372 if i == 0:
373 main.log.error( self.name + ": Git pull had some issue" )
374 output = self.handle.after
375 self.handle.expect( '\$' )
376 output += self.handle.before
377 main.log.warn( output )
378 return main.ERROR
379 elif i == 1:
380 main.log.error(
381 self.name +
382 ": Git Pull Asking for username. " )
383 return main.ERROR
384 elif i == 2:
385 main.log.info(
386 self.name +
387 ": Git Pull - pulling repository now" )
388 self.handle.expect( self.home + "\$", 120 )
389
390 return main.TRUE
391 elif i == 3:
392 main.log.info( self.name + ": Git Pull - Already up to date" )
393 return i
394 elif i == 4:
395 main.log.info(
396 self.name +
397 ": Git Pull - Aborting..." +
398 "Are there conflicting git files?" )
399 return main.ERROR
400 elif i == 5:
401 main.log.info(
402 self.name +
403 ": Git Pull - You are not currently " +
404 "on a branch so git pull failed!" )
405 return main.ERROR
406 elif i == 6:
407 main.log.info(
408 self.name +
409 ": Git Pull - You have not configured an upstream " +
410 "branch to pull from. Git pull failed!" )
411 return main.ERROR
412 elif i == 7:
413 main.log.info(
414 self.name +
415 ": Git Pull - Pull is not possible because " +
416 "you have unmerged files." )
417 return main.ERROR
418 elif i == 8:
419
420
421
422 main.log.error( "Git pull resulted in a merge commit message" +
423 ". Exiting test!" )
424 main.cleanup()
425 main.exit()
426 elif i == 9:
427 main.log.error( "Git pull resulted in a merge commit message" +
428 " but a swap file exists." )
429 try:
430 self.handle.send( 'A' )
431 self.handle.expect( "\$" )
432 return main.ERROR
433 except Exception:
434 main.log.exception( "Couldn't exit editor prompt!")
435 main.cleanup()
436 main.exit()
437 elif i == 10:
438 main.log.error( "Git branch is in the middle of a merge. " )
439 main.log.warn( self.handle.before + self.handle.after )
440 return main.ERROR
441 elif i == 11:
442 main.log.error( self.name + ": Git Pull - TIMEOUT" )
443 main.log.error(
444 self.name + " Response was: " + str(
445 self.handle.before ) )
446 return main.ERROR
447 else:
448 main.log.error(
449 self.name +
450 ": Git Pull - Unexpected response, check for pull errors" )
451 return main.ERROR
452 except pexpect.EOF:
453 main.log.error( self.name + ": EOF exception found" )
454 main.log.error( self.name + ": " + self.handle.before )
455 main.cleanup()
456 main.exit()
457 except Exception:
458 main.log.exception( self.name + ": Uncaught exception!" )
459 main.cleanup()
460 main.exit()
461
463 """
464 Assumes that "git pull" works without login
465
466 This function will perform a git git checkout on the ONOS instance.
467 If used as gitCheckout( "branch" ) it will do git checkout
468 of the "branch".
469
470 Otherwise, this function will perform a git checkout of the master
471 branch of the ONOS repository. If it has any problems, it will return
472 main.ERROR.
473 If the branch was already the specified branch, or the git checkout was
474 successful then the function will return main.TRUE.
475
476 """
477 try:
478 self.handle.sendline( "cd " + self.home )
479 self.handle.expect( self.home + "\$" )
480 main.log.info( self.name +
481 ": Checking out git branch/ref: " + branch + "..." )
482 cmd = "git checkout " + branch
483 self.handle.sendline( cmd )
484 self.handle.expect( cmd )
485 i = self.handle.expect(
486 [ 'fatal',
487 'Username for (.*): ',
488 'Already on \'',
489 'Switched to (a new )?branch \'' + str( branch ),
490 pexpect.TIMEOUT,
491 'error: Your local changes to the following files' +
492 'would be overwritten by checkout:',
493 'error: you need to resolve your current index first',
494 "You are in 'detached HEAD' state.",
495 "HEAD is now at " ],
496 timeout=60 )
497 if i == 0:
498 main.log.error(
499 self.name +
500 ": Git checkout had some issue..." )
501 main.log.error( self.name + ": " + self.handle.before )
502 return main.ERROR
503 elif i == 1:
504 main.log.error(
505 self.name +
506 ": Git checkout asking for username." +
507 " Please configure your local git repository to be able " +
508 "to access your remote repository passwordlessly" )
509
510 return main.ERROR
511 elif i == 2:
512 main.log.info(
513 self.name +
514 ": Git Checkout %s : Already on this branch" % branch )
515 self.handle.expect( self.home + "\$" )
516
517
518 return main.TRUE
519 elif i == 3:
520 main.log.info(
521 self.name +
522 ": Git checkout %s - Switched to this branch" % branch )
523 self.handle.expect( self.home + "\$" )
524
525
526 return main.TRUE
527 elif i == 4:
528 main.log.error( self.name + ": Git Checkout- TIMEOUT" )
529 main.log.error(
530 self.name + " Response was: " + str( self.handle.before ) )
531 return main.ERROR
532 elif i == 5:
533 self.handle.expect( "Aborting" )
534 main.log.error(
535 self.name +
536 ": Git checkout error: \n" +
537 "Your local changes to the following files would" +
538 " be overwritten by checkout:" +
539 str( self.handle.before ) )
540 self.handle.expect( self.home + "\$" )
541 return main.ERROR
542 elif i == 6:
543 main.log.error(
544 self.name +
545 ": Git checkout error: \n" +
546 "You need to resolve your current index first:" +
547 str( self.handle.before ) )
548 self.handle.expect( self.home + "\$" )
549 return main.ERROR
550 elif i == 7:
551 main.log.info(
552 self.name +
553 ": Git checkout " + str( branch ) +
554 " - You are in 'detached HEAD' state. HEAD is now at " +
555 str( branch ) )
556 self.handle.expect( self.home + "\$" )
557 return main.TRUE
558 elif i == 8:
559 main.log.info(
560 self.name +
561 ": Git Checkout %s : Already on commit" % branch )
562 self.handle.expect( self.home + "\$" )
563 return main.TRUE
564 else:
565 main.log.error(
566 self.name +
567 ": Git Checkout - Unexpected response, " +
568 "check for pull errors" )
569 main.log.error( self.name + ": " + self.handle.before )
570 return main.ERROR
571
572 except pexpect.EOF:
573 main.log.error( self.name + ": EOF exception found" )
574 main.log.error( self.name + ": " + self.handle.before )
575 main.cleanup()
576 main.exit()
577 except Exception:
578 main.log.exception( self.name + ": Uncaught exception!" )
579 main.cleanup()
580 main.exit()
581
583 main.log.info( "self.home = " )
584 main.log.info( self.home )
585 self.handle.sendline( "cd " + self.home )
586 self.handle.expect( self.home + "\$" )
587 self.handle.sendline( "git name-rev --name-only HEAD" )
588 self.handle.expect( "git name-rev --name-only HEAD" )
589 self.handle.expect( "\$" )
590
591 lines = self.handle.before.splitlines()
592 if lines[1] == "master":
593 return "master"
594 elif lines[1] == "onos-1.0":
595 return "onos-1.0"
596 else:
597 main.log.info( lines[1] )
598 return "unexpected ONOS branch for SDN-IP test"
599
601 """
602 Writes the COMMIT number to the report to be parsed
603 by Jenkins data collector.
604 """
605 try:
606 self.handle.sendline( "" )
607 self.handle.expect( "\$" )
608 self.handle.sendline(
609 "cd " +
610 self.home +
611 "; git log -1 --pretty=fuller --decorate=short | grep -A 6 " +
612 " \"commit\" --color=never" )
613
614
615 self.handle.expect( "never" )
616 self.handle.expect( "\$" )
617 response = ( self.name + ": \n" + str(
618 self.handle.before + self.handle.after ) )
619 self.handle.sendline( "cd " + self.home )
620 self.handle.expect( "\$" )
621 lines = response.splitlines()
622 for line in lines:
623 print line
624 if report:
625 main.log.wiki( "<blockquote>" )
626 for line in lines[ 2:-1 ]:
627
628
629
630 line = line.replace( "<", "[" )
631 line = line.replace( ">", "]" )
632
633 main.log.wiki( line + "<br /> " )
634 main.log.summary( line )
635 main.log.wiki( "</blockquote>" )
636 main.log.summary("\n")
637 return lines[ 2 ]
638 except pexpect.EOF:
639 main.log.error( self.name + ": EOF exception found" )
640 main.log.error( self.name + ": " + self.handle.before )
641 main.cleanup()
642 main.exit()
643 except pexpect.TIMEOUT:
644 main.log.error( self.name + ": TIMEOUT exception found" )
645 main.log.error( self.name + ": " + self.handle.before )
646 main.cleanup()
647 main.exit()
648 except Exception:
649 main.log.exception( self.name + ": Uncaught exception!" )
650 main.cleanup()
651 main.exit()
652
653 - def createCellFile( self, benchIp, fileName, mnIpAddrs,
654 appString, onosIpAddrs ):
655 """
656 Creates a cell file based on arguments
657 Required:
658 * Bench IP address ( benchIp )
659 - Needed to copy the cell file over
660 * File name of the cell file ( fileName )
661 * Mininet IP address ( mnIpAddrs )
662 - Note that only 1 ip address is
663 supported currently
664 * ONOS IP addresses ( onosIpAddrs )
665 - Must be passed in as last arguments
666
667 NOTE: Assumes cells are located at:
668 ~/<self.home>/tools/test/cells/
669 """
670
671 cellDirectory = self.home + "/tools/test/cells/"
672
673
674 tempDirectory = "/tmp/"
675
676 cellFile = open( tempDirectory + fileName, 'w+' )
677 if isinstance( onosIpAddrs, types.StringType ):
678 onosIpAddrs = [ onosIpAddrs ]
679
680
681
682
683
684 appString = "export ONOS_APPS=" + appString
685 mnString = "export OCN="
686 if mnIpAddrs == "":
687 mnString = ""
688 onosString = "export OC"
689 tempCount = 1
690
691
692 tempOnosIp = str( onosIpAddrs[ 0 ] )
693 tempList = []
694 tempList = tempOnosIp.split( "." )
695
696 tempList = tempList[ :-1 ]
697
698 nicAddr = ".".join( tempList ) + ".*"
699 onosNicString = "export ONOS_NIC=" + nicAddr
700
701 try:
702
703 cellFile.write( onosNicString + "\n" )
704
705 for arg in onosIpAddrs:
706
707
708
709
710 cellFile.write( onosString + str( tempCount ) +
711 "=" + "\"" + arg + "\"" + "\n" )
712 tempCount = tempCount + 1
713
714 cellFile.write( mnString + "\"" + mnIpAddrs + "\"" + "\n" )
715 cellFile.write( appString + "\n" )
716 cellFile.close()
717
718
719
720
721
722
723
724 os.system( "scp " + tempDirectory + fileName + " " +
725 self.user_name + "@" + self.ip_address + ":" + cellDirectory )
726
727 return main.TRUE
728
729 except pexpect.EOF:
730 main.log.error( self.name + ": EOF exception found" )
731 main.log.error( self.name + ": " + self.handle.before )
732 main.cleanup()
733 main.exit()
734 except Exception:
735 main.log.exception( self.name + ": Uncaught exception!" )
736 main.cleanup()
737 main.exit()
738
740 """
741 Calls 'cell <name>' to set the environment variables on ONOSbench
742 """
743 import re
744 try:
745 if not cellname:
746 main.log.error( "Must define cellname" )
747 main.cleanup()
748 main.exit()
749 else:
750 self.handle.sendline( "cell " + str( cellname ) )
751
752
753
754 self.handle.expect(str(cellname))
755 handleBefore = self.handle.before
756 handleAfter = self.handle.after
757
758 self.handle.sendline("")
759 self.handle.expect("\$")
760 handleMore = self.handle.before
761
762 cell_result = handleBefore + handleAfter + handleMore
763 print cell_result
764 if( re.search( "No such cell", cell_result ) ):
765 main.log.error( "Cell call returned: " + handleBefore +
766 handleAfter + handleMore )
767 main.cleanup()
768 main.exit()
769 return main.TRUE
770
771 except pexpect.EOF:
772 main.log.error( self.name + ": EOF exception found" )
773 main.log.error( self.name + ": " + self.handle.before )
774 main.cleanup()
775 main.exit()
776 except Exception:
777 main.log.exception( self.name + ": Uncaught exception!" )
778 main.cleanup()
779 main.exit()
780
782 """
783 Calls 'onos-verify-cell' to check for cell installation
784 """
785
786
787 try:
788
789 self.handle.sendline( "" )
790 self.handle.expect( "\$" )
791 self.handle.sendline( "onos-verify-cell" )
792 self.handle.expect( "\$" )
793 handleBefore = self.handle.before
794 handleAfter = self.handle.after
795
796 self.handle.sendline( "" )
797 self.handle.expect( "\$" )
798 handleMore = self.handle.before
799
800 main.log.info( "Verify cell returned: " + handleBefore +
801 handleAfter + handleMore )
802
803 return main.TRUE
804 except pexpect.ExceptionPexpect as e:
805 main.log.error( self.name + ": Pexpect exception found of type " +
806 str( type( e ) ) )
807 main.log.error ( e.get_trace() )
808 main.log.error( self.name + ": " + self.handle.before )
809 main.cleanup()
810 main.exit()
811 except Exception:
812 main.log.exception( self.name + ": Uncaught exception!" )
813 main.cleanup()
814 main.exit()
815
816 - def onosCfgSet( self, ONOSIp, configName, configParam ):
817 """
818 Uses 'onos <node-ip> cfg set' to change a parameter value of an
819 application.
820
821 ex)
822 onos 10.0.0.1 cfg set org.onosproject.myapp appSetting 1
823 ONOSIp = '10.0.0.1'
824 configName = 'org.onosproject.myapp'
825 configParam = 'appSetting 1'
826 """
827 for i in range(5):
828 try:
829 cfgStr = ( "onos "+str(ONOSIp)+" cfg set "+
830 str(configName) + " " +
831 str(configParam)
832 )
833
834 self.handle.sendline( "" )
835 self.handle.expect( ":~" )
836 self.handle.sendline( cfgStr )
837 self.handle.expect("cfg set")
838 self.handle.expect( ":~" )
839
840 paramValue = configParam.split(" ")[1]
841 paramName = configParam.split(" ")[0]
842
843 checkStr = ( "onos " + str(ONOSIp) + """ cfg get " """ + str(configName) + " " + paramName + """ " """)
844
845 self.handle.sendline( checkStr )
846 self.handle.expect( ":~" )
847
848 if "value=" + paramValue + "," in self.handle.before:
849 main.log.info("cfg " + configName + " successfully set to " + configParam)
850 return main.TRUE
851
852 except pexpect.ExceptionPexpect as e:
853 main.log.error( self.name + ": Pexpect exception found of type " +
854 str( type( e ) ) )
855 main.log.error ( e.get_trace() )
856 main.log.error( self.name + ": " + self.handle.before )
857 main.cleanup()
858 main.exit()
859 except Exception:
860 main.log.exception( self.name + ": Uncaught exception!" )
861 main.cleanup()
862 main.exit()
863
864 time.sleep(5)
865
866 main.log.error("CFG SET FAILURE: " + configName + " " + configParam )
867 main.ONOSbench.handle.sendline("onos $OC1 cfg get")
868 main.ONOSbench.handle.expect("\$")
869 print main.ONOSbench.handle.before
870 main.ONOSbench.logReport( ONOSIp, ["ERROR","WARN","EXCEPT"], "d")
871 return main.FALSE
872
873
874 - def onosCli( self, ONOSIp, cmdstr ):
875 """
876 Uses 'onos' command to send various ONOS CLI arguments.
877 Required:
878 * ONOSIp: specify the ip of the cell machine
879 * cmdstr: specify the command string to send
880
881 This function is intended to expose the entire karaf
882 CLI commands for ONOS. Try to use this function first
883 before attempting to write a ONOS CLI specific driver
884 function.
885 You can see a list of available 'cmdstr' arguments
886 by starting onos, and typing in 'onos' to enter the
887 onos> CLI. Then, type 'help' to see the list of
888 available commands.
889 """
890 try:
891 if not ONOSIp:
892 main.log.error( "You must specify the IP address" )
893 return main.FALSE
894 if not cmdstr:
895 main.log.error( "You must specify the command string" )
896 return main.FALSE
897
898 cmdstr = str( cmdstr )
899 self.handle.sendline( "" )
900 self.handle.expect( "\$" )
901
902 self.handle.sendline( "onos -w " + ONOSIp + " " + cmdstr )
903 self.handle.expect( "\$" )
904
905 handleBefore = self.handle.before
906 print "handle_before = ", self.handle.before
907
908
909
910
911
912
913 main.log.info( "Command sent successfully" )
914
915
916
917
918
919 returnString = handleBefore
920 print "return_string = ", returnString
921 return returnString
922
923 except pexpect.EOF:
924 main.log.error( self.name + ": EOF exception found" )
925 main.log.error( self.name + ": " + self.handle.before )
926 main.cleanup()
927 main.exit()
928 except Exception:
929 main.log.exception( self.name + ": Uncaught exception!" )
930 main.cleanup()
931 main.exit()
932
934 """
935 Installs ONOS bits on the designated cell machine.
936 If -f option is provided, it also forces an uninstall.
937 Presently, install also includes onos-push-bits and
938 onos-config within.
939 The node option allows you to selectively only push the jar
940 files to certain onos nodes
941
942 Returns: main.TRUE on success and main.FALSE on failure
943 """
944 try:
945 if options:
946 self.handle.sendline( "onos-install " + options + " " + node )
947 else:
948 self.handle.sendline( "onos-install " + node )
949 self.handle.expect( "onos-install " )
950
951
952 i = self.handle.expect( [ "Network\sis\sunreachable",
953 "onos\sstart/running,\sprocess",
954 "ONOS\sis\salready\sinstalled",
955 pexpect.TIMEOUT ], timeout=60 )
956
957 if i == 0:
958 main.log.warn( "Network is unreachable" )
959 return main.FALSE
960 elif i == 1:
961 main.log.info(
962 "ONOS was installed on " +
963 node +
964 " and started" )
965 return main.TRUE
966 elif i == 2:
967 main.log.info( "ONOS is already installed on " + node )
968 return main.TRUE
969 elif i == 3:
970 main.log.info(
971 "Installation of ONOS on " +
972 node +
973 " timed out" )
974 return main.FALSE
975
976 except pexpect.EOF:
977 main.log.error( self.name + ": EOF exception found" )
978 main.log.error( self.name + ": " + self.handle.before )
979 main.cleanup()
980 main.exit()
981 except Exception:
982 main.log.exception( self.name + ": Uncaught exception!" )
983 main.cleanup()
984 main.exit()
985
987 """
988 Calls onos command: 'onos-service [<node-ip>] start'
989 This command is a remote management of the ONOS upstart daemon
990 """
991 try:
992 self.handle.sendline( "" )
993 self.handle.expect( "\$" )
994 self.handle.sendline( "onos-service " + str( nodeIp ) +
995 " start" )
996 i = self.handle.expect( [
997 "Job\sis\salready\srunning",
998 "start/running",
999 "Unknown\sinstance",
1000 pexpect.TIMEOUT ], timeout=120 )
1001
1002 if i == 0:
1003 main.log.info( "Service is already running" )
1004 return main.TRUE
1005 elif i == 1:
1006 main.log.info( "ONOS service started" )
1007 return main.TRUE
1008 else:
1009 main.log.error( "ONOS service failed to start" )
1010 main.cleanup()
1011 main.exit()
1012 except pexpect.EOF:
1013 main.log.error( self.name + ": EOF exception found" )
1014 main.log.error( self.name + ": " + self.handle.before )
1015 main.cleanup()
1016 main.exit()
1017 except Exception:
1018 main.log.exception( self.name + ": Uncaught exception!" )
1019 main.cleanup()
1020 main.exit()
1021
1023 """
1024 Calls onos command: 'onos-service [<node-ip>] stop'
1025 This command is a remote management of the ONOS upstart daemon
1026 """
1027 try:
1028 self.handle.sendline( "" )
1029 self.handle.expect( "\$" )
1030 self.handle.sendline( "onos-service " + str( nodeIp ) +
1031 " stop" )
1032 i = self.handle.expect( [
1033 "stop/waiting",
1034 "Could not resolve hostname",
1035 "Unknown\sinstance",
1036 pexpect.TIMEOUT ], timeout=60 )
1037
1038 if i == 0:
1039 main.log.info( "ONOS service stopped" )
1040 return main.TRUE
1041 elif i == 1:
1042 main.log.info( "onosStop() Unknown ONOS instance specified: " +
1043 str( nodeIp ) )
1044 return main.FALSE
1045 elif i == 2:
1046 main.log.warn( "ONOS wasn't running" )
1047 return main.TRUE
1048 else:
1049 main.log.error( "ONOS service failed to stop" )
1050 return main.FALSE
1051
1052 except pexpect.EOF:
1053 main.log.error( self.name + ": EOF exception found" )
1054 main.log.error( self.name + ": " + self.handle.before )
1055 main.cleanup()
1056 main.exit()
1057 except Exception:
1058 main.log.exception( self.name + ": Uncaught exception!" )
1059 main.cleanup()
1060 main.exit()
1061
1063 """
1064 Calls the command: 'onos-uninstall'
1065 Uninstalls ONOS from the designated cell machine, stopping
1066 if needed
1067 """
1068 try:
1069 self.handle.sendline( "" )
1070 self.handle.expect( "\$", timeout=60 )
1071 self.handle.sendline( "onos-uninstall " + str( nodeIp ) )
1072 self.handle.expect( "\$" )
1073
1074 main.log.info( "ONOS " + nodeIp + " was uninstalled" )
1075
1076
1077 return main.TRUE
1078
1079 except pexpect.TIMEOUT:
1080 main.log.exception( self.name + ": Timeout in onosUninstall" )
1081 return main.FALSE
1082 except pexpect.EOF:
1083 main.log.error( self.name + ": EOF exception found" )
1084 main.log.error( self.name + ": " + self.handle.before )
1085 main.cleanup()
1086 main.exit()
1087 except Exception:
1088 main.log.exception( self.name + ": Uncaught exception!" )
1089 main.cleanup()
1090 main.exit()
1091
1093 """
1094 Issues the command 'onos-die <node-ip>'
1095 This command calls onos-kill and also stops the node
1096 """
1097 try:
1098 self.handle.sendline( "" )
1099 self.handle.expect( "\$" )
1100 cmdStr = "onos-kill " + str( nodeIp )
1101 self.handle.sendline( cmdStr )
1102 i = self.handle.expect( [
1103 "Killing\sONOS",
1104 "ONOS\sprocess\sis\snot\srunning",
1105 pexpect.TIMEOUT ], timeout=20 )
1106 if i == 0:
1107 main.log.info( "ONOS instance " + str( nodeIp ) +
1108 " was killed and stopped" )
1109 return main.TRUE
1110 elif i == 1:
1111 main.log.info( "ONOS process was not running" )
1112 return main.FALSE
1113 except pexpect.EOF:
1114 main.log.error( self.name + ": EOF exception found" )
1115 main.log.error( self.name + ": " + self.handle.before )
1116 main.cleanup()
1117 main.exit()
1118 except Exception:
1119 main.log.exception( self.name + ": Uncaught exception!" )
1120 main.cleanup()
1121 main.exit()
1122
1124 """
1125 Calls the command: 'onos-kill [<node-ip>]'
1126 "Remotely, and unceremoniously kills the ONOS instance running on
1127 the specified cell machine" - Tom V
1128 """
1129 try:
1130 self.handle.sendline( "" )
1131 self.handle.expect( "\$" )
1132 self.handle.sendline( "onos-kill " + str( nodeIp ) )
1133 i = self.handle.expect( [
1134 "\$",
1135 "No\sroute\sto\shost",
1136 "password:",
1137 pexpect.TIMEOUT ], timeout=20 )
1138
1139 if i == 0:
1140 main.log.info(
1141 "ONOS instance " + str(
1142 nodeIp ) + " was killed" )
1143 return main.TRUE
1144 elif i == 1:
1145 main.log.info( "No route to host" )
1146 return main.FALSE
1147 elif i == 2:
1148 main.log.info(
1149 "Passwordless login for host: " +
1150 str( nodeIp ) +
1151 " not configured" )
1152 return main.FALSE
1153 else:
1154 main.log.info( "ONOS instance was not killed" )
1155 return main.FALSE
1156
1157 except pexpect.EOF:
1158 main.log.error( self.name + ": EOF exception found" )
1159 main.log.error( self.name + ": " + self.handle.before )
1160 main.cleanup()
1161 main.exit()
1162 except Exception:
1163 main.log.exception( self.name + ": Uncaught exception!" )
1164 main.cleanup()
1165 main.exit()
1166
1168 """
1169 Removes Raft / Copy cat files from ONOS to ensure
1170 a cleaner environment.
1171
1172 Description:
1173 Stops all ONOS defined in the cell,
1174 wipes the raft / copycat log files
1175 """
1176 try:
1177 self.handle.sendline( "" )
1178 self.handle.expect( "\$" )
1179 self.handle.sendline( "onos-remove-raft-logs" )
1180
1181 i = self.handle.expect( [ "\$", pexpect.TIMEOUT ],
1182 timeout=120 )
1183 if i == 1:
1184 i = self.handle.expect( [ "\$", pexpect.TIMEOUT ],
1185 timeout=120 )
1186 if i == 1:
1187 return main.FALSE
1188
1189
1190 return main.TRUE
1191
1192 except pexpect.EOF:
1193 main.log.error( self.name + ": EOF exception found" )
1194 main.log.error( self.name + ": " + self.handle.before )
1195 main.cleanup()
1196 main.exit()
1197 except Exception:
1198 main.log.exception( self.name + ": Uncaught exception!" )
1199 main.cleanup()
1200 main.exit()
1201
1203 """
1204 Calls the command 'onos-start-network [ <mininet-topo> ]
1205 "remotely starts the specified topology on the cell's
1206 mininet machine against all controllers configured in the
1207 cell."
1208 * Specify mininet topology file name for mntopo
1209 * Topo files should be placed at:
1210 ~/<your-onos-directory>/tools/test/topos
1211
1212 NOTE: This function will take you to the mininet prompt
1213 """
1214 try:
1215 if not mntopo:
1216 main.log.error( "You must specify a topo file to execute" )
1217 return main.FALSE
1218
1219 mntopo = str( mntopo )
1220 self.handle.sendline( "" )
1221 self.handle.expect( "\$" )
1222
1223 self.handle.sendline( "onos-start-network " + mntopo )
1224 self.handle.expect( "mininet>" )
1225 main.log.info( "Network started, entered mininet prompt" )
1226
1227
1228
1229 except pexpect.EOF:
1230 main.log.error( self.name + ": EOF exception found" )
1231 main.log.error( self.name + ": " + self.handle.before )
1232 main.cleanup()
1233 main.exit()
1234 except Exception:
1235 main.log.exception( self.name + ": Uncaught exception!" )
1236 main.cleanup()
1237 main.exit()
1238
1239 - def isup(self, node = "", timeout = 120):
1240 """
1241 Run's onos-wait-for-start which only returns once ONOS is at run
1242 level 100(ready for use)
1243
1244 Returns: main.TRUE if ONOS is running and main.FALSE on timeout
1245 """
1246 try:
1247 self.handle.sendline("onos-wait-for-start " + node )
1248 self.handle.expect("onos-wait-for-start")
1249
1250 i = self.handle.expect(["\$", pexpect.TIMEOUT], timeout)
1251 if i == 0:
1252 main.log.info( self.name + ": " + node + " is up" )
1253 return main.TRUE
1254 elif i == 1:
1255
1256
1257 main.log.error( "ONOS has not started yet" )
1258 self.handle.send( "\x03" )
1259 self.handle.expect( "\$" )
1260 return main.FALSE
1261 except pexpect.EOF:
1262 main.log.error( self.name + ": EOF exception found" )
1263 main.log.error( self.name + ": " + self.handle.before )
1264 main.cleanup()
1265 main.exit()
1266 except Exception:
1267 main.log.exception( self.name + ": Uncaught exception!" )
1268 main.cleanup()
1269 main.exit()
1270
1271 - def pushTestIntentsShell(
1272 self,
1273 dpidSrc,
1274 dpidDst,
1275 numIntents,
1276 dirFile,
1277 onosIp,
1278 numMult="",
1279 appId="",
1280 report=True,
1281 options="" ):
1282 """
1283 Description:
1284 Use the linux prompt to push test intents to
1285 better parallelize the results than the CLI
1286 Required:
1287 * dpidSrc: specify source dpid
1288 * dpidDst: specify destination dpid
1289 * numIntents: specify number of intents to push
1290 * dirFile: specify directory and file name to save
1291 results
1292 * onosIp: specify the IP of ONOS to install on
1293 NOTE:
1294 You must invoke this command at linux shell prompt
1295 """
1296 try:
1297
1298 if options:
1299 baseCmd = "onos " + str( onosIp ) + " push-test-intents " +\
1300 options + " "
1301 else:
1302 baseCmd = "onos " + str( onosIp ) + " push-test-intents "
1303
1304 addDpid = baseCmd + str( dpidSrc ) + " " + str( dpidDst )
1305 if not numMult:
1306 addIntents = addDpid + " " + str( numIntents )
1307 elif numMult:
1308 addIntents = addDpid + " " + str( numIntents ) + " " +\
1309 str( numMult )
1310 if appId:
1311 addApp = addIntents + " " + str( appId )
1312 else:
1313 addApp = addIntents
1314
1315 if report:
1316 sendCmd = addApp + " > " + str( dirFile ) + " &"
1317 else:
1318 sendCmd = addApp + " &"
1319 main.log.info( "Send cmd: " + sendCmd )
1320
1321 self.handle.sendline( sendCmd )
1322
1323 except pexpect.EOF:
1324 main.log.error( self.name + ": EOF exception found" )
1325 main.log.error( self.name + ": " + self.handle.before )
1326 main.cleanup()
1327 main.exit()
1328 except Exception:
1329 main.log.exception( self.name + ": Uncaught exception!" )
1330 main.cleanup()
1331 main.exit()
1332
1334 """
1335 Definition:
1336 Loads a json topology output
1337 Return:
1338 topology = current ONOS topology
1339 """
1340 import json
1341 try:
1342
1343 topology = json.loads(topologyOutput)
1344 print topology
1345 return topology
1346 except pexpect.EOF:
1347 main.log.error( self.name + ": EOF exception found" )
1348 main.log.error( self.name + ": " + self.handle.before )
1349 main.cleanup()
1350 main.exit()
1351 except Exception:
1352 main.log.exception( self.name + ": Uncaught exception!" )
1353 main.cleanup()
1354 main.exit()
1355
1356 - def checkStatus(
1357 self,
1358 topologyResult,
1359 numoswitch,
1360 numolink,
1361 logLevel="info" ):
1362 """
1363 Checks the number of switches & links that ONOS sees against the
1364 supplied values. By default this will report to main.log, but the
1365 log level can be specific.
1366
1367 Params: ip = ip used for the onos cli
1368 numoswitch = expected number of switches
1369 numolink = expected number of links
1370 logLevel = level to log to.
1371 Currently accepts 'info', 'warn' and 'report'
1372
1373
1374 logLevel can
1375
1376 Returns: main.TRUE if the number of switches and links are correct,
1377 main.FALSE if the number of switches and links is incorrect,
1378 and main.ERROR otherwise
1379 """
1380 try:
1381 topology = self.getTopology( topologyResult )
1382 if topology == {}:
1383 return main.ERROR
1384 output = ""
1385
1386 devices = topology.get( 'devices', False )
1387 links = topology.get( 'links', False )
1388 if not devices or not links:
1389 return main.ERROR
1390 switchCheck = ( int( devices ) == int( numoswitch ) )
1391
1392 linkCheck = ( int( links ) == int( numolink ) )
1393 if switchCheck and linkCheck:
1394
1395 output = output + "The number of links and switches match "\
1396 + "what was expected"
1397 result = main.TRUE
1398 else:
1399 output = output + \
1400 "The number of links and switches does not match " + \
1401 "what was expected"
1402 result = main.FALSE
1403 output = output + "\n ONOS sees %i devices" % int( devices )
1404 output = output + " (%i expected) " % int( numoswitch )
1405 output = output + "and %i links " % int( links )
1406 output = output + "(%i expected)" % int( numolink )
1407 if logLevel == "report":
1408 main.log.report( output )
1409 elif logLevel == "warn":
1410 main.log.warn( output )
1411 else:
1412 main.log.info( output )
1413 return result
1414 except pexpect.EOF:
1415 main.log.error( self.name + ": EOF exception found" )
1416 main.log.error( self.name + ": " + self.handle.before )
1417 main.cleanup()
1418 main.exit()
1419 except Exception:
1420 main.log.exception( self.name + ": Uncaught exception!" )
1421 main.cleanup()
1422 main.exit()
1423
1425 """
1426 Capture all packet activity and store in specified
1427 directory/file
1428
1429 Required:
1430 * interface: interface to capture
1431 * dir: directory/filename to store pcap
1432 """
1433 try:
1434 self.handle.sendline( "" )
1435 self.handle.expect( "\$" )
1436
1437 self.handle.sendline( "tshark -i " + str( interface ) + " -t e -w " + str( dirFile ) + " &" )
1438 self.handle.sendline( "\r" )
1439 self.handle.expect( "Capturing on" )
1440 self.handle.sendline( "\r" )
1441 self.handle.expect( "\$" )
1442
1443 main.log.info( "Tshark started capturing files on " +
1444 str( interface ) + " and saving to directory: " +
1445 str( dirFile ) )
1446 except pexpect.EOF:
1447 main.log.error( self.name + ": EOF exception found" )
1448 main.log.error( self.name + ": " + self.handle.before )
1449 main.cleanup()
1450 main.exit()
1451 except Exception:
1452 main.log.exception( self.name + ": Uncaught exception!" )
1453 main.cleanup()
1454 main.exit()
1455
1457 """
1458 On ONOS bench, run this command:
1459 {ONOS_HOME}/tools/test/bin/onos-topo-cfg $OC1 filename
1460 which starts the rest and copies
1461 the json file to the onos instance
1462 """
1463 try:
1464 self.handle.sendline( "" )
1465 self.handle.expect( "\$" )
1466 self.handle.sendline( "cd " + self.home + "/tools/test/bin" )
1467 self.handle.expect( "/bin$" )
1468 cmd = "./onos-topo-cfg " + instanceName + " " + jsonFile
1469 print "cmd = ", cmd
1470 self.handle.sendline( cmd )
1471 self.handle.expect( "\$" )
1472 self.handle.sendline( "cd ~" )
1473 self.handle.expect( "\$" )
1474 return main.TRUE
1475 except pexpect.EOF:
1476 main.log.error( self.name + ": EOF exception found" )
1477 main.log.error( self.name + ": " + self.handle.before )
1478 main.cleanup()
1479 main.exit()
1480 except Exception:
1481 main.log.exception( self.name + ": Uncaught exception!" )
1482 main.cleanup()
1483 main.exit()
1484
1485 - def tsharkGrep( self, grep, directory, interface='eth0', grepOptions='' ):
1486 """
1487 Required:
1488 * grep string
1489 * directory to store results
1490 Optional:
1491 * interface - default: eth0
1492 * grepOptions - options for grep
1493 Description:
1494 Uses tshark command to grep specific group of packets
1495 and stores the results to specified directory.
1496 The timestamp is hardcoded to be in epoch
1497 """
1498 try:
1499 self.handle.sendline( "" )
1500 self.handle.expect( "\$" )
1501 self.handle.sendline( "" )
1502 if grepOptions:
1503 grepStr = "grep "+str(grepOptions)
1504 else:
1505 grepStr = "grep"
1506
1507 cmd = (
1508 "sudo tshark -i " +
1509 str( interface ) +
1510 " -t e | " +
1511 grepStr + " --line-buffered \"" +
1512 str(grep) +
1513 "\" >" +
1514 directory +
1515 " &" )
1516 self.handle.sendline(cmd)
1517 main.log.info(cmd)
1518 self.handle.expect( "Capturing on" )
1519 self.handle.sendline( "\n" )
1520 self.handle.expect( "\$" )
1521 except pexpect.EOF:
1522 main.log.error( self.name + ": EOF exception found" )
1523 main.log.error( self.name + ": " + self.handle.before )
1524 main.cleanup()
1525 main.exit()
1526 except Exception:
1527 main.log.exception( self.name + ": Uncaught exception!" )
1528 main.cleanup()
1529 main.exit()
1530
1532 """
1533 Removes wireshark files from /tmp and kills all tshark processes
1534 """
1535
1536 try:
1537 self.execute( cmd="sudo rm /tmp/wireshark*" )
1538 self.handle.sendline( "" )
1539 self.handle.sendline( "sudo kill -9 `ps -ef | grep \"tshark -i\"" +
1540 " | grep -v grep | awk '{print $2}'`" )
1541 self.handle.sendline( "" )
1542 main.log.info( "Tshark stopped" )
1543 except pexpect.EOF:
1544 main.log.error( self.name + ": EOF exception found" )
1545 main.log.error( self.name + ": " + self.handle.before )
1546 main.cleanup()
1547 main.exit()
1548 except Exception:
1549 main.log.exception( self.name + ": Uncaught exception!" )
1550 main.cleanup()
1551 main.exit()
1552
1553 - def ptpd( self, args ):
1554 """
1555 Initiate ptp with user-specified args.
1556 Required:
1557 * args: specify string of args after command
1558 'sudo ptpd'
1559 """
1560 try:
1561 self.handle.sendline( "sudo ptpd " + str( args ) )
1562 i = self.handle.expect( [
1563 "Multiple",
1564 "Error",
1565 "\$" ] )
1566 self.handle.expect( "\$" )
1567
1568 if i == 0:
1569 handle = self.handle.before
1570 main.log.info( "ptpd returned an error: " +
1571 str( handle ) )
1572 return handle
1573 elif i == 1:
1574 handle = self.handle.before
1575 main.log.error( "ptpd returned an error: " +
1576 str( handle ) )
1577 return handle
1578 else:
1579 return main.TRUE
1580
1581 except pexpect.EOF:
1582 main.log.error( self.name + ": EOF exception found" )
1583 main.log.error( self.name + ": " + self.handle.before )
1584 main.cleanup()
1585 main.exit()
1586 except Exception:
1587 main.log.exception( self.name + ": Uncaught exception!" )
1588 main.cleanup()
1589 main.exit()
1590
1591 - def cpLogsToDir( self, logToCopy,
1592 destDir, copyFileName="" ):
1593 """
1594 Copies logs to a desired directory.
1595 Current implementation of ONOS deletes its karaf
1596 logs on every iteration. For debugging purposes,
1597 you may want to use this function to capture
1598 certain karaf logs. ( or any other logs if needed )
1599 Localtime will be attached to the filename
1600
1601 Required:
1602 * logToCopy: specify directory and log name to
1603 copy.
1604 ex ) /opt/onos/log/karaf.log.1
1605 For copying multiple files, leave copyFileName
1606 empty and only specify destDir -
1607 ex ) /opt/onos/log/karaf*
1608 * destDir: specify directory to copy to.
1609 ex ) /tmp/
1610 Optional:
1611 * copyFileName: If you want to rename the log
1612 file, specify copyFileName. This will not work
1613 with multiple file copying
1614 """
1615 try:
1616 localtime = time.strftime( '%x %X' )
1617 localtime = localtime.replace( "/", "" )
1618 localtime = localtime.replace( " ", "_" )
1619 localtime = localtime.replace( ":", "" )
1620 if destDir[ -1: ] != "/":
1621 destDir += "/"
1622
1623 if copyFileName:
1624 self.handle.sendline( "cp " + str( logToCopy ) + " " +
1625 str( destDir ) + str( copyFileName ) +
1626 localtime )
1627 self.handle.expect( "cp" )
1628 self.handle.expect( "\$" )
1629 else:
1630 self.handle.sendline( "cp " + str( logToCopy ) +
1631 " " + str( destDir ) )
1632 self.handle.expect( "cp" )
1633 self.handle.expect( "\$" )
1634
1635 return self.handle.before
1636
1637 except pexpect.EOF:
1638 main.log.error( "Copying files failed" )
1639 main.log.error( self.name + ": EOF exception found" )
1640 main.log.error( self.name + ": " + self.handle.before )
1641 except Exception:
1642 main.log.exception( "Copying files failed" )
1643
1644 - def checkLogs( self, onosIp, restart=False):
1645 """
1646 runs onos-check-logs on the given onos node
1647 If restart is True, use the old version of onos-check-logs which
1648 does not print the full stacktrace, but shows the entire log file,
1649 including across restarts
1650 returns the response
1651 """
1652 try:
1653 cmd = "onos-check-logs " + str( onosIp )
1654 if restart:
1655 cmd += " old"
1656 self.handle.sendline( cmd )
1657 self.handle.expect( cmd )
1658 self.handle.expect( "\$" )
1659 response = self.handle.before
1660 return response
1661 except pexpect.EOF:
1662 main.log.error( "Lost ssh connection" )
1663 main.log.error( self.name + ": EOF exception found" )
1664 main.log.error( self.name + ": " + self.handle.before )
1665 except Exception:
1666 main.log.exception( self.name + ": Uncaught exception!" )
1667 main.cleanup()
1668 main.exit()
1669
1671 """
1672 Calls onos command: 'onos-service [<node-ip>] status'
1673 """
1674 try:
1675 self.handle.sendline( "" )
1676 self.handle.expect( "\$" )
1677 self.handle.sendline( "onos-service " + str( node ) +
1678 " status" )
1679 i = self.handle.expect( [
1680 "start/running",
1681 "stop/waiting",
1682 pexpect.TIMEOUT ], timeout=120 )
1683
1684 if i == 0:
1685 main.log.info( "ONOS is running" )
1686 return main.TRUE
1687 elif i == 1:
1688 main.log.info( "ONOS is stopped" )
1689 main.log.error( "ONOS service failed to check the status" )
1690 main.cleanup()
1691 main.exit()
1692 except pexpect.EOF:
1693 main.log.error( self.name + ": EOF exception found" )
1694 main.log.error( self.name + ": " + self.handle.before )
1695 main.cleanup()
1696 main.exit()
1697 except Exception:
1698 main.log.exception( self.name + ": Uncaught exception!" )
1699 main.cleanup()
1700 main.exit()
1701
1702 - def setIpTables( self, ip, port='', action='add', packet_type='',
1703 direction='INPUT', rule='DROP', states=True ):
1704 """
1705 Description:
1706 add or remove iptables rule to DROP (default) packets from
1707 specific IP and PORT
1708 Usage:
1709 * specify action ('add' or 'remove')
1710 when removing, pass in the same argument as you would add. It will
1711 delete that specific rule.
1712 * specify the ip to block
1713 * specify the destination port to block (defaults to all ports)
1714 * optional packet type to block (default tcp)
1715 * optional iptables rule (default DROP)
1716 * optional direction to block (default 'INPUT')
1717 * States boolean toggles adding all supported tcp states to the
1718 firewall rule
1719 Returns:
1720 main.TRUE on success or
1721 main.FALSE if given invalid input or
1722 main.ERROR if there is an error in response from iptables
1723 WARNING:
1724 * This function uses root privilege iptables command which may result
1725 in unwanted network errors. USE WITH CAUTION
1726 """
1727 import time
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740 try:
1741
1742 action_type = action.lower()
1743 rule = rule.upper()
1744 direction = direction.upper()
1745 if action_type != 'add' and action_type != 'remove':
1746 main.log.error( "Invalid action type. Use 'add' or "
1747 "'remove' table rule" )
1748 if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
1749
1750 main.log.error( "Invalid rule. Valid rules are 'DROP' or "
1751 "'ACCEPT' or 'LOG' only." )
1752 if direction != 'INPUT' and direction != 'OUTPUT':
1753
1754 main.log.error( "Invalid rule. Valid directions are"
1755 " 'OUTPUT' or 'INPUT'" )
1756 return main.FALSE
1757 return main.FALSE
1758 return main.FALSE
1759 if action_type == 'add':
1760
1761 actionFlag = '-A'
1762 elif action_type == 'remove':
1763
1764 actionFlag = '-D'
1765 self.handle.sendline( "" )
1766 self.handle.expect( "\$" )
1767 cmd = "sudo iptables " + actionFlag + " " +\
1768 direction +\
1769 " -s " + str( ip )
1770
1771 if packet_type:
1772 cmd += " -p " + str( packet_type )
1773 if port:
1774 cmd += " --dport " + str( port )
1775 if states:
1776 cmd += " -m state --state="
1777
1778 cmd += "INVALID,ESTABLISHED,NEW,RELATED,UNTRACKED"
1779 cmd += " -j " + str( rule )
1780
1781 self.handle.sendline( cmd )
1782 self.handle.expect( "\$" )
1783 main.log.warn( self.handle.before )
1784
1785 info_string = "On " + str( self.name )
1786 info_string += " " + str( action_type )
1787 info_string += " iptable rule [ "
1788 info_string += " IP: " + str( ip )
1789 info_string += " Port: " + str( port )
1790 info_string += " Rule: " + str( rule )
1791 info_string += " Direction: " + str( direction ) + " ]"
1792 main.log.info( info_string )
1793 return main.TRUE
1794 except pexpect.TIMEOUT:
1795 main.log.exception( self.name + ": Timeout exception in "
1796 "setIpTables function" )
1797 return main.ERROR
1798 except pexpect.EOF:
1799 main.log.error( self.name + ": EOF exception found" )
1800 main.log.error( self.name + ": " + self.handle.before )
1801 main.cleanup()
1802 main.exit()
1803 except Exception:
1804 main.log.exception( self.name + ": Uncaught exception!" )
1805 main.cleanup()
1806 main.exit()
1807
1809 """
1810 This method is used by STS to check the status of the controller
1811 Reports RUNNING, STARTING, STOPPED, FROZEN, ERROR (and reason)
1812 """
1813 import re
1814 try:
1815 self.handle.sendline( "" )
1816 self.handle.expect( "\$" )
1817 self.handle.sendline( "cd " + self.home )
1818 self.handle.expect( "\$" )
1819 self.handle.sendline( "service onos status" )
1820 self.handle.expect( "\$" )
1821 response = self.handle.before
1822 if re.search( "onos start/running", response ):
1823
1824 return 'RUNNING'
1825
1826
1827
1828 elif re.search( "onos stop/", response ):
1829
1830
1831 return 'STOPPED'
1832
1833
1834
1835 else:
1836 main.log.warn( self.name +
1837 " WARNING: status received unknown response" )
1838 main.log.warn( response )
1839 return 'ERROR', "Unknown response: %s" % response
1840 except pexpect.TIMEOUT:
1841 main.log.exception( self.name + ": Timeout exception in "
1842 "setIpTables function" )
1843 return 'ERROR', "Pexpect Timeout"
1844 except pexpect.EOF:
1845 main.log.error( self.name + ": EOF exception found" )
1846 main.log.error( self.name + ": " + self.handle.before )
1847 main.cleanup()
1848 main.exit()
1849 except Exception:
1850 main.log.exception( self.name + ": Uncaught exception!" )
1851 main.cleanup()
1852 main.exit()
1853
1855 '''
1856 Create/formats the LinkGraph.cfg file based on arguments
1857 -only creates a linear topology and connects islands
1858 -evenly distributes devices
1859 -must be called by ONOSbench
1860
1861 ONOSIpList - list of all of the node IPs to be used
1862
1863 deviceCount - number of switches to be assigned
1864 '''
1865 main.log.step("Creating link graph configuration file." )
1866 linkGraphPath = self.home + "/tools/package/etc/linkGraph.cfg"
1867 tempFile = "/tmp/linkGraph.cfg"
1868
1869 linkGraph = open(tempFile, 'w+')
1870 linkGraph.write("# NullLinkProvider topology description (config file).\n")
1871 linkGraph.write("# The NodeId is only added if the destination is another node's device.\n")
1872 linkGraph.write("# Bugs: Comments cannot be appended to a line to be read.\n")
1873
1874 clusterCount = len(ONOSIpList)
1875
1876 if type(deviceCount) is int or type(deviceCount) is str:
1877 deviceCount = int(deviceCount)
1878 switchList = [0]*(clusterCount+1)
1879 baselineSwitchCount = deviceCount/clusterCount
1880
1881 for node in range(1, clusterCount + 1):
1882 switchList[node] = baselineSwitchCount
1883
1884 for node in range(1, (deviceCount%clusterCount)+1):
1885 switchList[node] += 1
1886
1887 if type(deviceCount) is list:
1888 main.log.info("Using provided device distribution")
1889 switchList = [0]
1890 for i in deviceCount:
1891 switchList.append(int(i))
1892
1893 tempList = ['0']
1894 tempList.extend(ONOSIpList)
1895 ONOSIpList = tempList
1896
1897 myPort = 6
1898 lastSwitch = 0
1899 for node in range(1, clusterCount+1):
1900 if switchList[node] == 0:
1901 continue
1902
1903 linkGraph.write("graph " + ONOSIpList[node] + " {\n")
1904
1905 if node > 1:
1906
1907 line = ("\t0:5 -> " + str(lastSwitch) + ":6:" + lastIp + "\n")
1908 linkGraph.write(line)
1909
1910 lastSwitch = 0
1911 for switch in range (0, switchList[node]-1):
1912 line = ""
1913 line = ("\t" + str(switch) + ":" + str(myPort))
1914 line += " -- "
1915 line += (str(switch+1) + ":" + str(myPort-1) + "\n")
1916 linkGraph.write(line)
1917 lastSwitch = switch+1
1918 lastIp = ONOSIpList[node]
1919
1920
1921 if node < (clusterCount):
1922
1923 line = ("\t" + str(lastSwitch) + ":6 -> 0:5:" + ONOSIpList[node+1] + "\n")
1924 linkGraph.write(line)
1925
1926 linkGraph.write("}\n")
1927 linkGraph.close()
1928
1929
1930 os.system( "scp " + tempFile + " " + self.user_name + "@" + benchIp + ":" + linkGraphPath)
1931 main.log.info("linkGraph.cfg creation complete")
1932
1933 - def configNullDev( self, ONOSIpList, deviceCount, numPorts=10):
1934
1935 '''
1936 ONOSIpList = list of Ip addresses of nodes switches will be devided amongst
1937 deviceCount = number of switches to distribute, or list of values to use as custom distribution
1938 numPorts = number of ports per device. Defaults to 10 both in this function and in ONOS. Optional arg
1939 '''
1940
1941 main.log.step("Configuring Null Device Provider" )
1942 clusterCount = len(ONOSIpList)
1943
1944 try:
1945
1946 if type(deviceCount) is int or type(deviceCount) is str:
1947 main.log.step("Creating device distribution")
1948 deviceCount = int(deviceCount)
1949 switchList = [0]*(clusterCount+1)
1950 baselineSwitchCount = deviceCount/clusterCount
1951
1952 for node in range(1, clusterCount + 1):
1953 switchList[node] = baselineSwitchCount
1954
1955 for node in range(1, (deviceCount%clusterCount)+1):
1956 switchList[node] += 1
1957
1958 if type(deviceCount) is list:
1959 main.log.info("Using provided device distribution")
1960
1961 if len(deviceCount) == clusterCount:
1962 switchList = ['0']
1963 switchList.extend(deviceCount)
1964
1965 if len(deviceCount) == (clusterCount + 1):
1966 if deviceCount[0] == '0' or deviceCount[0] == 0:
1967 switchList = deviceCount
1968
1969 assert len(switchList) == (clusterCount + 1)
1970
1971 except AssertionError:
1972 main.log.error( "Bad device/Ip list match")
1973 except TypeError:
1974 main.log.exception( self.name + ": Object not as expected" )
1975 return None
1976 except Exception:
1977 main.log.exception( self.name + ": Uncaught exception!" )
1978 main.cleanup()
1979 main.exit()
1980
1981
1982 ONOSIp = [0]
1983 ONOSIp.extend(ONOSIpList)
1984
1985 devicesString = "devConfigs = "
1986 for node in range(1, len(ONOSIp)):
1987 devicesString += (ONOSIp[node] + ":" + str(switchList[node] ))
1988 if node < clusterCount:
1989 devicesString += (",")
1990
1991 try:
1992 self.handle.sendline("onos $OC1 cfg set org.onosproject.provider.nil.device.impl.NullDeviceProvider devConfigs " + devicesString )
1993 self.handle.expect(":~")
1994 self.handle.sendline("onos $OC1 cfg set org.onosproject.provider.nil.device.impl.NullDeviceProvider numPorts " + str(numPorts) )
1995 self.handle.expect(":~")
1996
1997 for i in range(10):
1998 self.handle.sendline("onos $OC1 cfg get org.onosproject.provider.nil.device.impl.NullDeviceProvider")
1999 self.handle.expect(":~")
2000 verification = self.handle.before
2001 if (" value=" + str(numPorts)) in verification and (" value=" + devicesString) in verification:
2002 break
2003 else:
2004 time.sleep(1)
2005
2006 assert ("value=" + str(numPorts)) in verification and (" value=" + devicesString) in verification
2007
2008 except AssertionError:
2009 main.log.error("Incorrect Config settings: " + verification)
2010 except Exception:
2011 main.log.exception( self.name + ": Uncaught exception!" )
2012 main.cleanup()
2013 main.exit()
2014
2015 - def configNullLink( self,fileName="/opt/onos/apache-karaf-3.0.3/etc/linkGraph.cfg", eventRate=0):
2016 '''
2017 fileName default is currently the same as the default on ONOS, specify alternate file if
2018 you want to use a different topology file than linkGraph.cfg
2019 '''
2020
2021
2022 try:
2023 self.handle.sendline("onos $OC1 cfg set org.onosproject.provider.nil.link.impl.NullLinkProvider eventRate " + str(eventRate))
2024 self.handle.expect(":~")
2025 self.handle.sendline("onos $OC1 cfg set org.onosproject.provider.nil.link.impl.NullLinkProvider cfgFile " + fileName )
2026 self.handle.expect(":~")
2027
2028 for i in range(10):
2029 self.handle.sendline("onos $OC1 cfg get org.onosproject.provider.nil.link.impl.NullLinkProvider")
2030 self.handle.expect(":~")
2031 verification = self.handle.before
2032 if (" value=" + str(eventRate)) in verification and (" value=" + fileName) in verification:
2033 break
2034 else:
2035 time.sleep(1)
2036
2037 assert ("value=" + str(eventRate)) in verification and (" value=" + fileName) in verification
2038
2039 except pexpect.EOF:
2040 main.log.error( self.name + ": EOF exception found" )
2041 main.log.error( self.name + ": " + self.handle.before )
2042 main.cleanup()
2043 main.exit()
2044 except AssertionError:
2045 main.log.info("Settings did not post to ONOS")
2046 main.log.error(varification)
2047 except Exception:
2048 main.log.exception( self.name + ": Uncaught exception!" )
2049 main.log.error(varification)
2050 main.cleanup()
2051 main.exit()
2052
2054 """
2055 Get all onos IPs stored in
2056 """
2057
2058 return sorted( self.onosIps.values() )
2059
2060 - def logReport( self, nodeIp, searchTerms, outputMode="s" ):
2061 '''
2062 - accepts either a list or a string for "searchTerms" these
2063 terms will be searched for in the log and have their
2064 instances counted
2065
2066 - nodeIp is the ip of the node whos log is to be scanned
2067
2068 - output modes:
2069 "s" - Simple. Quiet output mode that just prints
2070 the occurences of each search term
2071
2072 "d" - Detailed. Prints number of occurences as well as the entire
2073 line for each of the last 5 occurences
2074
2075 - returns total of the number of instances of all search terms
2076 '''
2077 main.log.info("========================== Log Report ===========================\n")
2078
2079 if type(searchTerms) is str:
2080 searchTerms = [searchTerms]
2081
2082 logLines = [ [" "] for i in range(len(searchTerms)) ]
2083
2084 for term in range(len(searchTerms)):
2085 logLines[term][0] = searchTerms[term]
2086
2087 totalHits = 0
2088 for term in range(len(searchTerms)):
2089 cmd = "onos-ssh " + nodeIp + " cat /opt/onos/log/karaf.log | grep " + searchTerms[term]
2090 self.handle.sendline(cmd)
2091 self.handle.expect(":~")
2092 before = (self.handle.before).splitlines()
2093
2094 count = [searchTerms[term],0]
2095
2096 for line in before:
2097 if searchTerms[term] in line and "grep" not in line:
2098 count[1] += 1
2099 if before.index(line) > ( len(before) - 7 ):
2100 logLines[term].append(line)
2101
2102 main.log.info( str(count[0]) + ": " + str(count[1]) )
2103 if term == len(searchTerms)-1:
2104 print("\n")
2105 totalHits += int(count[1])
2106
2107 if outputMode != "s" and outputMode != "S":
2108 outputString = ""
2109 for i in logLines:
2110 outputString = i[0] + ": \n"
2111 for x in range(1,len(i)):
2112 outputString += ( i[x] + "\n" )
2113
2114 if outputString != (i[0] + ": \n"):
2115 main.log.info(outputString)
2116
2117 main.log.info("================================================================\n")
2118 return totalHits
2119
2120 - def copyMininetFile( self, fileName, localPath, userName, ip,
2121 mnPath='~/mininet/custom/', timeout = 60 ):
2122 """
2123 Description:
2124 Copy mininet topology file from dependency folder in the test folder
2125 and paste it to the mininet machine's mininet/custom folder
2126 Required:
2127 fileName - Name of the topology file to copy
2128 localPath - File path of the mininet topology file
2129 userName - User name of the mininet machine to send the file to
2130 ip - Ip address of the mininet machine
2131 Optional:
2132 mnPath - of the mininet directory to send the file to
2133 Return:
2134 Return main.TRUE if successfully copied the file otherwise
2135 return main.FALSE
2136 """
2137
2138 try:
2139 cmd = "scp " + localPath + fileName + " " + userName + "@" + \
2140 str( ip ) + ":" + mnPath + fileName
2141
2142 self.handle.sendline( "" )
2143 self.handle.expect( "\$" )
2144
2145 main.log.info( self.name + ": Execute: " + cmd )
2146
2147 self.handle.sendline( cmd )
2148
2149 i = self.handle.expect( [ 'No such file',
2150 "100%",
2151 pexpect.TIMEOUT ] )
2152
2153 if i == 0:
2154 main.log.error( self.name + ": File " + fileName +
2155 " does not exist!" )
2156 return main.FALSE
2157
2158 if i == 1:
2159 main.log.info( self.name + ": File " + fileName +
2160 " has been copied!" )
2161 self.handle.sendline( "" )
2162 self.handle.expect( "\$" )
2163 return main.TRUE
2164
2165 except pexpect.EOF:
2166 main.log.error( self.name + ": EOF exception found" )
2167 main.log.error( self.name + ": " + self.handle.before )
2168 main.cleanup()
2169 main.exit()
2170 except pexpect.TIMEOUT:
2171 main.log.error( self.name + ": TIMEOUT exception found" )
2172 main.log.error( self.name + ": " + self.handle.before )
2173 main.cleanup()
2174 main.exit()
2175
2177
2178 import os
2179
2180 homeDir = os.path.expanduser('~')
2181 filename = "/onos/tools/package/bin/onos-service"
2182
2183 serviceConfig = open(homeDir + filename, 'w+')
2184 serviceConfig.write("#!/bin/bash\n ")
2185 serviceConfig.write("#------------------------------------- \n ")
2186 serviceConfig.write("# Starts ONOS Apache Karaf container\n ")
2187 serviceConfig.write("#------------------------------------- \n ")
2188 serviceConfig.write("#export JAVA_HOME=${JAVA_HOME:-/usr/lib/jvm/java-7-openjdk-amd64/}\n ")
2189 serviceConfig.write("""export JAVA_OPTS="${JAVA_OPTS:--Xms""" + str(memory) + "G -Xmx" + str(memory) + """G}" \n """)
2190 serviceConfig.write("[ -d $ONOS_HOME ] && cd $ONOS_HOME || ONOS_HOME=$(dirname $0)/..\n")
2191 serviceConfig.write("""${ONOS_HOME}/apache-karaf-$KARAF_VERSION/bin/karaf "$@" \n """)
2192 serviceConfig.close()
2193
2195
2196 filename = main.TEST + "DB"
2197 DBString = ""
2198
2199 for item in testData:
2200 if type(item) is string:
2201 item = "'" + item + "'"
2202 if testData.index(item) < len(testData-1):
2203 item += ","
2204 DBString += str(item)
2205
2206 DBFile = open(filename, "a")
2207 DBFile.write(DBString)
2208 DBFile.close()
2209
2211
2212 self.handle.sendline("onos " + ONOSIp + " summary")
2213 self.handle.expect(":~")
2214
2215 summaryStr = self.handle.before
2216 print "\nSummary\n==============\n" + summaryStr + "\n\n"
2217
2218
2219
2220
2221
2222
2223 if "SCC(s)=1," in summaryStr:
2224 passed = True
2225 print("Summary is verifed")
2226 else:
2227 print("Summary failed")
2228
2229 if deviceCount:
2230 print" ============================="
2231 checkStr = "devices=" + str(deviceCount[0]) + ","
2232 print "Checkstr: " + checkStr
2233 if checkStr not in summaryStr:
2234 passed = False
2235 print("Device count failed")
2236 else:
2237 print "device count verified"
2238
2239 return passed
2240