Package TestON :: Package drivers :: Package common :: Package cli :: Package emulator :: Module mininetclidriver
[hide private]
[frames] | no frames]

Source Code for Module TestON.drivers.common.cli.emulator.mininetclidriver

   1  #!/usr/bin/env python 
   2  """ 
   3  Created on 26-Oct-2012 
   4   
   5  author: Anil Kumar ( anilkumar.s@paxterrasolutions.com ) 
   6   
   7   
   8  TestON is free software: you can redistribute it and/or modify 
   9  it under the terms of the GNU General Public License as published by 
  10  the Free Software Foundation, either version 2 of the License, or 
  11  ( at your option ) any later version. 
  12   
  13  TestON is distributed in the hope that it will be useful, 
  14  but WITHOUT ANY WARRANTY; without even the implied warranty of 
  15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  16  GNU General Public License for more details. 
  17   
  18  You should have received a copy of the GNU General Public License 
  19  along with TestON.  If not, see <http://www.gnu.org/licenses/>. 
  20   
  21  MininetCliDriver is the basic driver which will handle the Mininet functions 
  22   
  23  Some functions rely on a modified version of Mininet. These functions 
  24  should all be noted in the comments. To get this MN version run these commands 
  25  from within your Mininet folder: 
  26      git remote add jhall11 https://github.com/jhall11/mininet.git 
  27      git fetch jhall11 
  28      git checkout -b dynamic_topo remotes/jhall11/dynamic_topo 
  29      git pull 
  30   
  31   
  32      Note that you may need to run 'sudo make develop' if your mnexec.c file 
  33  changed when switching branches.""" 
  34  import pexpect 
  35  import re 
  36  import sys 
  37  import types 
  38  import os 
  39  from math import pow 
  40  from drivers.common.cli.emulatordriver import Emulator 
  41   
  42   
43 -class MininetCliDriver( Emulator ):
44 45 """ 46 MininetCliDriver is the basic driver which will handle 47 the Mininet functions"""
48 - def __init__( self ):
49 super( Emulator, self ).__init__() 50 self.handle = self 51 self.name = None 52 self.wrapped = sys.modules[ __name__ ] 53 self.flag = 0
54
55 - def connect( self, **connectargs ):
56 """ 57 Here the main is the TestON instance after creating 58 all the log handles.""" 59 try: 60 for key in connectargs: 61 vars( self )[ key ] = connectargs[ key ] 62 63 self.name = self.options[ 'name' ] 64 65 try: 66 if os.getenv( str( self.ip_address ) ) != None: 67 self.ip_address = os.getenv( str( self.ip_address ) ) 68 else: 69 main.log.info( self.name + 70 ": Trying to connect to " + 71 self.ip_address ) 72 73 except KeyError: 74 main.log.info( "Invalid host name," + 75 " connecting to local host instead" ) 76 self.ip_address = 'localhost' 77 except Exception as inst: 78 main.log.error( "Uncaught exception: " + str( inst ) ) 79 80 self.handle = super( 81 MininetCliDriver, 82 self ).connect( 83 user_name=self.user_name, 84 ip_address=self.ip_address, 85 port=None, 86 pwd=self.pwd ) 87 88 if self.handle: 89 main.log.info( "Connection successful to the host " + 90 self.user_name + 91 "@" + 92 self.ip_address ) 93 return main.TRUE 94 else: 95 main.log.error( "Connection failed to the host " + 96 self.user_name + 97 "@" + 98 self.ip_address ) 99 main.log.error( "Failed to connect to the Mininet CLI" ) 100 return main.FALSE 101 except pexpect.EOF: 102 main.log.error( self.name + ": EOF exception found" ) 103 main.log.error( self.name + ": " + self.handle.before ) 104 main.cleanup() 105 main.exit() 106 except Exception: 107 main.log.exception( self.name + ": Uncaught exception!" ) 108 main.cleanup() 109 main.exit()
110
111 - def startNet( self, topoFile='', args='', mnCmd='', timeout=120 ):
112 """ 113 Description: 114 Starts Mininet accepts a topology(.py) file and/or an optional 115 argument, to start the mininet, as a parameter. 116 Can also send regular mininet command to load up desired topology. 117 Eg. Pass in a string 'sudo mn --topo=tree,3,3' to mnCmd 118 Options: 119 topoFile = file path for topology file (.py) 120 args = extra option added when starting the topology from the file 121 mnCmd = Mininet command use to start topology 122 Returns: 123 main.TRUE if the mininet starts successfully, main.FALSE 124 otherwise 125 """ 126 if self.handle: 127 # make sure old networks are cleaned up 128 main.log.info( self.name + 129 ": Clearing any residual state or processes" ) 130 self.handle.sendline( "sudo mn -c" ) 131 i = self.handle.expect( [ 'password\sfor\s', 132 'Cleanup\scomplete', 133 pexpect.EOF, 134 pexpect.TIMEOUT ], 135 timeout ) 136 if i == 0: 137 # Sudo asking for password 138 main.log.info( self.name + ": Sending sudo password" ) 139 self.handle.sendline( self.pwd ) 140 i = self.handle.expect( [ '%s:' % self.user, 141 '\$', 142 pexpect.EOF, 143 pexpect.TIMEOUT ], 144 timeout ) 145 if i == 1: 146 main.log.info( self.name + ": Clean" ) 147 elif i == 2: 148 main.log.error( self.name + ": Connection terminated" ) 149 elif i == 3: # timeout 150 main.log.error( self.name + ": Something while cleaning " + 151 "Mininet took too long... " ) 152 # Craft the string to start mininet 153 cmdString = "sudo " 154 if not mnCmd: 155 if topoFile is None or topoFile == '': # If no file is given 156 main.log.info( self.name + ": building fresh Mininet" ) 157 cmdString += "mn " 158 if args is None or args == '': 159 # If no args given, use args from .topo file 160 args = self.options[ 'arg1' ] +\ 161 " " + self.options[ 'arg2' ] +\ 162 " --mac --controller " +\ 163 self.options[ 'controller' ] + " " +\ 164 self.options[ 'arg3' ] 165 else: # else only use given args 166 pass 167 # TODO: allow use of topo args and method args? 168 else: # Use given topology file 169 main.log.info( 170 "Starting Mininet from topo file " + 171 topoFile ) 172 cmdString += topoFile + " " 173 if args is None: 174 args = '' 175 # TODO: allow use of args from .topo file? 176 cmdString += args 177 else: 178 main.log.info( "Starting Mininet topology using '" + mnCmd + 179 "' command" ) 180 cmdString += mnCmd 181 # Send the command and check if network started 182 self.handle.sendline( "" ) 183 self.handle.expect( '\$' ) 184 main.log.info( "Sending '" + cmdString + "' to " + self.name ) 185 self.handle.sendline( cmdString ) 186 while True: 187 i = self.handle.expect( [ 'mininet>', 188 'Exception', 189 '\*\*\*', 190 pexpect.EOF, 191 pexpect.TIMEOUT ], 192 timeout ) 193 if i == 0: 194 main.log.info( self.name + ": Mininet built" ) 195 return main.TRUE 196 elif i == 1: 197 response = str( self.handle.before + 198 self.handle.after ) 199 self.handle.expect( '\$' ) 200 response += str( self.handle.before + 201 self.handle.after ) 202 main.log.error( 203 self.name + 204 ": Launching Mininet failed: " + response ) 205 return main.FALSE 206 elif i == 2: 207 self.handle.expect( [ "\n", 208 pexpect.EOF, 209 pexpect.TIMEOUT ], 210 timeout ) 211 main.log.info( self.handle.before ) 212 elif i == 3: 213 main.log.error( self.name + ": Connection timeout" ) 214 return main.FALSE 215 elif i == 4: # timeout 216 main.log.error( 217 self.name + 218 ": Something took too long... " ) 219 return main.FALSE 220 # Why did we hit this part? 221 main.log.error( "startNet did not return correctly" ) 222 return main.FASLE 223 else: # if no handle 224 main.log.error( self.name + ": Connection failed to the host " + 225 self.user_name + "@" + self.ip_address ) 226 main.log.error( self.name + ": Failed to connect to the Mininet" ) 227 return main.FALSE
228 264 276
277 - def pingall( self, timeout=300, shortCircuit=False, acceptableFailed=0 ):
278 """ 279 Verifies the reachability of the hosts using pingall command. 280 Optional parameter timeout allows you to specify how long to 281 wait for pingall to complete 282 Optional: 283 timeout( seconds ) - How long to wait before breaking the pingall 284 shortCircuit - Break the pingall based on the number of failed hosts 285 ping 286 acceptableFailed - Set the number of acceptable failed pings for the 287 function to still return main.TRUE 288 Returns: 289 main.TRUE if pingall completes with no pings dropped 290 otherwise main.FALSE 291 """ 292 import time 293 try: 294 timeout = int( timeout ) 295 if self.handle: 296 main.log.info( 297 self.name + 298 ": Checking reachabilty to the hosts using pingall" ) 299 response = "" 300 failedPings = 0 301 returnValue = main.TRUE 302 self.handle.sendline( "pingall" ) 303 startTime = time.time() 304 while True: 305 i = self.handle.expect( [ "mininet>", "X", 306 pexpect.EOF, 307 pexpect.TIMEOUT ], 308 timeout ) 309 if i == 0: 310 main.log.info( self.name + ": pingall finished" ) 311 response += self.handle.before 312 break 313 elif i == 1: 314 response += self.handle.before + self.handle.after 315 failedPings = failedPings + 1 316 if failedPings > acceptableFailed: 317 returnValue = main.FALSE 318 if shortCircuit: 319 main.log.error( self.name + 320 ": Aborting pingall - " 321 + str( failedPings ) + 322 " pings failed" ) 323 break 324 if ( time.time() - startTime ) > timeout: 325 returnValue = main.FALSE 326 main.log.error( self.name + 327 ": Aborting pingall - " + 328 "Function took too long " ) 329 break 330 elif i == 2: 331 main.log.error( self.name + 332 ": EOF exception found" ) 333 main.log.error( self.name + ": " + 334 self.handle.before ) 335 main.cleanup() 336 main.exit() 337 elif i == 3: 338 response += self.handle.before 339 main.log.error( self.name + 340 ": TIMEOUT exception found" ) 341 main.log.error( self.name + 342 ": " + 343 str( response ) ) 344 # NOTE: Send ctrl-c to make sure pingall is done 345 self.handle.sendline( "\x03" ) 346 self.handle.expect( "Interrupt" ) 347 self.handle.expect( "mininet>" ) 348 break 349 pattern = "Results\:" 350 main.log.info( "Pingall output: " + str( response ) ) 351 if re.search( pattern, response ): 352 main.log.info( self.name + ": Pingall finished with " 353 + str( failedPings ) + " failed pings" ) 354 return returnValue 355 else: 356 # NOTE: Send ctrl-c to make sure pingall is done 357 self.handle.sendline( "\x03" ) 358 self.handle.expect( "Interrupt" ) 359 self.handle.expect( "mininet>" ) 360 return main.FALSE 361 else: 362 main.log.error( self.name + ": Connection failed to the host" ) 363 main.cleanup() 364 main.exit() 365 except pexpect.TIMEOUT: 366 if response: 367 main.log.info( "Pingall output: " + str( response ) ) 368 main.log.error( self.name + ": pexpect.TIMEOUT found" ) 369 return main.FALSE 370 except pexpect.EOF: 371 main.log.error( self.name + ": EOF exception found" ) 372 main.log.error( self.name + ": " + self.handle.before ) 373 main.cleanup() 374 main.exit()
375
376 - def fpingHost( self, **pingParams ):
377 """ 378 Uses the fping package for faster pinging... 379 *requires fping to be installed on machine running mininet""" 380 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams ) 381 command = args[ "SRC" ] + \ 382 " fping -i 100 -t 20 -C 1 -q " + args[ "TARGET" ] 383 self.handle.sendline( command ) 384 self.handle.expect( 385 [ args[ "TARGET" ], pexpect.EOF, pexpect.TIMEOUT ] ) 386 self.handle.expect( [ "mininet", pexpect.EOF, pexpect.TIMEOUT ] ) 387 response = self.handle.before 388 if re.search( ":\s-", response ): 389 main.log.info( self.name + ": Ping fail" ) 390 return main.FALSE 391 elif re.search( ":\s\d{1,2}\.\d\d", response ): 392 main.log.info( self.name + ": Ping good!" ) 393 return main.TRUE 394 main.log.info( self.name + ": Install fping on mininet machine... " ) 395 main.log.info( self.name + ": \n---\n" + response ) 396 return main.FALSE
397
398 - def pingallHosts( self, hostList ):
399 """ 400 Ping all specified IPv4 hosts 401 402 Acceptable hostList: 403 - [ 'h1','h2','h3','h4' ] 404 405 Returns main.TRUE if all hosts specified can reach 406 each other 407 408 Returns main.FALSE if one or more of hosts specified 409 cannot reach each other""" 410 411 cmd = " ping -c 1 -i 1 -W 8 " 412 413 try: 414 main.log.info( "Testing reachability between specified hosts" ) 415 416 isReachable = main.TRUE 417 418 for host in hostList: 419 listIndex = hostList.index( host ) 420 # List of hosts to ping other than itself 421 pingList = hostList[ :listIndex ] + \ 422 hostList[ ( listIndex + 1 ): ] 423 424 for temp in pingList: 425 # Current host pings all other hosts specified 426 pingCmd = str( host ) + cmd + str( temp ) 427 self.handle.sendline( pingCmd ) 428 i = self.handle.expect( [ pingCmd, pexpect.TIMEOUT ] ) 429 j = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] ) 430 response = self.handle.before 431 if re.search( ',\s0\%\spacket\sloss', response ): 432 main.log.info( str( host ) + " -> " + str( temp ) ) 433 else: 434 main.log.info( 435 str( host ) + " -> X (" + str( temp ) + ") " 436 " Destination Unreachable" ) 437 # One of the host to host pair is unreachable 438 isReachable = main.FALSE 439 440 return isReachable 441 442 except pexpect.EOF: 443 main.log.error( self.name + ": EOF exception found" ) 444 main.log.error( self.name + ": " + self.handle.before ) 445 main.cleanup() 446 main.exit()
447
448 - def pingIpv6Hosts(self, hostList, prefix='1000::'):
449 """ 450 IPv6 ping all hosts in hostList. If no prefix passed this will use 451 default prefix of 1000:: 452 453 Returns main.TRUE if all hosts specified can reach each other 454 455 Returns main.FALSE if one or more of hosts specified cannot reach each other 456 """ 457 try: 458 main.log.info( "Testing reachability between specified IPv6 hosts" ) 459 isReachable = main.TRUE 460 cmd = " ping6 -c 1 -i 1 -W 8 " 461 for host in hostList: 462 listIndex = hostList.index( host ) 463 # List of hosts to ping other than itself 464 pingList = hostList[ :listIndex ] + \ 465 hostList[ ( listIndex + 1 ): ] 466 467 for temp in pingList: 468 # Current host pings all other hosts specified 469 pingCmd = str( host ) + cmd + prefix + str( temp[1:] ) 470 i = self.handle.expect( [ pingCmd, pexpect.TIMEOUT ] ) 471 j = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] ) 472 response = self.handle.before 473 if re.search( ',\s0\%\spacket\sloss', response ): 474 main.log.info( str( host ) + " -> " + str( temp ) ) 475 else: 476 main.log.info( 477 str( host ) + " -> X (" + str( temp ) + ") " 478 " Destination Unreachable" ) 479 main.log.error( "Response from Mininet: " + str( response ) ) 480 # One of the host to host pair is unreachable 481 isReachable = main.FALSE 482 return isReachable 483 484 except pexpect.EOF: 485 main.log.error( self.name + ": EOF exception found" ) 486 main.log.error( self.name + ": " + self.handle.before ) 487 main.cleanup() 488 main.exit()
489
490 - def pingHost( self, **pingParams ):
491 """ 492 Ping from one mininet host to another 493 Currently the only supported Params: SRC and TARGET""" 494 args = utilities.parse_args( [ "SRC", "TARGET" ], **pingParams ) 495 command = args[ "SRC" ] + " ping " + \ 496 args[ "TARGET" ] + " -c 1 -i 1 -W 8" 497 try: 498 main.log.info( "Sending: " + command ) 499 self.handle.sendline( command ) 500 i = self.handle.expect( [ command, pexpect.TIMEOUT ] ) 501 if i == 1: 502 main.log.error( 503 self.name + 504 ": timeout when waiting for response from mininet" ) 505 main.log.error( "response: " + str( self.handle.before ) ) 506 i = self.handle.expect( [ "mininet>", pexpect.TIMEOUT ] ) 507 if i == 1: 508 main.log.error( 509 self.name + 510 ": timeout when waiting for response from mininet" ) 511 main.log.error( "response: " + str( self.handle.before ) ) 512 response = self.handle.before 513 except pexpect.EOF: 514 main.log.error( self.name + ": EOF exception found" ) 515 main.log.error( self.name + ": " + self.handle.before ) 516 main.cleanup() 517 main.exit() 518 main.log.info( self.name + ": Ping Response: " + response ) 519 if re.search( ',\s0\%\spacket\sloss', response ): 520 main.log.info( self.name + ": no packets lost, host is reachable" ) 521 main.lastResult = main.TRUE 522 return main.TRUE 523 else: 524 main.log.error( 525 self.name + 526 ": PACKET LOST, HOST IS NOT REACHABLE" ) 527 main.lastResult = main.FALSE 528 return main.FALSE
529
530 - def checkIP( self, host ):
531 """ 532 Verifies the host's ip configured or not.""" 533 if self.handle: 534 try: 535 response = self.execute( 536 cmd=host + 537 " ifconfig", 538 prompt="mininet>", 539 timeout=10 ) 540 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 546 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|" +\ 547 "2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}" +\ 548 "[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})." +\ 549 "([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|" +\ 550 "[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4]" +\ 551 "[0-9]|25[0-5]|[0-9]{1,2})" 552 # pattern = "inet addr:10.0.0.6" 553 if re.search( pattern, response ): 554 main.log.info( self.name + ": Host Ip configured properly" ) 555 return main.TRUE 556 else: 557 main.log.error( self.name + ": Host IP not found" ) 558 return main.FALSE 559 else: 560 main.log.error( self.name + ": Connection failed to the host" )
561
562 - def verifySSH( self, **connectargs ):
563 # FIXME: Who uses this and what is the purpose? seems very specific 564 try: 565 response = self.execute( 566 cmd="h1 /usr/sbin/sshd -D&", 567 prompt="mininet>", 568 timeout=10 ) 569 response = self.execute( 570 cmd="h4 /usr/sbin/sshd -D&", 571 prompt="mininet>", 572 timeout=10 ) 573 for key in connectargs: 574 vars( self )[ key ] = connectargs[ key ] 575 response = self.execute( 576 cmd="xterm h1 h4 ", 577 prompt="mininet>", 578 timeout=10 ) 579 except pexpect.EOF: 580 main.log.error( self.name + ": EOF exception found" ) 581 main.log.error( self.name + ": " + self.handle.before ) 582 main.cleanup() 583 main.exit() 584 import time 585 time.sleep( 20 ) 586 if self.flag == 0: 587 self.flag = 1 588 return main.FALSE 589 else: 590 return main.TRUE
591
592 - def moveHost( self, host, oldSw, newSw, ):
593 """ 594 Moves a host from one switch to another on the fly 595 Note: The intf between host and oldSw when detached 596 using detach(), will still show up in the 'net' 597 cmd, because switch.detach() doesn't affect switch.intfs[] 598 ( which is correct behavior since the interfaces 599 haven't moved ). 600 """ 601 if self.handle: 602 try: 603 # Bring link between oldSw-host down 604 cmd = "py net.configLinkStatus('" + oldSw + "'," + "'" + host +\ 605 "'," + "'down')" 606 print "cmd1= ", cmd 607 response = self.execute( cmd=cmd, 608 prompt="mininet>", 609 timeout=10 ) 610 611 # Determine hostintf and Oldswitchintf 612 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + oldSw +\ 613 ")[0]" 614 print "cmd2= ", cmd 615 self.handle.sendline( cmd ) 616 self.handle.expect( "mininet>" ) 617 618 # Determine ip and mac address of the host-oldSw interface 619 cmd = "px ipaddr = hintf.IP()" 620 print "cmd3= ", cmd 621 self.handle.sendline( cmd ) 622 self.handle.expect( "mininet>" ) 623 624 cmd = "px macaddr = hintf.MAC()" 625 print "cmd3= ", cmd 626 self.handle.sendline( cmd ) 627 self.handle.expect( "mininet>" ) 628 629 # Detach interface between oldSw-host 630 cmd = "px " + oldSw + ".detach( sintf )" 631 print "cmd4= ", cmd 632 self.handle.sendline( cmd ) 633 self.handle.expect( "mininet>" ) 634 635 # Add link between host-newSw 636 cmd = "py net.addLink(" + host + "," + newSw + ")" 637 print "cmd5= ", cmd 638 self.handle.sendline( cmd ) 639 self.handle.expect( "mininet>" ) 640 641 # Determine hostintf and Newswitchintf 642 cmd = "px hintf,sintf = " + host + ".connectionsTo(" + newSw +\ 643 ")[0]" 644 print "cmd6= ", cmd 645 self.handle.sendline( cmd ) 646 self.handle.expect( "mininet>" ) 647 648 # Attach interface between newSw-host 649 cmd = "px " + newSw + ".attach( sintf )" 650 print "cmd3= ", cmd 651 self.handle.sendline( cmd ) 652 self.handle.expect( "mininet>" ) 653 654 # Set ipaddress of the host-newSw interface 655 cmd = "px " + host + ".setIP( ip = ipaddr, intf = hintf)" 656 print "cmd7 = ", cmd 657 self.handle.sendline( cmd ) 658 self.handle.expect( "mininet>" ) 659 660 # Set macaddress of the host-newSw interface 661 cmd = "px " + host + ".setMAC( mac = macaddr, intf = hintf)" 662 print "cmd8 = ", cmd 663 self.handle.sendline( cmd ) 664 self.handle.expect( "mininet>" ) 665 666 cmd = "net" 667 print "cmd9 = ", cmd 668 self.handle.sendline( cmd ) 669 self.handle.expect( "mininet>" ) 670 print "output = ", self.handle.before 671 672 # Determine ipaddress of the host-newSw interface 673 cmd = host + " ifconfig" 674 print "cmd10= ", cmd 675 self.handle.sendline( cmd ) 676 self.handle.expect( "mininet>" ) 677 print "ifconfig o/p = ", self.handle.before 678 679 return main.TRUE 680 except pexpect.EOF: 681 main.log.error( self.name + ": EOF exception found" ) 682 main.log.error( self.name + ": " + self.handle.before ) 683 return main.FALSE
684
685 - def changeIP( self, host, intf, newIP, newNetmask ):
686 """ 687 Changes the ip address of a host on the fly 688 Ex: h2 ifconfig h2-eth0 10.0.1.2 netmask 255.255.255.0""" 689 if self.handle: 690 try: 691 cmd = host + " ifconfig " + intf + " " + \ 692 newIP + " " + 'netmask' + " " + newNetmask 693 self.handle.sendline( cmd ) 694 self.handle.expect( "mininet>" ) 695 response = self.handle.before 696 main.log.info( "response = " + response ) 697 main.log.info( 698 "Ip of host " + 699 host + 700 " changed to new IP " + 701 newIP ) 702 return main.TRUE 703 except pexpect.EOF: 704 main.log.error( self.name + ": EOF exception found" ) 705 main.log.error( self.name + ": " + self.handle.before ) 706 return main.FALSE
707
708 - def changeDefaultGateway( self, host, newGW ):
709 """ 710 Changes the default gateway of a host 711 Ex: h1 route add default gw 10.0.1.2""" 712 if self.handle: 713 try: 714 cmd = host + " route add default gw " + newGW 715 self.handle.sendline( cmd ) 716 self.handle.expect( "mininet>" ) 717 response = self.handle.before 718 main.log.info( "response = " + response ) 719 main.log.info( 720 "Default gateway of host " + 721 host + 722 " changed to " + 723 newGW ) 724 return main.TRUE 725 except pexpect.EOF: 726 main.log.error( self.name + ": EOF exception found" ) 727 main.log.error( self.name + ": " + self.handle.before ) 728 return main.FALSE
729
730 - def addStaticMACAddress( self, host, GW, macaddr ):
731 """ 732 Changes the mac address of a gateway host""" 733 if self.handle: 734 try: 735 # h1 arp -s 10.0.1.254 00:00:00:00:11:11 736 cmd = host + " arp -s " + GW + " " + macaddr 737 self.handle.sendline( cmd ) 738 self.handle.expect( "mininet>" ) 739 response = self.handle.before 740 main.log.info( "response = " + response ) 741 main.log.info( 742 "Mac address of gateway " + 743 GW + 744 " changed to " + 745 macaddr ) 746 return main.TRUE 747 except pexpect.EOF: 748 main.log.error( self.name + ": EOF exception found" ) 749 main.log.error( self.name + ": " + self.handle.before ) 750 return main.FALSE
751
752 - def verifyStaticGWandMAC( self, host ):
753 """ 754 Verify if the static gateway and mac address assignment""" 755 if self.handle: 756 try: 757 # h1 arp -an 758 cmd = host + " arp -an " 759 self.handle.sendline( cmd ) 760 self.handle.expect( "mininet>" ) 761 response = self.handle.before 762 main.log.info( host + " arp -an = " + response ) 763 return main.TRUE 764 except pexpect.EOF: 765 main.log.error( self.name + ": EOF exception found" ) 766 main.log.error( self.name + ": " + self.handle.before ) 767 return main.FALSE
768
769 - def getMacAddress( self, host ):
770 """ 771 Verifies the host's ip configured or not.""" 772 if self.handle: 773 try: 774 response = self.execute( 775 cmd=host + 776 " ifconfig", 777 prompt="mininet>", 778 timeout=10 ) 779 except pexpect.EOF: 780 main.log.error( self.name + ": EOF exception found" ) 781 main.log.error( self.name + ": " + self.handle.before ) 782 main.cleanup() 783 main.exit() 784 785 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})' 786 macAddressSearch = re.search( pattern, response, re.I ) 787 macAddress = macAddressSearch.group().split( " " )[ 1 ] 788 main.log.info( 789 self.name + 790 ": Mac-Address of Host " + 791 host + 792 " is " + 793 macAddress ) 794 return macAddress 795 else: 796 main.log.error( self.name + ": Connection failed to the host" )
797
798 - def getInterfaceMACAddress( self, host, interface ):
799 """ 800 Return the IP address of the interface on the given host""" 801 if self.handle: 802 try: 803 response = self.execute( cmd=host + " ifconfig " + interface, 804 prompt="mininet>", timeout=10 ) 805 except pexpect.EOF: 806 main.log.error( self.name + ": EOF exception found" ) 807 main.log.error( self.name + ": " + self.handle.before ) 808 main.cleanup() 809 main.exit() 810 811 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})' 812 macAddressSearch = re.search( pattern, response, re.I ) 813 if macAddressSearch is None: 814 main.log.info( "No mac address found in %s" % response ) 815 return main.FALSE 816 macAddress = macAddressSearch.group().split( " " )[ 1 ] 817 main.log.info( 818 "Mac-Address of " + 819 host + 820 ":" + 821 interface + 822 " is " + 823 macAddress ) 824 return macAddress 825 else: 826 main.log.error( "Connection failed to the host" )
827
828 - def getIPAddress( self, host ):
829 """ 830 Verifies the host's ip configured or not.""" 831 if self.handle: 832 try: 833 response = self.execute( 834 cmd=host + 835 " ifconfig", 836 prompt="mininet>", 837 timeout=10 ) 838 except pexpect.EOF: 839 main.log.error( self.name + ": EOF exception found" ) 840 main.log.error( self.name + ": " + self.handle.before ) 841 main.cleanup() 842 main.exit() 843 844 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)" 845 ipAddressSearch = re.search( pattern, response ) 846 main.log.info( 847 self.name + 848 ": IP-Address of Host " + 849 host + 850 " is " + 851 ipAddressSearch.group( 1 ) ) 852 return ipAddressSearch.group( 1 ) 853 else: 854 main.log.error( self.name + ": Connection failed to the host" )
855
856 - def getSwitchDPID( self, switch ):
857 """ 858 return the datapath ID of the switch""" 859 if self.handle: 860 cmd = "py %s.dpid" % switch 861 try: 862 response = self.execute( 863 cmd=cmd, 864 prompt="mininet>", 865 timeout=10 ) 866 except pexpect.EOF: 867 main.log.error( self.name + ": EOF exception found" ) 868 main.log.error( self.name + ": " + self.handle.before ) 869 main.cleanup() 870 main.exit() 871 pattern = r'^(?P<dpid>\w)+' 872 result = re.search( pattern, response, re.MULTILINE ) 873 if result is None: 874 main.log.info( 875 "Couldn't find DPID for switch %s, found: %s" % 876 ( switch, response ) ) 877 return main.FALSE 878 return str( result.group( 0 ) ).lower() 879 else: 880 main.log.error( "Connection failed to the host" )
881
882 - def getDPID( self, switch ):
883 if self.handle: 884 self.handle.sendline( "" ) 885 self.expect( "mininet>" ) 886 cmd = "py %s.dpid" % switch 887 try: 888 response = self.execute( 889 cmd=cmd, 890 prompt="mininet>", 891 timeout=10 ) 892 self.handle.expect( "mininet>" ) 893 response = self.handle.before 894 return response 895 except pexpect.EOF: 896 main.log.error( self.name + ": EOF exception found" ) 897 main.log.error( self.name + ": " + self.handle.before ) 898 main.cleanup() 899 main.exit()
900
901 - def getInterfaces( self, node ):
902 """ 903 return information dict about interfaces connected to the node""" 904 if self.handle: 905 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,enabled=%s"' +\ 906 ' % (i.name, i.MAC(), i.IP(), i.isUp())' 907 cmd += ' for i in %s.intfs.values()])' % node 908 try: 909 response = self.execute( 910 cmd=cmd, 911 prompt="mininet>", 912 timeout=10 ) 913 except pexpect.EOF: 914 main.log.error( self.name + ": EOF exception found" ) 915 main.log.error( self.name + ": " + self.handle.before ) 916 main.cleanup() 917 main.exit() 918 return response 919 else: 920 main.log.error( "Connection failed to the node" )
921
922 - def dump( self ):
923 main.log.info( self.name + ": Dump node info" ) 924 try: 925 response = self.execute( 926 cmd='dump', 927 prompt='mininet>', 928 timeout=10 ) 929 except pexpect.EOF: 930 main.log.error( self.name + ": EOF exception found" ) 931 main.log.error( self.name + ": " + self.handle.before ) 932 main.cleanup() 933 main.exit() 934 return response
935
936 - def intfs( self ):
937 main.log.info( self.name + ": List interfaces" ) 938 try: 939 response = self.execute( 940 cmd='intfs', 941 prompt='mininet>', 942 timeout=10 ) 943 except pexpect.EOF: 944 main.log.error( self.name + ": EOF exception found" ) 945 main.log.error( self.name + ": " + self.handle.before ) 946 main.cleanup() 947 main.exit() 948 return response
949
950 - def net( self ):
951 main.log.info( self.name + ": List network connections" ) 952 try: 953 response = self.execute( cmd='net', prompt='mininet>', timeout=10 ) 954 except pexpect.EOF: 955 main.log.error( self.name + ": EOF exception found" ) 956 main.log.error( self.name + ": " + self.handle.before ) 957 main.cleanup() 958 main.exit() 959 return response
960 972
973 - def iperftcpAll(self, hosts, timeout=6):
974 ''' 975 Runs the iperftcp function with a given set of hosts and specified timeout. 976 977 @parm: 978 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete, 979 and short enough to stop an unsuccessful test from quiting and cleaning up mininet. 980 ''' 981 for host1 in hosts: 982 for host2 in hosts: 983 if host1 != host2: 984 if self.iperftcp(host1, host2, timeout) == main.FALSE: 985 main.log.error(self.name + ": iperftcp test failed for " + host1 + " and " + host2)
986
987 - def iperftcp(self, host1="h1", host2="h2", timeout=6):
988 ''' 989 Creates an iperf TCP test between two hosts. Returns main.TRUE if test results 990 are valid. 991 992 @parm: 993 timeout: The defualt timeout is 6 sec to allow enough time for a successful test to complete, 994 and short enough to stop an unsuccessful test from quiting and cleaning up mininet. 995 ''' 996 main.log.info( self.name + ": Simple iperf TCP test between two hosts" ) 997 try: 998 # Setup the mininet command 999 cmd1 = 'iperf ' + host1 + " " + host2 1000 self.handle.sendline( cmd1 ) 1001 outcome = self.handle.expect( "mininet>", timeout ) 1002 response = self.handle.before 1003 1004 # checks if there are results in the mininet response 1005 if "Results:" in response: 1006 main.log.report(self.name + ": iperf test completed") 1007 # parse the mn results 1008 response = response.split("\r\n") 1009 response = response[len(response)-2] 1010 response = response.split(": ") 1011 response = response[len(response)-1] 1012 response = response.replace("[", "") 1013 response = response.replace("]", "") 1014 response = response.replace("\'", "") 1015 1016 # this is the bandwith two and from the two hosts 1017 bandwidth = response.split(", ") 1018 1019 # there should be two elements in the bandwidth list 1020 # ['host1 to host2', 'host2 to host1"] 1021 if len(bandwidth) == 2: 1022 main.log.report(self.name + ": iperf test successful") 1023 return main.TRUE 1024 else: 1025 main.log.error(self.name + ": invalid iperf results") 1026 return main.FALSE 1027 else: 1028 main.log.error( self.name + ": iperf test failed" ) 1029 return main.FALSE 1030 1031 except pexpect.TIMEOUT: 1032 main.log.error( self.name + ": TIMEOUT exception found") 1033 main.log.error( self.name + ": Exception: Cannot connect to iperf on port 5001" ) 1034 return main.FALSE 1035 1036 except pexpect.EOF: 1037 main.log.error( self.name + ": EOF exception found" ) 1038 main.log.error( self.name + ": " + self.handle.before ) 1039 main.cleanup() 1040 main.exit()
1041
1042 - def iperfudpAll(self, hosts, bandwidth="10M"):
1043 ''' 1044 Runs the iperfudp function with a given set of hosts and specified 1045 bandwidth 1046 1047 @param: 1048 bandwidth: the targeted bandwidth, in megabits ('M') 1049 ''' 1050 for host1 in hosts: 1051 for host2 in hosts: 1052 if host1 != host2: 1053 if self.iperfudp(host1, host2, bandwidth) == main.FALSE: 1054 main.log.error(self.name + ": iperfudp test failed for " + host1 + " and " + host2)
1055
1056 - def iperfudp( self, bandwidth="10M", host1="h1", host2="h2"):
1057 1058 ''' 1059 Creates an iperf UDP test with a specific bandwidth. 1060 Returns true if results are valid. 1061 1062 @param: 1063 bandwidth: the targeted bandwidth, in megabits ('M'), to run the test 1064 ''' 1065 main.log.info(self.name + ": Simple iperf UDP test between two hosts") 1066 try: 1067 # setup the mininet command 1068 cmd = 'iperfudp ' + bandwidth + " " + host1 + " " + host2 1069 self.handle.sendline(cmd) 1070 self.handle.expect("mininet>") 1071 response = self.handle.before 1072 1073 # check if there are in results in the mininet response 1074 if "Results:" in response: 1075 main.log.report(self.name + ": iperfudp test completed") 1076 # parse the results 1077 response = response.split("\r\n") 1078 response = response[len(response)-2] 1079 response = response.split(": ") 1080 response = response[len(response)-1] 1081 response = response.replace("[", "") 1082 response = response.replace("]", "") 1083 response = response.replace("\'", "") 1084 1085 mnBandwidth = response.split(", ") 1086 1087 # check to see if there are at least three entries 1088 # ['bandwidth', 'host1 to host2', 'host2 to host1'] 1089 if len(mnBandwidth) == 3: 1090 # if one entry is blank then something is wrong 1091 for item in mnBandwidth: 1092 if item == "": 1093 main.log.error(self.name + ": Could not parse iperf output") 1094 main.log.error(self.name + ": invalid iperfudp results") 1095 return main.FALSE 1096 # otherwise results are vaild 1097 main.log.report(self.name + ": iperfudp test successful") 1098 return main.TRUE 1099 else: 1100 main.log.error(self.name + ": invalid iperfudp results") 1101 return main.FALSE 1102 1103 except pexpect.EOF: 1104 main.log.error( self.name + ": EOF exception found" ) 1105 main.log.error( self.name + ": " + self.handle.before ) 1106 main.cleanup() 1107 main.exit()
1108
1109 - def nodes( self ):
1110 main.log.info( self.name + ": List all nodes." ) 1111 try: 1112 response = self.execute( 1113 cmd='nodes', 1114 prompt='mininet>', 1115 timeout=10 ) 1116 except pexpect.EOF: 1117 main.log.error( self.name + ": EOF exception found" ) 1118 main.log.error( self.name + ": " + self.handle.before ) 1119 main.cleanup() 1120 main.exit() 1121 return response
1122
1123 - def pingpair( self ):
1124 main.log.info( self.name + ": Ping between first two hosts" ) 1125 try: 1126 response = self.execute( 1127 cmd='pingpair', 1128 prompt='mininet>', 1129 timeout=20 ) 1130 except pexpect.EOF: 1131 main.log.error( self.name + ": EOF exception found" ) 1132 main.log.error( self.name + ": " + self.handle.before ) 1133 main.cleanup() 1134 main.exit() 1135 1136 if re.search( ',\s0\%\spacket\sloss', response ): 1137 main.log.info( self.name + ": Ping between two hosts SUCCESSFUL" ) 1138 main.lastResult = main.TRUE 1139 return main.TRUE 1140 else: 1141 main.log.error( self.name + ": PACKET LOST, HOSTS NOT REACHABLE" ) 1142 main.lastResult = main.FALSE 1143 return main.FALSE
1144 1171
1172 - def yank( self, **yankargs ):
1173 """ 1174 yank a mininet switch interface to a host""" 1175 main.log.info( 'Yank the switch interface attached to a host' ) 1176 args = utilities.parse_args( [ "SW", "INTF" ], **yankargs ) 1177 sw = args[ "SW" ] if args[ "SW" ] is not None else "" 1178 intf = args[ "INTF" ] if args[ "INTF" ] is not None else "" 1179 command = "py " + str( sw ) + '.detach("' + str(intf) + '")' 1180 try: 1181 response = self.execute( 1182 cmd=command, 1183 prompt="mininet>", 1184 timeout=10 ) 1185 except pexpect.EOF: 1186 main.log.error( self.name + ": EOF exception found" ) 1187 main.log.error( self.name + ": " + self.handle.before ) 1188 main.cleanup() 1189 main.exit() 1190 return main.TRUE
1191
1192 - def plug( self, **plugargs ):
1193 """ 1194 plug the yanked mininet switch interface to a switch""" 1195 main.log.info( 'Plug the switch interface attached to a switch' ) 1196 args = utilities.parse_args( [ "SW", "INTF" ], **plugargs ) 1197 sw = args[ "SW" ] if args[ "SW" ] is not None else "" 1198 intf = args[ "INTF" ] if args[ "INTF" ] is not None else "" 1199 command = "py " + str( sw ) + '.attach("' + str(intf) + '")' 1200 try: 1201 response = self.execute( 1202 cmd=command, 1203 prompt="mininet>", 1204 timeout=10 ) 1205 except pexpect.EOF: 1206 main.log.error( self.name + ": EOF exception found" ) 1207 main.log.error( self.name + ": " + self.handle.before ) 1208 main.cleanup() 1209 main.exit() 1210 return main.TRUE
1211
1212 - def dpctl( self, **dpctlargs ):
1213 """ 1214 Run dpctl command on all switches.""" 1215 main.log.info( 'Run dpctl command on all switches' ) 1216 args = utilities.parse_args( [ "CMD", "ARGS" ], **dpctlargs ) 1217 cmd = args[ "CMD" ] if args[ "CMD" ] is not None else "" 1218 cmdargs = args[ "ARGS" ] if args[ "ARGS" ] is not None else "" 1219 command = "dpctl " + cmd + " " + str( cmdargs ) 1220 try: 1221 response = self.execute( 1222 cmd=command, 1223 prompt="mininet>", 1224 timeout=10 ) 1225 except pexpect.EOF: 1226 main.log.error( self.name + ": EOF exception found" ) 1227 main.log.error( self.name + ": " + self.handle.before ) 1228 main.cleanup() 1229 main.exit() 1230 return main.TRUE
1231
1232 - def getVersion( self ):
1233 # FIXME: What uses this? This should be refactored to get 1234 # version from MN and not some other file 1235 fileInput = path + '/lib/Mininet/INSTALL' 1236 version = super( Mininet, self ).getVersion() 1237 pattern = 'Mininet\s\w\.\w\.\w\w*' 1238 for line in open( fileInput, 'r' ).readlines(): 1239 result = re.match( pattern, line ) 1240 if result: 1241 version = result.group( 0 ) 1242 return version
1243
1244 - def getSwController( self, sw ):
1245 """ 1246 Parameters: 1247 sw: The name of an OVS switch. Example "s1" 1248 Return: 1249 The output of the command from the mininet cli 1250 or main.FALSE on timeout""" 1251 command = "sh ovs-vsctl get-controller " + str( sw ) 1252 try: 1253 response = self.execute( 1254 cmd=command, 1255 prompt="mininet>", 1256 timeout=10 ) 1257 if response: 1258 return response 1259 else: 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
1267 - def assignSwController( self, sw, ip, port="6633", ptcp="" ):
1268 """ 1269 Description: 1270 Assign switches to the controllers ( for ovs use only ) 1271 Required: 1272 sw - Name of the switch. This can be a list or a string. 1273 ip - Ip addresses of controllers. This can be a list or a string. 1274 Optional: 1275 port - ONOS use port 6633, if no list of ports is passed, then 1276 the all the controller will use 6633 as their port number 1277 ptcp - ptcp number, This can be a string or a list that has 1278 the same length as switch. This is optional and not required 1279 when using ovs switches. 1280 NOTE: If switches and ptcp are given in a list type they should have the 1281 same length and should be in the same order, Eg. sw=[ 's1' ... n ] 1282 ptcp=[ '6637' ... n ], s1 has ptcp number 6637 and so on. 1283 1284 Return: 1285 Returns main.TRUE if mininet correctly assigned switches to 1286 controllers, otherwise it will return main.FALSE or an appropriate 1287 exception(s) 1288 """ 1289 assignResult = main.TRUE 1290 # Initial ovs command 1291 commandList = [] 1292 command = "sh ovs-vsctl set-controller " 1293 onosIp = "" 1294 try: 1295 if isinstance( ip, types.StringType ): 1296 onosIp = "tcp:" + str( ip ) + ":" 1297 if isinstance( port, types.StringType ) or \ 1298 isinstance( port, types.IntType ): 1299 onosIp += str( port ) 1300 elif isinstance( port, types.ListType ): 1301 main.log.error( self.name + ": Only one controller " + 1302 "assigned and a list of ports has" + 1303 " been passed" ) 1304 return main.FALSE 1305 else: 1306 main.log.error( self.name + ": Invalid controller port " + 1307 "number. Please specify correct " + 1308 "controller port" ) 1309 return main.FALSE 1310 1311 elif isinstance( ip, types.ListType ): 1312 if isinstance( port, types.StringType ) or \ 1313 isinstance( port, types.IntType ): 1314 for ipAddress in ip: 1315 onosIp += "tcp:" + str( ipAddress ) + ":" + \ 1316 str( port ) + " " 1317 elif isinstance( port, types.ListType ): 1318 if ( len( ip ) != len( port ) ): 1319 main.log.error( self.name + ": Port list = " + 1320 str( len( port ) ) + 1321 "should be the same as controller" + 1322 " ip list = " + str( len( ip ) ) ) 1323 return main.FALSE 1324 else: 1325 onosIp = "" 1326 for ipAddress, portNum in zip( ip, port ): 1327 onosIp += "tcp:" + str( ipAddress ) + ":" + \ 1328 str( portNum ) + " " 1329 else: 1330 main.log.error( self.name + ": Invalid controller port " + 1331 "number. Please specify correct " + 1332 "controller port" ) 1333 return main.FALSE 1334 else: 1335 main.log.error( self.name + ": Invalid ip address" ) 1336 return main.FALSE 1337 1338 if isinstance( sw, types.StringType ): 1339 command += sw + " " 1340 if ptcp: 1341 if isinstance( ptcp, types.StringType ): 1342 command += "ptcp:" + str( ptcp ) + " " 1343 elif isinstance( ptcp, types.ListType ): 1344 main.log.error( self.name + ": Only one switch is " + 1345 "being set and multiple PTCP is " + 1346 "being passed " ) 1347 else: 1348 main.log.error( self.name + ": Invalid PTCP" ) 1349 ptcp = "" 1350 command += onosIp 1351 commandList.append( command ) 1352 1353 elif isinstance( sw, types.ListType ): 1354 if ptcp: 1355 if isinstance( ptcp, types.ListType ): 1356 if len( ptcp ) != len( sw ): 1357 main.log.error( self.name + ": PTCP length = " + 1358 str( len( ptcp ) ) + 1359 " is not the same as switch" + 1360 " length = " + 1361 str( len( sw ) ) ) 1362 return main.FALSE 1363 else: 1364 for switch, ptcpNum in zip( sw, ptcp ): 1365 tempCmd = "sh ovs-vsctl set-controller " 1366 tempCmd += switch + " ptcp:" + \ 1367 str( ptcpNum ) + " " 1368 tempCmd += onosIp 1369 commandList.append( tempCmd ) 1370 else: 1371 main.log.error( self.name + ": Invalid PTCP" ) 1372 return main.FALSE 1373 else: 1374 for switch in sw: 1375 tempCmd = "sh ovs-vsctl set-controller " 1376 tempCmd += switch + " " + onosIp 1377 commandList.append( tempCmd ) 1378 else: 1379 main.log.error( self.name + ": Invalid switch type " ) 1380 return main.FALSE 1381 1382 for cmd in commandList: 1383 try: 1384 self.execute( cmd=cmd, prompt="mininet>", timeout=5 ) 1385 except pexpect.TIMEOUT: 1386 main.log.error( self.name + ": pexpect.TIMEOUT found" ) 1387 return main.FALSE 1388 except pexpect.EOF: 1389 main.log.error( self.name + ": EOF exception found" ) 1390 main.log.error( self.name + ": " + self.handle.before ) 1391 main.cleanup() 1392 main.exit() 1393 return main.TRUE 1394 except Exception: 1395 main.log.exception( self.name + ": Uncaught exception!" ) 1396 main.cleanup() 1397 main.exit()
1398
1399 - def deleteSwController( self, sw ):
1400 """ 1401 Removes the controller target from sw""" 1402 command = "sh ovs-vsctl del-controller " + str( sw ) 1403 try: 1404 response = self.execute( 1405 cmd=command, 1406 prompt="mininet>", 1407 timeout=10 ) 1408 except pexpect.EOF: 1409 main.log.error( self.name + ": EOF exception found" ) 1410 main.log.error( self.name + ": " + self.handle.before ) 1411 main.cleanup() 1412 main.exit() 1413 else: 1414 main.log.info( response )
1415
1416 - def addSwitch( self, sw, **kwargs ):
1417 """ 1418 adds a switch to the mininet topology 1419 NOTE: This uses a custom mn function. MN repo should be on 1420 dynamic_topo branch 1421 NOTE: cannot currently specify what type of switch 1422 required params: 1423 sw = name of the new switch as a string 1424 optional keywords: 1425 dpid = "dpid" 1426 returns: main.FALSE on an error, else main.TRUE 1427 """ 1428 dpid = kwargs.get( 'dpid', '' ) 1429 command = "addswitch " + str( sw ) + " " + str( dpid ) 1430 try: 1431 response = self.execute( 1432 cmd=command, 1433 prompt="mininet>", 1434 timeout=10 ) 1435 if re.search( "already exists!", response ): 1436 main.log.warn( response ) 1437 return main.FALSE 1438 elif re.search( "Error", response ): 1439 main.log.warn( response ) 1440 return main.FALSE 1441 elif re.search( "usage:", response ): 1442 main.log.warn( response ) 1443 return main.FALSE 1444 else: 1445 return main.TRUE 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
1452 - def delSwitch( self, sw ):
1453 """ 1454 delete a switch from the mininet topology 1455 NOTE: This uses a custom mn function. MN repo should be on 1456 dynamic_topo branch 1457 required params: 1458 sw = name of the switch as a string 1459 returns: main.FALSE on an error, else main.TRUE""" 1460 command = "delswitch " + str( sw ) 1461 try: 1462 response = self.execute( 1463 cmd=command, 1464 prompt="mininet>", 1465 timeout=10 ) 1466 if re.search( "no switch named", response ): 1467 main.log.warn( response ) 1468 return main.FALSE 1469 elif re.search( "Error", response ): 1470 main.log.warn( response ) 1471 return main.FALSE 1472 elif re.search( "usage:", response ): 1473 main.log.warn( response ) 1474 return main.FALSE 1475 else: 1476 return main.TRUE 1477 except pexpect.EOF: 1478 main.log.error( self.name + ": EOF exception found" ) 1479 main.log.error( self.name + ": " + self.handle.before ) 1480 main.cleanup() 1481 main.exit()
1482 1515 1547
1548 - def addHost( self, hostname, **kwargs ):
1549 """ 1550 Add a host to the mininet topology 1551 NOTE: This uses a custom mn function. MN repo should be on 1552 dynamic_topo branch 1553 NOTE: cannot currently specify what type of host 1554 required params: 1555 hostname = the string hostname 1556 optional key-value params 1557 switch = "switch name" 1558 returns: main.FALSE on an error, else main.TRUE 1559 """ 1560 switch = kwargs.get( 'switch', '' ) 1561 command = "addhost " + str( hostname ) + " " + str( switch ) 1562 try: 1563 response = self.execute( 1564 cmd=command, 1565 prompt="mininet>", 1566 timeout=10 ) 1567 if re.search( "already exists!", response ): 1568 main.log.warn( response ) 1569 return main.FALSE 1570 elif re.search( "doesnt exists!", response ): 1571 main.log.warn( response ) 1572 return main.FALSE 1573 elif re.search( "Error", response ): 1574 main.log.warn( response ) 1575 return main.FALSE 1576 elif re.search( "usage:", response ): 1577 main.log.warn( response ) 1578 return main.FALSE 1579 else: 1580 return main.TRUE 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
1587 - def delHost( self, hostname ):
1588 """ 1589 delete a host from the mininet topology 1590 NOTE: This uses a custom mn function. MN repo should be on 1591 dynamic_topo branch 1592 NOTE: this uses a custom mn function 1593 required params: 1594 hostname = the string hostname 1595 returns: main.FALSE on an error, else main.TRUE""" 1596 command = "delhost " + str( hostname ) 1597 try: 1598 response = self.execute( 1599 cmd=command, 1600 prompt="mininet>", 1601 timeout=10 ) 1602 if re.search( "no host named", response ): 1603 main.log.warn( response ) 1604 return main.FALSE 1605 elif re.search( "Error", response ): 1606 main.log.warn( response ) 1607 return main.FALSE 1608 elif re.search( "usage:", response ): 1609 main.log.warn( response ) 1610 return main.FALSE 1611 else: 1612 return main.TRUE 1613 except pexpect.EOF: 1614 main.log.error( self.name + ": EOF exception found" ) 1615 main.log.error( self.name + ": " + self.handle.before ) 1616 main.cleanup() 1617 main.exit()
1618
1619 - def disconnect( self ):
1620 """ 1621 Called at the end of the test to stop the mininet and 1622 disconnect the handle. 1623 """ 1624 self.handle.sendline( '' ) 1625 i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ], 1626 timeout=2 ) 1627 response = main.TRUE 1628 if i == 0: 1629 response = self.stopNet() 1630 elif i == 1: 1631 return main.TRUE 1632 # print "Disconnecting Mininet" 1633 if self.handle: 1634 self.handle.sendline( "exit" ) 1635 self.handle.expect( "exit" ) 1636 self.handle.expect( "(.*)" ) 1637 else: 1638 main.log.error( "Connection failed to the host" ) 1639 return response
1640
1641 - def stopNet( self, fileName="", timeout=5 ):
1642 """ 1643 Stops mininet. 1644 Returns main.TRUE if the mininet successfully stops and 1645 main.FALSE if the pexpect handle does not exist. 1646 1647 Will cleanup and exit the test if mininet fails to stop 1648 """ 1649 main.log.info( self.name + ": Stopping mininet..." ) 1650 response = '' 1651 if self.handle: 1652 try: 1653 self.handle.sendline( "" ) 1654 i = self.handle.expect( [ 'mininet>', 1655 '\$', 1656 pexpect.EOF, 1657 pexpect.TIMEOUT ], 1658 timeout ) 1659 if i == 0: 1660 main.log.info( "Exiting mininet..." ) 1661 response = self.execute( 1662 cmd="exit", 1663 prompt="(.*)", 1664 timeout=120 ) 1665 main.log.info( self.name + ": Stopped" ) 1666 self.handle.sendline( "sudo mn -c" ) 1667 response = main.TRUE 1668 1669 if i == 1: 1670 main.log.info( " Mininet trying to exit while not " + 1671 "in the mininet prompt" ) 1672 elif i == 2: 1673 main.log.error( "Something went wrong exiting mininet" ) 1674 elif i == 3: # timeout 1675 main.log.error( "Something went wrong exiting mininet " + 1676 "TIMEOUT" ) 1677 1678 if fileName: 1679 self.handle.sendline( "" ) 1680 self.handle.expect( '\$' ) 1681 self.handle.sendline( 1682 "sudo kill -9 \`ps -ef | grep \"" + 1683 fileName + 1684 "\" | grep -v grep | awk '{print $2}'\`" ) 1685 except pexpect.EOF: 1686 main.log.error( self.name + ": EOF exception found" ) 1687 main.log.error( self.name + ": " + self.handle.before ) 1688 main.cleanup() 1689 main.exit() 1690 else: 1691 main.log.error( self.name + ": Connection failed to the host" ) 1692 response = main.FALSE 1693 return response
1694
1695 - def arping( self, host="", ip="10.128.20.211", ethDevice="" ):
1696 """ 1697 Description: 1698 Sends arp message from mininet host for hosts discovery 1699 Required: 1700 host - hosts name 1701 Optional: 1702 ip - ip address that does not exist in the network so there would 1703 be no reply. 1704 """ 1705 if ethDevice: 1706 ethDevice = '-I ' + ethDevice + ' ' 1707 cmd = " py " + host + ".cmd(\"arping -c 1 " + ethDevice + ip + "\")" 1708 try: 1709 main.log.warn( "Sending: " + cmd ) 1710 self.handle.sendline( cmd ) 1711 response = self.handle.before 1712 self.handle.sendline( "" ) 1713 self.handle.expect( "mininet>" ) 1714 return main.TRUE 1715 1716 except pexpect.EOF: 1717 main.log.error( self.name + ": EOF exception found" ) 1718 main.log.error( self.name + ": " + self.handle.before ) 1719 main.cleanup() 1720 main.exit()
1721
1722 - def decToHex( self, num ):
1723 return hex( num ).split( 'x' )[ 1 ]
1724
1725 - def getSwitchFlowCount( self, switch ):
1726 """ 1727 return the Flow Count of the switch""" 1728 if self.handle: 1729 cmd = "sh ovs-ofctl dump-aggregate %s" % switch 1730 try: 1731 response = self.execute( 1732 cmd=cmd, 1733 prompt="mininet>", 1734 timeout=10 ) 1735 except pexpect.EOF: 1736 main.log.error( self.name + ": EOF exception found" ) 1737 main.log.error( self.name + " " + self.handle.before ) 1738 main.cleanup() 1739 main.exit() 1740 pattern = "flow_count=(\d+)" 1741 result = re.search( pattern, response, re.MULTILINE ) 1742 if result is None: 1743 main.log.info( 1744 "Couldn't find flows on switch %s, found: %s" % 1745 ( switch, response ) ) 1746 return main.FALSE 1747 return result.group( 1 ) 1748 else: 1749 main.log.error( "Connection failed to the Mininet host" )
1750
1751 - def checkFlows( self, sw, dumpFormat=None ):
1752 if dumpFormat: 1753 command = "sh ovs-ofctl -F " + \ 1754 dumpFormat + " dump-flows " + str( sw ) 1755 else: 1756 command = "sh ovs-ofctl dump-flows " + str( sw ) 1757 try: 1758 response = self.execute( 1759 cmd=command, 1760 prompt="mininet>", 1761 timeout=10 ) 1762 return response 1763 except pexpect.EOF: 1764 main.log.error( self.name + ": EOF exception found" ) 1765 main.log.error( self.name + ": " + self.handle.before ) 1766 main.cleanup() 1767 main.exit()
1768
1769 - def getFlowTable( self, protoVersion, sw ):
1770 """ 1771 Returns certain fields of an OVS flow table. Will force output to 1772 either OF 1.0 or 1.3 format for consistency. 1773 1774 TODO add option to look at cookies. ignoring them for now 1775 1776 NOTE: Use format to force consistent flow table output across 1777 versions 1778 """ 1779 try: 1780 self.handle.sendline( "" ) 1781 self.handle.expect( "mininet>" ) 1782 command = "sh ovs-ofctl dump-flows " + sw 1783 if protoVersion == 1.0: 1784 command += " -F OpenFlow10-table_id | awk '{OFS=\",\" ;" +\ 1785 " print $1 $3 $6 $7 $8}' | " 1786 elif protoVersion == 1.3: 1787 command += " -O OpenFlow13 | awk '{OFS=\",\" ;" +\ 1788 " print $1 $3 $6 $7}' | " 1789 else: 1790 main.log.error( 1791 "Unknown protoVersion in getFlowTable(). given: (" + 1792 str( type( protoVersion ) ) + 1793 ") '" + str( protoVersion ) + "'" ) 1794 return None 1795 command += "cut -d ',' -f 2- | sort -n -k1 -r" 1796 self.handle.sendline( command ) 1797 self.handle.expect( "sort" ) 1798 self.handle.expect( "OFPST_FLOW" ) 1799 response = self.handle.before 1800 return response 1801 except pexpect.EOF: 1802 main.log.error( self.name + ": EOF exception found" ) 1803 main.log.error( self.name + ": " + self.handle.before ) 1804 main.cleanup() 1805 main.exit() 1806 except pexpect.TIMEOUT: 1807 main.log.exception( self.name + ": Timeout exception: " ) 1808 return None
1809
1810 - def flowComp( self, flow1, flow2 ):
1811 if flow1 == flow2: 1812 return main.TRUE 1813 else: 1814 main.log.info( "Flow tables do not match, printing tables:" ) 1815 main.log.info( "Flow Table 1:" ) 1816 main.log.info( flow1 ) 1817 main.log.info( "Flow Table 2:" ) 1818 main.log.info( flow2 ) 1819 return main.FALSE
1820
1821 - def startTcpdump( self, filename, intf="eth0", port="port 6633" ):
1822 """ 1823 Runs tpdump on an interface and saves the file 1824 intf can be specified, or the default eth0 is used""" 1825 try: 1826 self.handle.sendline( "" ) 1827 self.handle.expect( "mininet>" ) 1828 self.handle.sendline( 1829 "sh sudo tcpdump -n -i " + 1830 intf + 1831 " " + 1832 port + 1833 " -w " + 1834 filename.strip() + 1835 " &" ) 1836 self.handle.sendline( "" ) 1837 i = self.handle.expect( [ 'No\ssuch\device', 1838 'listening\son', 1839 pexpect.TIMEOUT, 1840 "mininet>" ], 1841 timeout=10 ) 1842 main.log.warn( self.handle.before + self.handle.after ) 1843 self.handle.sendline( "" ) 1844 self.handle.expect( "mininet>" ) 1845 if i == 0: 1846 main.log.error( 1847 self.name + 1848 ": tcpdump - No such device exists. " + 1849 "tcpdump attempted on: " + 1850 intf ) 1851 return main.FALSE 1852 elif i == 1: 1853 main.log.info( self.name + ": tcpdump started on " + intf ) 1854 return main.TRUE 1855 elif i == 2: 1856 main.log.error( 1857 self.name + 1858 ": tcpdump command timed out! Check interface name," + 1859 " given interface was: " + 1860 intf ) 1861 return main.FALSE 1862 elif i == 3: 1863 main.log.info( self.name + ": " + self.handle.before ) 1864 return main.TRUE 1865 else: 1866 main.log.error( self.name + ": tcpdump - unexpected response" ) 1867 return main.FALSE 1868 except pexpect.EOF: 1869 main.log.error( self.name + ": EOF exception found" ) 1870 main.log.error( self.name + ": " + self.handle.before ) 1871 main.cleanup() 1872 main.exit() 1873 except Exception: 1874 main.log.exception( self.name + ": Uncaught exception!" ) 1875 main.cleanup() 1876 main.exit()
1877
1878 - def stopTcpdump( self ):
1879 """ 1880 pkills tcpdump""" 1881 try: 1882 self.handle.sendline( "sh sudo pkill tcpdump" ) 1883 self.handle.expect( "mininet>" ) 1884 self.handle.sendline( "" ) 1885 self.handle.expect( "mininet>" ) 1886 except pexpect.EOF: 1887 main.log.error( self.name + ": EOF exception found" ) 1888 main.log.error( self.name + ": " + self.handle.before ) 1889 main.cleanup() 1890 main.exit() 1891 except Exception: 1892 main.log.exception( self.name + ": Uncaught exception!" ) 1893 main.cleanup() 1894 main.exit()
1895
1896 - def getPorts( self, nodeName, verbose=False ):
1897 """ 1898 Read ports from a Mininet switch. 1899 1900 Returns a json structure containing information about the 1901 ports of the given switch. 1902 """ 1903 response = self.getInterfaces( nodeName ) 1904 # TODO: Sanity check on response. log if no such switch exists 1905 ports = [] 1906 for line in response.split( "\n" ): 1907 if not line.startswith( "name=" ): 1908 continue 1909 portVars = {} 1910 for var in line.split( "," ): 1911 key, value = var.split( "=" ) 1912 portVars[ key ] = value 1913 isUp = portVars.pop( 'enabled', "True" ) 1914 isUp = "True" in isUp 1915 if verbose: 1916 main.log.info( "Reading switch port %s(%s)" % 1917 ( portVars[ 'name' ], portVars[ 'mac' ] ) ) 1918 mac = portVars[ 'mac' ] 1919 if mac == 'None': 1920 mac = None 1921 ips = [] 1922 ip = portVars[ 'ip' ] 1923 if ip == 'None': 1924 ip = None 1925 ips.append( ip ) 1926 name = portVars[ 'name' ] 1927 if name == 'None': 1928 name = None 1929 portRe = r'[^\-]\d\-eth(?P<port>\d+)' 1930 if name == 'lo': 1931 portNo = 0xfffe # TODO: 1.0 value - Should we just return lo? 1932 else: 1933 portNo = re.search( portRe, name ).group( 'port' ) 1934 ports.append( { 'of_port': portNo, 1935 'mac': str( mac ).replace( '\'', '' ), 1936 'name': name, 1937 'ips': ips, 1938 'enabled': isUp } ) 1939 return ports
1940
1941 - def getSwitches( self, verbose=False ):
1942 """ 1943 Read switches from Mininet. 1944 1945 Returns a dictionary whose keys are the switch names and the value is 1946 a dictionary containing information about the switch. 1947 """ 1948 # NOTE: To support new Mininet switch classes, just append the new 1949 # class to the switchClasses variable 1950 1951 # Regex patterns to parse 'dump' output 1952 # Example Switches: 1953 # <OVSSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=5238> 1954 # <OVSSwitch{ 'protocols': 'OpenFlow10' } s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=25974> 1955 # <OVSSwitchNS s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None,s1-eth3:None pid=22550> 1956 # <OVSBridge s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=26830> 1957 # <UserSwitch s1: lo:127.0.0.1,s1-eth1:None,s1-eth2:None pid=14737> 1958 switchClasses = r"(OVSSwitch)|(OVSBridge)|(OVSSwitchNS)|(IVSSwitch)|(LinuxBridge)|(UserSwitch)" 1959 swRE = r"<(?P<class>" + switchClasses + r")" +\ 1960 r"(?P<options>\{.*\})?\s" +\ 1961 r"(?P<name>[^:]+)\:\s" +\ 1962 r"(?P<ports>([^,]+,)*[^,\s]+)" +\ 1963 r"\spid=(?P<pid>(\d)+)" 1964 # Update mn port info 1965 self.update() 1966 output = {} 1967 dump = self.dump().split( "\n" ) 1968 for line in dump: 1969 result = re.search( swRE, line, re.I ) 1970 if result: 1971 name = result.group( 'name' ) 1972 dpid = str( self.getSwitchDPID( name ) ).zfill( 16 ) 1973 pid = result.group( 'pid' ) 1974 swClass = result.group( 'class' ) 1975 options = result.group( 'options' ) 1976 if verbose: 1977 main.log.info( "Reading switch %s(%s)" % ( name, dpid ) ) 1978 ports = self.getPorts( name ) 1979 output[ name ] = { "dpid": dpid, 1980 "ports": ports, 1981 "swClass": swClass, 1982 "pid": pid, 1983 "options": options } 1984 return output
1985
1986 - def getHosts( self, verbose=False ):
1987 """ 1988 Read hosts from Mininet. 1989 1990 Returns a dictionary whose keys are the host names and the value is 1991 a dictionary containing information about the host. 1992 """ 1993 # Regex patterns to parse dump output 1994 # Example host: <Host h1: h1-eth0:10.0.0.1 pid=5227> 1995 # <Host h1: pid=12725> 1996 # <VLANHost h12: h12-eth0.100.100.100:100.1.0.3 pid=30186> 1997 # <dualStackHost h19: h19-eth0:10.1.0.9 pid=30200> 1998 # <IPv6Host h18: h18-eth0:10.0.0.18 pid=30198> 1999 # NOTE: Does not correctly match hosts with multi-links 2000 # <Host h2: h2-eth0:10.0.0.2,h2-eth1:10.0.1.2 pid=14386> 2001 # FIXME: Fix that 2002 hostRE = r"Host\s(?P<name>[^:]+)\:((\s(?P<ifname>[^:]+)\:" +\ 2003 "(?P<ip>[^\s]+))|(\s)\spid=(?P<pid>[^>]+))" 2004 # update mn port info 2005 self.update() 2006 # Get mininet dump 2007 dump = self.dump().split( "\n" ) 2008 hosts = {} 2009 for line in dump: 2010 if "Host" in line : 2011 result = re.search( hostRE, line ) 2012 name = result.group( 'name' ) 2013 interfaces = [] 2014 response = self.getInterfaces( name ) 2015 # Populate interface info 2016 for line in response.split( "\n" ): 2017 if line.startswith( "name=" ): 2018 portVars = {} 2019 for var in line.split( "," ): 2020 key, value = var.split( "=" ) 2021 portVars[ key ] = value 2022 isUp = portVars.pop( 'enabled', "True" ) 2023 isUp = "True" in isUp 2024 if verbose: 2025 main.log.info( "Reading host port %s(%s)" % 2026 ( portVars[ 'name' ], 2027 portVars[ 'mac' ] ) ) 2028 mac = portVars[ 'mac' ] 2029 if mac == 'None': 2030 mac = None 2031 ips = [] 2032 ip = portVars[ 'ip' ] 2033 if ip == 'None': 2034 ip = None 2035 ips.append( ip ) 2036 intfName = portVars[ 'name' ] 2037 if name == 'None': 2038 name = None 2039 interfaces.append( { 2040 "name": intfName, 2041 "ips": ips, 2042 "mac": str( mac ), 2043 "isUp": isUp } ) 2044 hosts[ name ] = { "interfaces": interfaces } 2045 return hosts
2046 2084
2085 - def compareSwitches( self, switches, switchesJson, portsJson ):
2086 """ 2087 Compare mn and onos switches 2088 switchesJson: parsed json object from the onos devices api 2089 2090 Dependencies: 2091 1. numpy - "sudo pip install numpy" 2092 """ 2093 from numpy import uint64 2094 # created sorted list of dpid's in MN and ONOS for comparison 2095 mnDPIDs = [] 2096 for swName, switch in switches.iteritems(): 2097 mnDPIDs.append( switch[ 'dpid' ].lower() ) 2098 mnDPIDs.sort() 2099 if switchesJson == "": # if rest call fails 2100 main.log.error( 2101 self.name + 2102 ".compareSwitches(): Empty JSON object given from ONOS" ) 2103 return main.FALSE 2104 onos = switchesJson 2105 onosDPIDs = [] 2106 for switch in onos: 2107 if switch[ 'available' ]: 2108 onosDPIDs.append( 2109 switch[ 'id' ].replace( 2110 ":", 2111 '' ).replace( 2112 "of", 2113 '' ).lower() ) 2114 onosDPIDs.sort() 2115 2116 if mnDPIDs != onosDPIDs: 2117 switchResults = main.FALSE 2118 main.log.error( "Switches in MN but not in ONOS:" ) 2119 list1 = [ switch for switch in mnDPIDs if switch not in onosDPIDs ] 2120 main.log.error( str( list1 ) ) 2121 main.log.error( "Switches in ONOS but not in MN:" ) 2122 list2 = [ switch for switch in onosDPIDs if switch not in mnDPIDs ] 2123 main.log.error( str( list2 ) ) 2124 else: # list of dpid's match in onos and mn 2125 switchResults = main.TRUE 2126 finalResults = switchResults 2127 2128 # FIXME: this does not look for extra ports in ONOS, only checks that 2129 # ONOS has what is in MN 2130 portsResults = main.TRUE 2131 2132 # PORTS 2133 for name, mnSwitch in switches.iteritems(): 2134 mnPorts = [] 2135 onosPorts = [] 2136 switchResult = main.TRUE 2137 for port in mnSwitch[ 'ports' ]: 2138 if port[ 'enabled' ]: 2139 mnPorts.append( int( port[ 'of_port' ] ) ) 2140 for onosSwitch in portsJson: 2141 if onosSwitch[ 'device' ][ 'available' ]: 2142 if onosSwitch[ 'device' ][ 'id' ].replace( 2143 ':', 2144 '' ).replace( 2145 "of", 2146 '' ) == mnSwitch[ 'dpid' ]: 2147 for port in onosSwitch[ 'ports' ]: 2148 if port[ 'isEnabled' ]: 2149 if port[ 'port' ] == 'local': 2150 # onosPorts.append( 'local' ) 2151 onosPorts.append( long( uint64( -2 ) ) ) 2152 else: 2153 onosPorts.append( int( port[ 'port' ] ) ) 2154 break 2155 mnPorts.sort( key=float ) 2156 onosPorts.sort( key=float ) 2157 2158 mnPortsLog = mnPorts 2159 onosPortsLog = onosPorts 2160 mnPorts = [ x for x in mnPorts ] 2161 onosPorts = [ x for x in onosPorts ] 2162 2163 # TODO: handle other reserved port numbers besides LOCAL 2164 # NOTE: Reserved ports 2165 # Local port: -2 in Openflow, ONOS shows 'local', we store as 2166 # long( uint64( -2 ) ) 2167 for mnPort in mnPortsLog: 2168 if mnPort in onosPorts: 2169 # don't set results to true here as this is just one of 2170 # many checks and it might override a failure 2171 mnPorts.remove( mnPort ) 2172 onosPorts.remove( mnPort ) 2173 2174 # NOTE: OVS reports this as down since there is no link 2175 # So ignoring these for now 2176 # TODO: Come up with a better way of handling these 2177 if 65534 in mnPorts: 2178 mnPorts.remove( 65534 ) 2179 if long( uint64( -2 ) ) in onosPorts: 2180 onosPorts.remove( long( uint64( -2 ) ) ) 2181 if len( mnPorts ): # the ports of this switch don't match 2182 switchResult = main.FALSE 2183 main.log.warn( "Ports in MN but not ONOS: " + str( mnPorts ) ) 2184 if len( onosPorts ): # the ports of this switch don't match 2185 switchResult = main.FALSE 2186 main.log.warn( 2187 "Ports in ONOS but not MN: " + 2188 str( onosPorts ) ) 2189 if switchResult == main.FALSE: 2190 main.log.error( 2191 "The list of ports for switch %s(%s) does not match:" % 2192 ( name, mnSwitch[ 'dpid' ] ) ) 2193 main.log.warn( "mn_ports[] = " + str( mnPortsLog ) ) 2194 main.log.warn( "onos_ports[] = " + str( onosPortsLog ) ) 2195 portsResults = portsResults and switchResult 2196 finalResults = finalResults and portsResults 2197 return finalResults
2198 2311
2312 - def compareHosts( self, hosts, hostsJson ):
2313 """ 2314 Compare mn and onos Hosts. 2315 Since Mininet hosts are quiet, ONOS will only know of them when they 2316 speak. For this reason, we will only check that the hosts in ONOS 2317 stores are in Mininet, and not vice versa. 2318 2319 Arguments: 2320 hostsJson: parsed json object from the onos hosts api 2321 Returns: 2322 """ 2323 import json 2324 hostResults = main.TRUE 2325 for onosHost in hostsJson: 2326 onosMAC = onosHost[ 'mac' ].lower() 2327 match = False 2328 for mnHost, info in hosts.iteritems(): 2329 for mnIntf in info[ 'interfaces' ]: 2330 if onosMAC == mnIntf[ 'mac' ].lower(): 2331 match = True 2332 for ip in mnIntf[ 'ips' ]: 2333 if ip in onosHost[ 'ipAddresses' ]: 2334 pass # all is well 2335 else: 2336 # misssing ip 2337 main.log.error( "ONOS host " + 2338 onosHost[ 'id' ] + 2339 " has a different IP(" + 2340 str( onosHost[ 'ipAddresses' ] ) + 2341 ") than the Mininet host(" + 2342 str( ip ) + 2343 ")." ) 2344 output = json.dumps( 2345 onosHost, 2346 sort_keys=True, 2347 indent=4, 2348 separators=( ',', ': ' ) ) 2349 main.log.info( output ) 2350 hostResults = main.FALSE 2351 if not match: 2352 hostResults = main.FALSE 2353 main.log.error( "ONOS host " + onosHost[ 'id' ] + " has no " + 2354 "corresponding Mininet host." ) 2355 output = json.dumps( onosHost, 2356 sort_keys=True, 2357 indent=4, 2358 separators=( ',', ': ' ) ) 2359 main.log.info( output ) 2360 return hostResults
2361
2362 - def getHostsOld( self ):
2363 """ 2364 Returns a list of all hosts 2365 Don't ask questions just use it""" 2366 self.handle.sendline( "" ) 2367 self.handle.expect( "mininet>" ) 2368 2369 self.handle.sendline( "py [ host.name for host in net.hosts ]" ) 2370 self.handle.expect( "mininet>" ) 2371 2372 handlePy = self.handle.before 2373 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ] 2374 handlePy = handlePy.rstrip() 2375 2376 self.handle.sendline( "" ) 2377 self.handle.expect( "mininet>" ) 2378 2379 hostStr = handlePy.replace( "]", "" ) 2380 hostStr = hostStr.replace( "'", "" ) 2381 hostStr = hostStr.replace( "[", "" ) 2382 hostStr = hostStr.replace( " ", "" ) 2383 hostList = hostStr.split( "," ) 2384 2385 return hostList
2386
2387 - def getSwitch( self ):
2388 """ 2389 Returns a list of all switches 2390 Again, don't ask question just use it... 2391 """ 2392 # get host list... 2393 hostList = self.getHosts() 2394 # Make host set 2395 hostSet = set( hostList ) 2396 2397 # Getting all the nodes in mininet 2398 self.handle.sendline( "" ) 2399 self.handle.expect( "mininet>" ) 2400 2401 self.handle.sendline( "py [ node.name for node in net.values() ]" ) 2402 self.handle.expect( "mininet>" ) 2403 2404 handlePy = self.handle.before 2405 handlePy = handlePy.split( "]\r\n", 1 )[ 1 ] 2406 handlePy = handlePy.rstrip() 2407 2408 self.handle.sendline( "" ) 2409 self.handle.expect( "mininet>" ) 2410 2411 nodesStr = handlePy.replace( "]", "" ) 2412 nodesStr = nodesStr.replace( "'", "" ) 2413 nodesStr = nodesStr.replace( "[", "" ) 2414 nodesStr = nodesStr.replace( " ", "" ) 2415 nodesList = nodesStr.split( "," ) 2416 2417 nodesSet = set( nodesList ) 2418 # discarding default controller(s) node 2419 nodesSet.discard( 'c0' ) 2420 nodesSet.discard( 'c1' ) 2421 nodesSet.discard( 'c2' ) 2422 2423 switchSet = nodesSet - hostSet 2424 switchList = list( switchSet ) 2425 2426 return switchList
2427
2428 - def update( self ):
2429 """ 2430 updates the port address and status information for 2431 each port in mn""" 2432 # TODO: Add error checking. currently the mininet command has no output 2433 main.log.info( "Updating MN port information" ) 2434 try: 2435 self.handle.sendline( "" ) 2436 self.handle.expect( "mininet>" ) 2437 2438 self.handle.sendline( "update" ) 2439 self.handle.expect( "update" ) 2440 self.handle.expect( "mininet>" ) 2441 2442 self.handle.sendline( "" ) 2443 self.handle.expect( "mininet>" ) 2444 2445 return main.TRUE 2446 except pexpect.EOF: 2447 main.log.error( self.name + ": EOF exception found" ) 2448 main.log.error( self.name + ": " + self.handle.before ) 2449 main.cleanup() 2450 main.exit()
2451
2452 - def assignVLAN( self, host, intf, vlan ):
2453 """ 2454 Add vlan tag to a host. 2455 Dependencies: 2456 This class depends on the "vlan" package 2457 $ sudo apt-get install vlan 2458 Configuration: 2459 Load the 8021q module into the kernel 2460 $sudo modprobe 8021q 2461 2462 To make this setup permanent: 2463 $ sudo su -c 'echo "8021q" >> /etc/modules' 2464 """ 2465 if self.handle: 2466 try: 2467 # get the ip address of the host 2468 main.log.info( "Get the ip address of the host" ) 2469 ipaddr = self.getIPAddress( host ) 2470 print repr( ipaddr ) 2471 2472 # remove IP from interface intf 2473 # Ex: h1 ifconfig h1-eth0 inet 0 2474 main.log.info( "Remove IP from interface " ) 2475 cmd2 = host + " ifconfig " + intf + " " + " inet 0 " 2476 self.handle.sendline( cmd2 ) 2477 self.handle.expect( "mininet>" ) 2478 response = self.handle.before 2479 main.log.info( "====> %s ", response ) 2480 2481 # create VLAN interface 2482 # Ex: h1 vconfig add h1-eth0 100 2483 main.log.info( "Create Vlan" ) 2484 cmd3 = host + " vconfig add " + intf + " " + vlan 2485 self.handle.sendline( cmd3 ) 2486 self.handle.expect( "mininet>" ) 2487 response = self.handle.before 2488 main.log.info( "====> %s ", response ) 2489 2490 # assign the host's IP to the VLAN interface 2491 # Ex: h1 ifconfig h1-eth0.100 inet 10.0.0.1 2492 main.log.info( "Assign the host IP to the vlan interface" ) 2493 vintf = intf + "." + vlan 2494 cmd4 = host + " ifconfig " + vintf + " " + " inet " + ipaddr 2495 self.handle.sendline( cmd4 ) 2496 self.handle.expect( "mininet>" ) 2497 response = self.handle.before 2498 main.log.info( "====> %s ", response ) 2499 2500 return main.TRUE 2501 except pexpect.EOF: 2502 main.log.error( self.name + ": EOF exception found" ) 2503 main.log.error( self.name + ": " + self.handle.before ) 2504 return main.FALSE
2505 2506 if __name__ != "__main__": 2507 import sys 2508 sys.modules[ __name__ ] = MininetCliDriver() 2509