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

Source Code for Module TestON.drivers.common.cli.onosclidriver

   1  #!/usr/bin/env python 
   2   
   3  """ 
   4  This driver enters the onos> prompt to issue commands. 
   5   
   6  Please follow the coding style demonstrated by existing 
   7  functions and document properly. 
   8   
   9  If you are a contributor to the driver, please 
  10  list your email here for future contact: 
  11   
  12  jhall@onlab.us 
  13  andrew@onlab.us 
  14  shreya@onlab.us 
  15   
  16  OCT 13 2014 
  17   
  18  """ 
  19  import pexpect 
  20  import re 
  21  import json 
  22  import types 
  23  import time 
  24  import os 
  25  from drivers.common.clidriver import CLI 
  26   
  27   
28 -class OnosCliDriver( CLI ):
29
30 - def __init__( self ):
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 cli. 42 """ 43 try: 44 for key in connectargs: 45 vars( self )[ key ] = connectargs[ key ] 46 self.home = "~/onos" 47 for key in self.options: 48 if key == "home": 49 self.home = self.options[ 'home' ] 50 break 51 if self.home is None or self.home == "": 52 self.home = "~/onos" 53 54 for key in self.options: 55 if key == 'onosIp': 56 self.onosIp = self.options[ 'onosIp' ] 57 break 58 59 self.name = self.options[ 'name' ] 60 61 try: 62 if os.getenv( str( self.ip_address ) ) != None: 63 self.ip_address = os.getenv( str( self.ip_address ) ) 64 else: 65 main.log.info( self.name + 66 ": Trying to connect to " + 67 self.ip_address ) 68 69 except KeyError: 70 main.log.info( "Invalid host name," + 71 " connecting to local host instead" ) 72 self.ip_address = 'localhost' 73 except Exception as inst: 74 main.log.error( "Uncaught exception: " + str( inst ) ) 75 76 self.handle = super( OnosCliDriver, self ).connect( 77 user_name=self.user_name, 78 ip_address=self.ip_address, 79 port=self.port, 80 pwd=self.pwd, 81 home=self.home ) 82 83 self.handle.sendline( "cd " + self.home ) 84 self.handle.expect( "\$" ) 85 if self.handle: 86 return self.handle 87 else: 88 main.log.info( "NO ONOS HANDLE" ) 89 return main.FALSE 90 except TypeError: 91 main.log.exception( self.name + ": Object not as expected" ) 92 return None 93 except pexpect.EOF: 94 main.log.error( self.name + ": EOF exception found" ) 95 main.log.error( self.name + ": " + self.handle.before ) 96 main.cleanup() 97 main.exit() 98 except Exception: 99 main.log.exception( self.name + ": Uncaught exception!" ) 100 main.cleanup() 101 main.exit()
102
103 - def disconnect( self ):
104 """ 105 Called when Test is complete to disconnect the ONOS handle. 106 """ 107 response = main.TRUE 108 try: 109 if self.handle: 110 i = self.logout() 111 if i == main.TRUE: 112 self.handle.sendline( "" ) 113 self.handle.expect( "\$" ) 114 self.handle.sendline( "exit" ) 115 self.handle.expect( "closed" ) 116 except TypeError: 117 main.log.exception( self.name + ": Object not as expected" ) 118 response = main.FALSE 119 except pexpect.EOF: 120 main.log.error( self.name + ": EOF exception found" ) 121 main.log.error( self.name + ": " + self.handle.before ) 122 except ValueError: 123 main.log.exception( "Exception in disconnect of " + self.name ) 124 response = main.TRUE 125 except Exception: 126 main.log.exception( self.name + ": Connection failed to the host" ) 127 response = main.FALSE 128 return response
129
130 - def logout( self ):
131 """ 132 Sends 'logout' command to ONOS cli 133 Returns main.TRUE if exited CLI and 134 main.FALSE on timeout (not guranteed you are disconnected) 135 None on TypeError 136 Exits test on unknown error or pexpect exits unexpectedly 137 """ 138 try: 139 if self.handle: 140 self.handle.sendline( "" ) 141 i = self.handle.expect( [ "onos>", "\$", pexpect.TIMEOUT ], 142 timeout=10 ) 143 if i == 0: # In ONOS CLI 144 self.handle.sendline( "logout" ) 145 self.handle.expect( "\$" ) 146 return main.TRUE 147 elif i == 1: # not in CLI 148 return main.TRUE 149 elif i == 3: # Timeout 150 return main.FALSE 151 else: 152 return main.TRUE 153 except TypeError: 154 main.log.exception( self.name + ": Object not as expected" ) 155 return None 156 except pexpect.EOF: 157 main.log.error( self.name + ": eof exception found" ) 158 main.log.error( self.name + ": " + self.handle.before ) 159 main.cleanup() 160 main.exit() 161 except ValueError: 162 main.log.error( self.name + 163 "ValueError exception in logout method" ) 164 except Exception: 165 main.log.exception( self.name + ": Uncaught exception!" ) 166 main.cleanup() 167 main.exit()
168
169 - def setCell( self, cellname ):
170 """ 171 Calls 'cell <name>' to set the environment variables on ONOSbench 172 173 Before issuing any cli commands, set the environment variable first. 174 """ 175 try: 176 if not cellname: 177 main.log.error( "Must define cellname" ) 178 main.cleanup() 179 main.exit() 180 else: 181 self.handle.sendline( "cell " + str( cellname ) ) 182 # Expect the cellname in the ONOSCELL variable. 183 # Note that this variable name is subject to change 184 # and that this driver will have to change accordingly 185 self.handle.expect(str(cellname)) 186 handleBefore = self.handle.before 187 handleAfter = self.handle.after 188 # Get the rest of the handle 189 self.handle.sendline("") 190 self.handle.expect("\$") 191 handleMore = self.handle.before 192 193 main.log.info( "Cell call returned: " + handleBefore + 194 handleAfter + handleMore ) 195 196 return main.TRUE 197 198 except TypeError: 199 main.log.exception( self.name + ": Object not as expected" ) 200 return None 201 except pexpect.EOF: 202 main.log.error( self.name + ": eof exception found" ) 203 main.log.error( self.name + ": " + self.handle.before ) 204 main.cleanup() 205 main.exit() 206 except Exception: 207 main.log.exception( self.name + ": Uncaught exception!" ) 208 main.cleanup() 209 main.exit()
210
211 - def startOnosCli( self, ONOSIp, karafTimeout="", 212 commandlineTimeout=10, onosStartTimeout=60 ):
213 """ 214 karafTimeout is an optional argument. karafTimeout value passed 215 by user would be used to set the current karaf shell idle timeout. 216 Note that when ever this property is modified the shell will exit and 217 the subsequent login would reflect new idle timeout. 218 Below is an example to start a session with 60 seconds idle timeout 219 ( input value is in milliseconds ): 220 221 tValue = "60000" 222 main.ONOScli1.startOnosCli( ONOSIp, karafTimeout=tValue ) 223 224 Note: karafTimeout is left as str so that this could be read 225 and passed to startOnosCli from PARAMS file as str. 226 """ 227 try: 228 self.handle.sendline( "" ) 229 x = self.handle.expect( [ 230 "\$", "onos>" ], commandlineTimeout) 231 232 if x == 1: 233 main.log.info( "ONOS cli is already running" ) 234 return main.TRUE 235 236 # Wait for onos start ( -w ) and enter onos cli 237 self.handle.sendline( "onos -w " + str( ONOSIp ) ) 238 i = self.handle.expect( [ 239 "onos>", 240 pexpect.TIMEOUT ], onosStartTimeout ) 241 242 if i == 0: 243 main.log.info( str( ONOSIp ) + " CLI Started successfully" ) 244 if karafTimeout: 245 self.handle.sendline( 246 "config:property-set -p org.apache.karaf.shell\ 247 sshIdleTimeout " + 248 karafTimeout ) 249 self.handle.expect( "\$" ) 250 self.handle.sendline( "onos -w " + str( ONOSIp ) ) 251 self.handle.expect( "onos>" ) 252 return main.TRUE 253 else: 254 # If failed, send ctrl+c to process and try again 255 main.log.info( "Starting CLI failed. Retrying..." ) 256 self.handle.send( "\x03" ) 257 self.handle.sendline( "onos -w " + str( ONOSIp ) ) 258 i = self.handle.expect( [ "onos>", pexpect.TIMEOUT ], 259 timeout=30 ) 260 if i == 0: 261 main.log.info( str( ONOSIp ) + " CLI Started " + 262 "successfully after retry attempt" ) 263 if karafTimeout: 264 self.handle.sendline( 265 "config:property-set -p org.apache.karaf.shell\ 266 sshIdleTimeout " + 267 karafTimeout ) 268 self.handle.expect( "\$" ) 269 self.handle.sendline( "onos -w " + str( ONOSIp ) ) 270 self.handle.expect( "onos>" ) 271 return main.TRUE 272 else: 273 main.log.error( "Connection to CLI " + 274 str( ONOSIp ) + " timeout" ) 275 return main.FALSE 276 277 except TypeError: 278 main.log.exception( self.name + ": Object not as expected" ) 279 return None 280 except pexpect.EOF: 281 main.log.error( self.name + ": EOF exception found" ) 282 main.log.error( self.name + ": " + self.handle.before ) 283 main.cleanup() 284 main.exit() 285 except Exception: 286 main.log.exception( self.name + ": Uncaught exception!" ) 287 main.cleanup() 288 main.exit()
289
290 - def log( self, cmdStr, level="" ):
291 """ 292 log the commands in the onos CLI. 293 returns main.TRUE on success 294 returns main.FALSE if Error occurred 295 Available level: DEBUG, TRACE, INFO, WARN, ERROR 296 Level defaults to INFO 297 """ 298 try: 299 lvlStr = "" 300 if level: 301 lvlStr = "--level=" + level 302 303 self.handle.sendline( "" ) 304 i = self.handle.expect( [ "onos>","\$", pexpect.TIMEOUT ] ) 305 if i == 1: 306 main.log.error( self.name + ": onos cli session closed." ) 307 main.cleanup() 308 main.exit() 309 if i == 2: 310 self.handle.sendline( "" ) 311 self.handle.expect( "onos>" ) 312 self.handle.sendline( "log:log " + lvlStr + " " + cmdStr ) 313 self.handle.expect( "log:log" ) 314 self.handle.expect( "onos>" ) 315 316 response = self.handle.before 317 if re.search( "Error", response ): 318 return main.FALSE 319 return main.TRUE 320 except pexpect.TIMEOUT: 321 main.log.exception( self.name + ": TIMEOUT exception found" ) 322 main.cleanup() 323 main.exit() 324 except pexpect.EOF: 325 main.log.error( self.name + ": EOF exception found" ) 326 main.log.error( self.name + ": " + self.handle.before ) 327 main.cleanup() 328 main.exit() 329 except Exception: 330 main.log.exception( self.name + ": Uncaught exception!" ) 331 main.cleanup() 332 main.exit()
333
334 - def sendline( self, cmdStr, debug=False ):
335 """ 336 Send a completely user specified string to 337 the onos> prompt. Use this function if you have 338 a very specific command to send. 339 340 Warning: There are no sanity checking to commands 341 sent using this method. 342 """ 343 try: 344 logStr = "\"Sending CLI command: '" + cmdStr + "'\"" 345 self.log( logStr ) 346 self.handle.sendline( cmdStr ) 347 i = self.handle.expect( ["onos>", "\$", pexpect.TIMEOUT] ) 348 response = self.handle.before 349 if i == 2: 350 self.handle.sendline() 351 self.handle.expect( ["\$", pexpect.TIMEOUT] ) 352 response += self.handle.before 353 print response 354 try: 355 print self.handle.after 356 except TypeError: 357 pass 358 # TODO: do something with i 359 main.log.info( "Command '" + str( cmdStr ) + "' sent to " 360 + self.name + "." ) 361 if debug: 362 main.log.debug( self.name + ": Raw output" ) 363 main.log.debug( self.name + ": " + repr( response ) ) 364 365 # Remove ANSI color control strings from output 366 ansiEscape = re.compile( r'\x1b[^m]*m' ) 367 response = ansiEscape.sub( '', response ) 368 if debug: 369 main.log.debug( self.name + ": ansiEscape output" ) 370 main.log.debug( self.name + ": " + repr( response ) ) 371 372 # Remove extra return chars that get added 373 response = re.sub( r"\s\r", "", response ) 374 if debug: 375 main.log.debug( self.name + ": Removed extra returns " + 376 "from output" ) 377 main.log.debug( self.name + ": " + repr( response ) ) 378 379 # Strip excess whitespace 380 response = response.strip() 381 if debug: 382 main.log.debug( self.name + ": parsed and stripped output" ) 383 main.log.debug( self.name + ": " + repr( response ) ) 384 385 # parse for just the output, remove the cmd from response 386 output = response.split( cmdStr.strip(), 1 ) 387 if debug: 388 main.log.debug( self.name + ": split output" ) 389 for r in output: 390 main.log.debug( self.name + ": " + repr( r ) ) 391 return output[1].strip() 392 except IndexError: 393 main.log.exception( self.name + ": Object not as expected" ) 394 return None 395 except TypeError: 396 main.log.exception( self.name + ": Object not as expected" ) 397 return None 398 except pexpect.EOF: 399 main.log.error( self.name + ": EOF exception found" ) 400 main.log.error( self.name + ": " + self.handle.before ) 401 main.cleanup() 402 main.exit() 403 except Exception: 404 main.log.exception( self.name + ": Uncaught exception!" ) 405 main.cleanup() 406 main.exit()
407 408 # IMPORTANT NOTE: 409 # For all cli commands, naming convention should match 410 # the cli command changing 'a:b' with 'aB'. 411 # Ex ) onos:topology > onosTopology 412 # onos:links > onosLinks 413 # feature:list > featureList 414
415 - def addNode( self, nodeId, ONOSIp, tcpPort="" ):
416 """ 417 Adds a new cluster node by ID and address information. 418 Required: 419 * nodeId 420 * ONOSIp 421 Optional: 422 * tcpPort 423 """ 424 try: 425 cmdStr = "add-node " + str( nodeId ) + " " +\ 426 str( ONOSIp ) + " " + str( tcpPort ) 427 handle = self.sendline( cmdStr ) 428 if re.search( "Error", handle ): 429 main.log.error( "Error in adding node" ) 430 main.log.error( handle ) 431 return main.FALSE 432 else: 433 main.log.info( "Node " + str( ONOSIp ) + " added" ) 434 return main.TRUE 435 except TypeError: 436 main.log.exception( self.name + ": Object not as expected" ) 437 return None 438 except pexpect.EOF: 439 main.log.error( self.name + ": EOF exception found" ) 440 main.log.error( self.name + ": " + self.handle.before ) 441 main.cleanup() 442 main.exit() 443 except Exception: 444 main.log.exception( self.name + ": Uncaught exception!" ) 445 main.cleanup() 446 main.exit()
447
448 - def removeNode( self, nodeId ):
449 """ 450 Removes a cluster by ID 451 Issues command: 'remove-node [<node-id>]' 452 Required: 453 * nodeId 454 """ 455 try: 456 457 cmdStr = "remove-node " + str( nodeId ) 458 handle = self.sendline( cmdStr ) 459 if re.search( "Error", handle ): 460 main.log.error( "Error in removing node" ) 461 main.log.error( handle ) 462 return main.FALSE 463 else: 464 return main.TRUE 465 except TypeError: 466 main.log.exception( self.name + ": Object not as expected" ) 467 return None 468 except pexpect.EOF: 469 main.log.error( self.name + ": EOF exception found" ) 470 main.log.error( self.name + ": " + self.handle.before ) 471 main.cleanup() 472 main.exit() 473 except Exception: 474 main.log.exception( self.name + ": Uncaught exception!" ) 475 main.cleanup() 476 main.exit()
477
478 - def nodes( self, jsonFormat=True):
479 """ 480 List the nodes currently visible 481 Issues command: 'nodes' 482 Optional argument: 483 * jsonFormat - boolean indicating if you want output in json 484 """ 485 try: 486 cmdStr = "nodes" 487 if jsonFormat: 488 cmdStr += " -j" 489 output = self.sendline( cmdStr ) 490 return output 491 except TypeError: 492 main.log.exception( self.name + ": Object not as expected" ) 493 return None 494 except pexpect.EOF: 495 main.log.error( self.name + ": EOF exception found" ) 496 main.log.error( self.name + ": " + self.handle.before ) 497 main.cleanup() 498 main.exit() 499 except Exception: 500 main.log.exception( self.name + ": Uncaught exception!" ) 501 main.cleanup() 502 main.exit()
503
504 - def topology( self ):
505 """ 506 Definition: 507 Returns the output of topology command. 508 Return: 509 topology = current ONOS topology 510 """ 511 try: 512 cmdStr = "topology -j" 513 handle = self.sendline( cmdStr ) 514 main.log.info( cmdStr + " returned: " + str( handle ) ) 515 return handle 516 except TypeError: 517 main.log.exception( self.name + ": Object not as expected" ) 518 return None 519 except pexpect.EOF: 520 main.log.error( self.name + ": EOF exception found" ) 521 main.log.error( self.name + ": " + self.handle.before ) 522 main.cleanup() 523 main.exit() 524 except Exception: 525 main.log.exception( self.name + ": Uncaught exception!" ) 526 main.cleanup() 527 main.exit()
528
529 - def featureInstall( self, featureStr ):
530 """ 531 Installs a specified feature by issuing command: 532 'feature:install <feature_str>' 533 NOTE: This is now deprecated, you should use the activateApp method 534 instead 535 """ 536 try: 537 cmdStr = "feature:install " + str( featureStr ) 538 handle = self.sendline( cmdStr ) 539 if re.search( "Error", handle ): 540 main.log.error( "Error in installing feature" ) 541 main.log.error( handle ) 542 return main.FALSE 543 else: 544 return main.TRUE 545 except TypeError: 546 main.log.exception( self.name + ": Object not as expected" ) 547 return None 548 except pexpect.EOF: 549 main.log.error( self.name + ": EOF exception found" ) 550 main.log.error( self.name + ": " + self.handle.before ) 551 main.log.report( "Failed to install feature" ) 552 main.log.report( "Exiting test" ) 553 main.cleanup() 554 main.exit() 555 except Exception: 556 main.log.exception( self.name + ": Uncaught exception!" ) 557 main.log.report( "Failed to install feature" ) 558 main.log.report( "Exiting test" ) 559 main.cleanup() 560 main.exit()
561
562 - def featureUninstall( self, featureStr ):
563 """ 564 Uninstalls a specified feature by issuing command: 565 'feature:uninstall <feature_str>' 566 NOTE: This is now deprecated, you should use the deactivateApp method 567 instead 568 """ 569 try: 570 cmdStr = 'feature:list -i | grep "' + featureStr + '"' 571 handle = self.sendline( cmdStr ) 572 if handle != '': 573 cmdStr = "feature:uninstall " + str( featureStr ) 574 output = self.sendline( cmdStr ) 575 # TODO: Check for possible error responses from karaf 576 else: 577 main.log.info( "Feature needs to be installed before " + 578 "uninstalling it" ) 579 return main.TRUE 580 if re.search( "Error", output ): 581 main.log.error( "Error in uninstalling feature" ) 582 main.log.error( output ) 583 return main.FALSE 584 else: 585 return main.TRUE 586 except TypeError: 587 main.log.exception( self.name + ": Object not as expected" ) 588 return None 589 except pexpect.EOF: 590 main.log.error( self.name + ": EOF exception found" ) 591 main.log.error( self.name + ": " + self.handle.before ) 592 main.cleanup() 593 main.exit() 594 except Exception: 595 main.log.exception( self.name + ": Uncaught exception!" ) 596 main.cleanup() 597 main.exit()
598
599 - def deviceRemove( self, deviceId ):
600 """ 601 Removes particular device from storage 602 603 TODO: refactor this function 604 """ 605 try: 606 cmdStr = "device-remove " + str( deviceId ) 607 handle = self.sendline( cmdStr ) 608 if re.search( "Error", handle ): 609 main.log.error( "Error in removing device" ) 610 main.log.error( handle ) 611 return main.FALSE 612 else: 613 return main.TRUE 614 except TypeError: 615 main.log.exception( self.name + ": Object not as expected" ) 616 return None 617 except pexpect.EOF: 618 main.log.error( self.name + ": EOF exception found" ) 619 main.log.error( self.name + ": " + self.handle.before ) 620 main.cleanup() 621 main.exit() 622 except Exception: 623 main.log.exception( self.name + ": Uncaught exception!" ) 624 main.cleanup() 625 main.exit()
626
627 - def devices( self, jsonFormat=True ):
628 """ 629 Lists all infrastructure devices or switches 630 Optional argument: 631 * jsonFormat - boolean indicating if you want output in json 632 """ 633 try: 634 cmdStr = "devices" 635 if jsonFormat: 636 cmdStr += " -j" 637 handle = self.sendline( cmdStr ) 638 return handle 639 except TypeError: 640 main.log.exception( self.name + ": Object not as expected" ) 641 return None 642 except pexpect.EOF: 643 main.log.error( self.name + ": EOF exception found" ) 644 main.log.error( self.name + ": " + self.handle.before ) 645 main.cleanup() 646 main.exit() 647 except Exception: 648 main.log.exception( self.name + ": Uncaught exception!" ) 649 main.cleanup() 650 main.exit()
651
652 - def balanceMasters( self ):
653 """ 654 This balances the devices across all controllers 655 by issuing command: 'onos> onos:balance-masters' 656 If required this could be extended to return devices balanced output. 657 """ 658 try: 659 cmdStr = "onos:balance-masters" 660 handle = self.sendline( cmdStr ) 661 if re.search( "Error", handle ): 662 main.log.error( "Error in balancing masters" ) 663 main.log.error( handle ) 664 return main.FALSE 665 else: 666 return main.TRUE 667 except TypeError: 668 main.log.exception( self.name + ": Object not as expected" ) 669 return None 670 except pexpect.EOF: 671 main.log.error( self.name + ": EOF exception found" ) 672 main.log.error( self.name + ": " + self.handle.before ) 673 main.cleanup() 674 main.exit() 675 except Exception: 676 main.log.exception( self.name + ": Uncaught exception!" ) 677 main.cleanup() 678 main.exit()
679
680 - def checkMasters( self,jsonFormat=True ):
681 """ 682 Returns the output of the masters command. 683 Optional argument: 684 * jsonFormat - boolean indicating if you want output in json 685 """ 686 try: 687 cmdStr = "onos:masters" 688 if jsonFormat: 689 cmdStr += " -j" 690 output = self.sendline( cmdStr ) 691 return output 692 except TypeError: 693 main.log.exception( self.name + ": Object not as expected" ) 694 return None 695 except pexpect.EOF: 696 main.log.error( self.name + ": EOF exception found" ) 697 main.log.error( self.name + ": " + self.handle.before ) 698 main.cleanup() 699 main.exit() 700 except Exception: 701 main.log.exception( self.name + ": Uncaught exception!" ) 702 main.cleanup() 703 main.exit()
704
705 - def checkBalanceMasters( self,jsonFormat=True ):
706 """ 707 Uses the master command to check that the devices' leadership 708 is evenly divided 709 710 Dependencies: checkMasters() and summary() 711 712 Returns main.True if the devices are balanced 713 Returns main.False if the devices are unbalanced 714 Exits on Exception 715 Returns None on TypeError 716 """ 717 try: 718 totalDevices = json.loads( self.summary() )[ "devices" ] 719 totalOwnedDevices = 0 720 masters = json.loads( self.checkMasters() ) 721 first = masters[ 0 ][ "size" ] 722 for master in masters: 723 totalOwnedDevices += master[ "size" ] 724 if master[ "size" ] > first + 1 or master[ "size" ] < first - 1: 725 main.log.error( "Mastership not balanced" ) 726 main.log.info( "\n" + self.checkMasters( False ) ) 727 return main.FALSE 728 main.log.info( "Mastership balanced between " \ 729 + str( len(masters) ) + " masters" ) 730 return main.TRUE 731 except TypeError: 732 main.log.exception( self.name + ": Object not as expected" ) 733 return None 734 except pexpect.EOF: 735 main.log.error( self.name + ": EOF exception found" ) 736 main.log.error( self.name + ": " + self.handle.before ) 737 main.cleanup() 738 main.exit() 739 except Exception: 740 main.log.exception( self.name + ": Uncaught exception!" ) 741 main.cleanup() 742 main.exit()
743 768
769 - def ports( self, jsonFormat=True ):
770 """ 771 Lists all ports 772 Optional argument: 773 * jsonFormat - boolean indicating if you want output in json 774 """ 775 try: 776 cmdStr = "ports" 777 if jsonFormat: 778 cmdStr += " -j" 779 handle = self.sendline( cmdStr ) 780 return handle 781 except TypeError: 782 main.log.exception( self.name + ": Object not as expected" ) 783 return None 784 except pexpect.EOF: 785 main.log.error( self.name + ": EOF exception found" ) 786 main.log.error( self.name + ": " + self.handle.before ) 787 main.cleanup() 788 main.exit() 789 except Exception: 790 main.log.exception( self.name + ": Uncaught exception!" ) 791 main.cleanup() 792 main.exit()
793
794 - def roles( self, jsonFormat=True ):
795 """ 796 Lists all devices and the controllers with roles assigned to them 797 Optional argument: 798 * jsonFormat - boolean indicating if you want output in json 799 """ 800 try: 801 cmdStr = "roles" 802 if jsonFormat: 803 cmdStr += " -j" 804 handle = self.sendline( cmdStr ) 805 return handle 806 except TypeError: 807 main.log.exception( self.name + ": Object not as expected" ) 808 return None 809 except pexpect.EOF: 810 main.log.error( self.name + ": EOF exception found" ) 811 main.log.error( self.name + ": " + self.handle.before ) 812 main.cleanup() 813 main.exit() 814 except Exception: 815 main.log.exception( self.name + ": Uncaught exception!" ) 816 main.cleanup() 817 main.exit()
818
819 - def getRole( self, deviceId ):
820 """ 821 Given the a string containing the json representation of the "roles" 822 cli command and a partial or whole device id, returns a json object 823 containing the roles output for the first device whose id contains 824 "device_id" 825 826 Returns: 827 A dict of the role assignments for the given device or 828 None if no match 829 """ 830 try: 831 if deviceId is None: 832 return None 833 else: 834 rawRoles = self.roles() 835 rolesJson = json.loads( rawRoles ) 836 # search json for the device with id then return the device 837 for device in rolesJson: 838 # print device 839 if str( deviceId ) in device[ 'id' ]: 840 return device 841 return None 842 except TypeError: 843 main.log.exception( self.name + ": Object not as expected" ) 844 return None 845 except pexpect.EOF: 846 main.log.error( self.name + ": EOF exception found" ) 847 main.log.error( self.name + ": " + self.handle.before ) 848 main.cleanup() 849 main.exit() 850 except Exception: 851 main.log.exception( self.name + ": Uncaught exception!" ) 852 main.cleanup() 853 main.exit()
854
855 - def rolesNotNull( self ):
856 """ 857 Iterates through each device and checks if there is a master assigned 858 Returns: main.TRUE if each device has a master 859 main.FALSE any device has no master 860 """ 861 try: 862 rawRoles = self.roles() 863 rolesJson = json.loads( rawRoles ) 864 # search json for the device with id then return the device 865 for device in rolesJson: 866 # print device 867 if device[ 'master' ] == "none": 868 main.log.warn( "Device has no master: " + str( device ) ) 869 return main.FALSE 870 return main.TRUE 871 872 except TypeError: 873 main.log.exception( self.name + ": Object not as expected" ) 874 return None 875 except pexpect.EOF: 876 main.log.error( self.name + ": EOF exception found" ) 877 main.log.error( self.name + ": " + self.handle.before ) 878 main.cleanup() 879 main.exit() 880 except Exception: 881 main.log.exception( self.name + ": Uncaught exception!" ) 882 main.cleanup() 883 main.exit()
884
885 - def paths( self, srcId, dstId ):
886 """ 887 Returns string of paths, and the cost. 888 Issues command: onos:paths <src> <dst> 889 """ 890 try: 891 cmdStr = "onos:paths " + str( srcId ) + " " + str( dstId ) 892 handle = self.sendline( cmdStr ) 893 if re.search( "Error", handle ): 894 main.log.error( "Error in getting paths" ) 895 return ( handle, "Error" ) 896 else: 897 path = handle.split( ";" )[ 0 ] 898 cost = handle.split( ";" )[ 1 ] 899 return ( path, cost ) 900 except TypeError: 901 main.log.exception( self.name + ": Object not as expected" ) 902 return ( handle, "Error" ) 903 except pexpect.EOF: 904 main.log.error( self.name + ": EOF exception found" ) 905 main.log.error( self.name + ": " + self.handle.before ) 906 main.cleanup() 907 main.exit() 908 except Exception: 909 main.log.exception( self.name + ": Uncaught exception!" ) 910 main.cleanup() 911 main.exit()
912
913 - def hosts( self, jsonFormat=True ):
914 """ 915 Lists all discovered hosts 916 Optional argument: 917 * jsonFormat - boolean indicating if you want output in json 918 """ 919 try: 920 cmdStr = "hosts" 921 if jsonFormat: 922 cmdStr += " -j" 923 handle = self.sendline( cmdStr ) 924 return handle 925 except TypeError: 926 main.log.exception( self.name + ": Object not as expected" ) 927 return None 928 except pexpect.EOF: 929 main.log.error( self.name + ": EOF exception found" ) 930 main.log.error( self.name + ": " + self.handle.before ) 931 main.cleanup() 932 main.exit() 933 except Exception: 934 main.log.exception( self.name + ": Uncaught exception!" ) 935 main.cleanup() 936 main.exit()
937
938 - def getHost( self, mac ):
939 """ 940 Return the first host from the hosts api whose 'id' contains 'mac' 941 942 Note: mac must be a colon separated mac address, but could be a 943 partial mac address 944 945 Return None if there is no match 946 """ 947 try: 948 if mac is None: 949 return None 950 else: 951 mac = mac 952 rawHosts = self.hosts() 953 hostsJson = json.loads( rawHosts ) 954 # search json for the host with mac then return the device 955 for host in hostsJson: 956 # print "%s in %s?" % ( mac, host[ 'id' ] ) 957 if not host: 958 pass 959 elif mac in host[ 'id' ]: 960 return host 961 return None 962 except TypeError: 963 main.log.exception( self.name + ": Object not as expected" ) 964 return None 965 except pexpect.EOF: 966 main.log.error( self.name + ": EOF exception found" ) 967 main.log.error( self.name + ": " + self.handle.before ) 968 main.cleanup() 969 main.exit() 970 except Exception: 971 main.log.exception( self.name + ": Uncaught exception!" ) 972 main.cleanup() 973 main.exit()
974
975 - def getHostsId( self, hostList ):
976 """ 977 Obtain list of hosts 978 Issues command: 'onos> hosts' 979 980 Required: 981 * hostList: List of hosts obtained by Mininet 982 IMPORTANT: 983 This function assumes that you started your 984 topology with the option '--mac'. 985 Furthermore, it assumes that value of VLAN is '-1' 986 Description: 987 Converts mininet hosts ( h1, h2, h3... ) into 988 ONOS format ( 00:00:00:00:00:01/-1 , ... ) 989 """ 990 try: 991 onosHostList = [] 992 993 for host in hostList: 994 host = host.replace( "h", "" ) 995 hostHex = hex( int( host ) ).zfill( 12 ) 996 hostHex = str( hostHex ).replace( 'x', '0' ) 997 i = iter( str( hostHex ) ) 998 hostHex = ":".join( a + b for a, b in zip( i, i ) ) 999 hostHex = hostHex + "/-1" 1000 onosHostList.append( hostHex ) 1001 1002 return onosHostList 1003 1004 except TypeError: 1005 main.log.exception( self.name + ": Object not as expected" ) 1006 return None 1007 except pexpect.EOF: 1008 main.log.error( self.name + ": EOF exception found" ) 1009 main.log.error( self.name + ": " + self.handle.before ) 1010 main.cleanup() 1011 main.exit() 1012 except Exception: 1013 main.log.exception( self.name + ": Uncaught exception!" ) 1014 main.cleanup() 1015 main.exit()
1016
1017 - def addHostIntent( self, hostIdOne, hostIdTwo ):
1018 """ 1019 Required: 1020 * hostIdOne: ONOS host id for host1 1021 * hostIdTwo: ONOS host id for host2 1022 Description: 1023 Adds a host-to-host intent ( bidirectional ) by 1024 specifying the two hosts. 1025 Returns: 1026 A string of the intent id or None on Error 1027 """ 1028 try: 1029 cmdStr = "add-host-intent " + str( hostIdOne ) +\ 1030 " " + str( hostIdTwo ) 1031 handle = self.sendline( cmdStr ) 1032 if re.search( "Error", handle ): 1033 main.log.error( "Error in adding Host intent" ) 1034 main.log.debug( "Response from ONOS was: " + repr( handle ) ) 1035 return None 1036 else: 1037 main.log.info( "Host intent installed between " + 1038 str( hostIdOne ) + " and " + str( hostIdTwo ) ) 1039 match = re.search('id=0x([\da-f]+),', handle) 1040 if match: 1041 return match.group()[3:-1] 1042 else: 1043 main.log.error( "Error, intent ID not found" ) 1044 main.log.debug( "Response from ONOS was: " + 1045 repr( handle ) ) 1046 return None 1047 except TypeError: 1048 main.log.exception( self.name + ": Object not as expected" ) 1049 return None 1050 except pexpect.EOF: 1051 main.log.error( self.name + ": EOF exception found" ) 1052 main.log.error( self.name + ": " + self.handle.before ) 1053 main.cleanup() 1054 main.exit() 1055 except Exception: 1056 main.log.exception( self.name + ": Uncaught exception!" ) 1057 main.cleanup() 1058 main.exit()
1059
1060 - def addOpticalIntent( self, ingressDevice, egressDevice ):
1061 """ 1062 Required: 1063 * ingressDevice: device id of ingress device 1064 * egressDevice: device id of egress device 1065 Optional: 1066 TODO: Still needs to be implemented via dev side 1067 Description: 1068 Adds an optical intent by specifying an ingress and egress device 1069 Returns: 1070 A string of the intent id or None on error 1071 """ 1072 try: 1073 cmdStr = "add-optical-intent " + str( ingressDevice ) +\ 1074 " " + str( egressDevice ) 1075 handle = self.sendline( cmdStr ) 1076 # If error, return error message 1077 if re.search( "Error", handle ): 1078 main.log.error( "Error in adding Optical intent" ) 1079 return None 1080 else: 1081 main.log.info( "Optical intent installed between " + 1082 str( ingressDevice ) + " and " + 1083 str( egressDevice ) ) 1084 match = re.search('id=0x([\da-f]+),', handle) 1085 if match: 1086 return match.group()[3:-1] 1087 else: 1088 main.log.error( "Error, intent ID not found" ) 1089 return None 1090 except TypeError: 1091 main.log.exception( self.name + ": Object not as expected" ) 1092 return None 1093 except pexpect.EOF: 1094 main.log.error( self.name + ": EOF exception found" ) 1095 main.log.error( self.name + ": " + self.handle.before ) 1096 main.cleanup() 1097 main.exit() 1098 except Exception: 1099 main.log.exception( self.name + ": Uncaught exception!" ) 1100 main.cleanup() 1101 main.exit()
1102
1103 - def addPointIntent( 1104 self, 1105 ingressDevice, 1106 egressDevice, 1107 portIngress="", 1108 portEgress="", 1109 ethType="", 1110 ethSrc="", 1111 ethDst="", 1112 bandwidth="", 1113 lambdaAlloc=False, 1114 ipProto="", 1115 ipSrc="", 1116 ipDst="", 1117 tcpSrc="", 1118 tcpDst="" ):
1119 """ 1120 Required: 1121 * ingressDevice: device id of ingress device 1122 * egressDevice: device id of egress device 1123 Optional: 1124 * ethType: specify ethType 1125 * ethSrc: specify ethSrc ( i.e. src mac addr ) 1126 * ethDst: specify ethDst ( i.e. dst mac addr ) 1127 * bandwidth: specify bandwidth capacity of link 1128 * lambdaAlloc: if True, intent will allocate lambda 1129 for the specified intent 1130 * ipProto: specify ip protocol 1131 * ipSrc: specify ip source address 1132 * ipDst: specify ip destination address 1133 * tcpSrc: specify tcp source port 1134 * tcpDst: specify tcp destination port 1135 Description: 1136 Adds a point-to-point intent ( uni-directional ) by 1137 specifying device id's and optional fields 1138 Returns: 1139 A string of the intent id or None on error 1140 1141 NOTE: This function may change depending on the 1142 options developers provide for point-to-point 1143 intent via cli 1144 """ 1145 try: 1146 # If there are no optional arguments 1147 if not ethType and not ethSrc and not ethDst\ 1148 and not bandwidth and not lambdaAlloc \ 1149 and not ipProto and not ipSrc and not ipDst \ 1150 and not tcpSrc and not tcpDst: 1151 cmd = "add-point-intent" 1152 1153 else: 1154 cmd = "add-point-intent" 1155 1156 if ethType: 1157 cmd += " --ethType " + str( ethType ) 1158 if ethSrc: 1159 cmd += " --ethSrc " + str( ethSrc ) 1160 if ethDst: 1161 cmd += " --ethDst " + str( ethDst ) 1162 if bandwidth: 1163 cmd += " --bandwidth " + str( bandwidth ) 1164 if lambdaAlloc: 1165 cmd += " --lambda " 1166 if ipProto: 1167 cmd += " --ipProto " + str( ipProto ) 1168 if ipSrc: 1169 cmd += " --ipSrc " + str( ipSrc ) 1170 if ipDst: 1171 cmd += " --ipDst " + str( ipDst ) 1172 if tcpSrc: 1173 cmd += " --tcpSrc " + str( tcpSrc ) 1174 if tcpDst: 1175 cmd += " --tcpDst " + str( tcpDst ) 1176 1177 # Check whether the user appended the port 1178 # or provided it as an input 1179 if "/" in ingressDevice: 1180 cmd += " " + str( ingressDevice ) 1181 else: 1182 if not portIngress: 1183 main.log.error( "You must specify the ingress port" ) 1184 # TODO: perhaps more meaningful return 1185 # Would it make sense to throw an exception and exit 1186 # the test? 1187 return None 1188 1189 cmd += " " + \ 1190 str( ingressDevice ) + "/" +\ 1191 str( portIngress ) + " " 1192 1193 if "/" in egressDevice: 1194 cmd += " " + str( egressDevice ) 1195 else: 1196 if not portEgress: 1197 main.log.error( "You must specify the egress port" ) 1198 return None 1199 1200 cmd += " " +\ 1201 str( egressDevice ) + "/" +\ 1202 str( portEgress ) 1203 1204 handle = self.sendline( cmd ) 1205 # If error, return error message 1206 if re.search( "Error", handle ): 1207 main.log.error( "Error in adding point-to-point intent" ) 1208 return None 1209 else: 1210 # TODO: print out all the options in this message? 1211 main.log.info( "Point-to-point intent installed between " + 1212 str( ingressDevice ) + " and " + 1213 str( egressDevice ) ) 1214 match = re.search('id=0x([\da-f]+),', handle) 1215 if match: 1216 return match.group()[3:-1] 1217 else: 1218 main.log.error( "Error, intent ID not found" ) 1219 return None 1220 except TypeError: 1221 main.log.exception( self.name + ": Object not as expected" ) 1222 return None 1223 except pexpect.EOF: 1224 main.log.error( self.name + ": EOF exception found" ) 1225 main.log.error( self.name + ": " + self.handle.before ) 1226 main.cleanup() 1227 main.exit() 1228 except Exception: 1229 main.log.exception( self.name + ": Uncaught exception!" ) 1230 main.cleanup() 1231 main.exit()
1232
1233 - def addMultipointToSinglepointIntent( 1234 self, 1235 ingressDeviceList, 1236 egressDevice, 1237 portIngressList=None, 1238 portEgress="", 1239 ethType="", 1240 ethSrc="", 1241 ethDst="", 1242 bandwidth="", 1243 lambdaAlloc=False, 1244 ipProto="", 1245 ipSrc="", 1246 ipDst="", 1247 tcpSrc="", 1248 tcpDst="", 1249 setEthSrc="", 1250 setEthDst="" ):
1251 """ 1252 Note: 1253 This function assumes the format of all ingress devices 1254 is same. That is, all ingress devices include port numbers 1255 with a "/" or all ingress devices could specify device 1256 ids and port numbers seperately. 1257 Required: 1258 * ingressDeviceList: List of device ids of ingress device 1259 ( Atleast 2 ingress devices required in the list ) 1260 * egressDevice: device id of egress device 1261 Optional: 1262 * ethType: specify ethType 1263 * ethSrc: specify ethSrc ( i.e. src mac addr ) 1264 * ethDst: specify ethDst ( i.e. dst mac addr ) 1265 * bandwidth: specify bandwidth capacity of link 1266 * lambdaAlloc: if True, intent will allocate lambda 1267 for the specified intent 1268 * ipProto: specify ip protocol 1269 * ipSrc: specify ip source address 1270 * ipDst: specify ip destination address 1271 * tcpSrc: specify tcp source port 1272 * tcpDst: specify tcp destination port 1273 * setEthSrc: action to Rewrite Source MAC Address 1274 * setEthDst: action to Rewrite Destination MAC Address 1275 Description: 1276 Adds a multipoint-to-singlepoint intent ( uni-directional ) by 1277 specifying device id's and optional fields 1278 Returns: 1279 A string of the intent id or None on error 1280 1281 NOTE: This function may change depending on the 1282 options developers provide for multipoint-to-singlepoint 1283 intent via cli 1284 """ 1285 try: 1286 # If there are no optional arguments 1287 if not ethType and not ethSrc and not ethDst\ 1288 and not bandwidth and not lambdaAlloc\ 1289 and not ipProto and not ipSrc and not ipDst\ 1290 and not tcpSrc and not tcpDst and not setEthSrc\ 1291 and not setEthDst: 1292 cmd = "add-multi-to-single-intent" 1293 1294 else: 1295 cmd = "add-multi-to-single-intent" 1296 1297 if ethType: 1298 cmd += " --ethType " + str( ethType ) 1299 if ethSrc: 1300 cmd += " --ethSrc " + str( ethSrc ) 1301 if ethDst: 1302 cmd += " --ethDst " + str( ethDst ) 1303 if bandwidth: 1304 cmd += " --bandwidth " + str( bandwidth ) 1305 if lambdaAlloc: 1306 cmd += " --lambda " 1307 if ipProto: 1308 cmd += " --ipProto " + str( ipProto ) 1309 if ipSrc: 1310 cmd += " --ipSrc " + str( ipSrc ) 1311 if ipDst: 1312 cmd += " --ipDst " + str( ipDst ) 1313 if tcpSrc: 1314 cmd += " --tcpSrc " + str( tcpSrc ) 1315 if tcpDst: 1316 cmd += " --tcpDst " + str( tcpDst ) 1317 if setEthSrc: 1318 cmd += " --setEthSrc " + str( setEthSrc ) 1319 if setEthDst: 1320 cmd += " --setEthDst " + str( setEthDst ) 1321 1322 # Check whether the user appended the port 1323 # or provided it as an input 1324 1325 if portIngressList is None: 1326 for ingressDevice in ingressDeviceList: 1327 if "/" in ingressDevice: 1328 cmd += " " + str( ingressDevice ) 1329 else: 1330 main.log.error( "You must specify " + 1331 "the ingress port" ) 1332 # TODO: perhaps more meaningful return 1333 return main.FALSE 1334 else: 1335 if len( ingressDeviceList ) == len( portIngressList ): 1336 for ingressDevice, portIngress in zip( ingressDeviceList, 1337 portIngressList ): 1338 cmd += " " + \ 1339 str( ingressDevice ) + "/" +\ 1340 str( portIngress ) + " " 1341 else: 1342 main.log.error( "Device list and port list does not " + 1343 "have the same length" ) 1344 return main.FALSE 1345 if "/" in egressDevice: 1346 cmd += " " + str( egressDevice ) 1347 else: 1348 if not portEgress: 1349 main.log.error( "You must specify " + 1350 "the egress port" ) 1351 return main.FALSE 1352 1353 cmd += " " +\ 1354 str( egressDevice ) + "/" +\ 1355 str( portEgress ) 1356 handle = self.sendline( cmd ) 1357 # If error, return error message 1358 if re.search( "Error", handle ): 1359 main.log.error( "Error in adding multipoint-to-singlepoint " + 1360 "intent" ) 1361 return None 1362 else: 1363 match = re.search('id=0x([\da-f]+),', handle) 1364 if match: 1365 return match.group()[3:-1] 1366 else: 1367 main.log.error( "Error, intent ID not found" ) 1368 return None 1369 except TypeError: 1370 main.log.exception( self.name + ": Object not as expected" ) 1371 return None 1372 except pexpect.EOF: 1373 main.log.error( self.name + ": EOF exception found" ) 1374 main.log.error( self.name + ": " + self.handle.before ) 1375 main.cleanup() 1376 main.exit() 1377 except Exception: 1378 main.log.exception( self.name + ": Uncaught exception!" ) 1379 main.cleanup() 1380 main.exit()
1381
1382 - def addSinglepointToMultipointIntent( 1383 self, 1384 ingressDevice, 1385 egressDeviceList, 1386 portIngress="", 1387 portEgressList=None, 1388 ethType="", 1389 ethSrc="", 1390 ethDst="", 1391 bandwidth="", 1392 lambdaAlloc=False, 1393 ipProto="", 1394 ipSrc="", 1395 ipDst="", 1396 tcpSrc="", 1397 tcpDst="", 1398 setEthSrc="", 1399 setEthDst="" ):
1400 """ 1401 Note: 1402 This function assumes the format of all egress devices 1403 is same. That is, all egress devices include port numbers 1404 with a "/" or all egress devices could specify device 1405 ids and port numbers seperately. 1406 Required: 1407 * EgressDeviceList: List of device ids of egress device 1408 ( Atleast 2 eress devices required in the list ) 1409 * ingressDevice: device id of ingress device 1410 Optional: 1411 * ethType: specify ethType 1412 * ethSrc: specify ethSrc ( i.e. src mac addr ) 1413 * ethDst: specify ethDst ( i.e. dst mac addr ) 1414 * bandwidth: specify bandwidth capacity of link 1415 * lambdaAlloc: if True, intent will allocate lambda 1416 for the specified intent 1417 * ipProto: specify ip protocol 1418 * ipSrc: specify ip source address 1419 * ipDst: specify ip destination address 1420 * tcpSrc: specify tcp source port 1421 * tcpDst: specify tcp destination port 1422 * setEthSrc: action to Rewrite Source MAC Address 1423 * setEthDst: action to Rewrite Destination MAC Address 1424 Description: 1425 Adds a singlepoint-to-multipoint intent ( uni-directional ) by 1426 specifying device id's and optional fields 1427 Returns: 1428 A string of the intent id or None on error 1429 1430 NOTE: This function may change depending on the 1431 options developers provide for singlepoint-to-multipoint 1432 intent via cli 1433 """ 1434 try: 1435 # If there are no optional arguments 1436 if not ethType and not ethSrc and not ethDst\ 1437 and not bandwidth and not lambdaAlloc\ 1438 and not ipProto and not ipSrc and not ipDst\ 1439 and not tcpSrc and not tcpDst and not setEthSrc\ 1440 and not setEthDst: 1441 cmd = "add-single-to-multi-intent" 1442 1443 else: 1444 cmd = "add-single-to-multi-intent" 1445 1446 if ethType: 1447 cmd += " --ethType " + str( ethType ) 1448 if ethSrc: 1449 cmd += " --ethSrc " + str( ethSrc ) 1450 if ethDst: 1451 cmd += " --ethDst " + str( ethDst ) 1452 if bandwidth: 1453 cmd += " --bandwidth " + str( bandwidth ) 1454 if lambdaAlloc: 1455 cmd += " --lambda " 1456 if ipProto: 1457 cmd += " --ipProto " + str( ipProto ) 1458 if ipSrc: 1459 cmd += " --ipSrc " + str( ipSrc ) 1460 if ipDst: 1461 cmd += " --ipDst " + str( ipDst ) 1462 if tcpSrc: 1463 cmd += " --tcpSrc " + str( tcpSrc ) 1464 if tcpDst: 1465 cmd += " --tcpDst " + str( tcpDst ) 1466 if setEthSrc: 1467 cmd += " --setEthSrc " + str( setEthSrc ) 1468 if setEthDst: 1469 cmd += " --setEthDst " + str( setEthDst ) 1470 1471 # Check whether the user appended the port 1472 # or provided it as an input 1473 1474 if "/" in ingressDevice: 1475 cmd += " " + str( ingressDevice ) 1476 else: 1477 if not portIngress: 1478 main.log.error( "You must specify " + 1479 "the Ingress port" ) 1480 return main.FALSE 1481 1482 cmd += " " +\ 1483 str( ingressDevice ) + "/" +\ 1484 str( portIngress ) 1485 1486 if portEgressList is None: 1487 for egressDevice in egressDeviceList: 1488 if "/" in egressDevice: 1489 cmd += " " + str( egressDevice ) 1490 else: 1491 main.log.error( "You must specify " + 1492 "the egress port" ) 1493 # TODO: perhaps more meaningful return 1494 return main.FALSE 1495 else: 1496 if len( egressDeviceList ) == len( portEgressList ): 1497 for egressDevice, portEgress in zip( egressDeviceList, 1498 portEgressList ): 1499 cmd += " " + \ 1500 str( egressDevice ) + "/" +\ 1501 str( portEgress ) 1502 else: 1503 main.log.error( "Device list and port list does not " + 1504 "have the same length" ) 1505 return main.FALSE 1506 handle = self.sendline( cmd ) 1507 # If error, return error message 1508 if re.search( "Error", handle ): 1509 main.log.error( "Error in adding singlepoint-to-multipoint " + 1510 "intent" ) 1511 return None 1512 else: 1513 match = re.search('id=0x([\da-f]+),', handle) 1514 if match: 1515 return match.group()[3:-1] 1516 else: 1517 main.log.error( "Error, intent ID not found" ) 1518 return None 1519 except TypeError: 1520 main.log.exception( self.name + ": Object not as expected" ) 1521 return None 1522 except pexpect.EOF: 1523 main.log.error( self.name + ": EOF exception found" ) 1524 main.log.error( self.name + ": " + self.handle.before ) 1525 main.cleanup() 1526 main.exit() 1527 except Exception: 1528 main.log.exception( self.name + ": Uncaught exception!" ) 1529 main.cleanup() 1530 main.exit()
1531
1532 - def addMplsIntent( 1533 self, 1534 ingressDevice, 1535 egressDevice, 1536 ingressPort="", 1537 egressPort="", 1538 ethType="", 1539 ethSrc="", 1540 ethDst="", 1541 bandwidth="", 1542 lambdaAlloc=False, 1543 ipProto="", 1544 ipSrc="", 1545 ipDst="", 1546 tcpSrc="", 1547 tcpDst="", 1548 ingressLabel="", 1549 egressLabel="", 1550 priority=""):
1551 """ 1552 Required: 1553 * ingressDevice: device id of ingress device 1554 * egressDevice: device id of egress device 1555 Optional: 1556 * ethType: specify ethType 1557 * ethSrc: specify ethSrc ( i.e. src mac addr ) 1558 * ethDst: specify ethDst ( i.e. dst mac addr ) 1559 * bandwidth: specify bandwidth capacity of link 1560 * lambdaAlloc: if True, intent will allocate lambda 1561 for the specified intent 1562 * ipProto: specify ip protocol 1563 * ipSrc: specify ip source address 1564 * ipDst: specify ip destination address 1565 * tcpSrc: specify tcp source port 1566 * tcpDst: specify tcp destination port 1567 * ingressLabel: Ingress MPLS label 1568 * egressLabel: Egress MPLS label 1569 Description: 1570 Adds MPLS intent by 1571 specifying device id's and optional fields 1572 Returns: 1573 A string of the intent id or None on error 1574 1575 NOTE: This function may change depending on the 1576 options developers provide for MPLS 1577 intent via cli 1578 """ 1579 try: 1580 # If there are no optional arguments 1581 if not ethType and not ethSrc and not ethDst\ 1582 and not bandwidth and not lambdaAlloc \ 1583 and not ipProto and not ipSrc and not ipDst \ 1584 and not tcpSrc and not tcpDst and not ingressLabel \ 1585 and not egressLabel: 1586 cmd = "add-mpls-intent" 1587 1588 else: 1589 cmd = "add-mpls-intent" 1590 1591 if ethType: 1592 cmd += " --ethType " + str( ethType ) 1593 if ethSrc: 1594 cmd += " --ethSrc " + str( ethSrc ) 1595 if ethDst: 1596 cmd += " --ethDst " + str( ethDst ) 1597 if bandwidth: 1598 cmd += " --bandwidth " + str( bandwidth ) 1599 if lambdaAlloc: 1600 cmd += " --lambda " 1601 if ipProto: 1602 cmd += " --ipProto " + str( ipProto ) 1603 if ipSrc: 1604 cmd += " --ipSrc " + str( ipSrc ) 1605 if ipDst: 1606 cmd += " --ipDst " + str( ipDst ) 1607 if tcpSrc: 1608 cmd += " --tcpSrc " + str( tcpSrc ) 1609 if tcpDst: 1610 cmd += " --tcpDst " + str( tcpDst ) 1611 if ingressLabel: 1612 cmd += " --ingressLabel " + str( ingressLabel ) 1613 if egressLabel: 1614 cmd += " --egressLabel " + str( egressLabel ) 1615 if priority: 1616 cmd += " --priority " + str( priority ) 1617 1618 # Check whether the user appended the port 1619 # or provided it as an input 1620 if "/" in ingressDevice: 1621 cmd += " " + str( ingressDevice ) 1622 else: 1623 if not ingressPort: 1624 main.log.error( "You must specify the ingress port" ) 1625 return None 1626 1627 cmd += " " + \ 1628 str( ingressDevice ) + "/" +\ 1629 str( ingressPort ) + " " 1630 1631 if "/" in egressDevice: 1632 cmd += " " + str( egressDevice ) 1633 else: 1634 if not egressPort: 1635 main.log.error( "You must specify the egress port" ) 1636 return None 1637 1638 cmd += " " +\ 1639 str( egressDevice ) + "/" +\ 1640 str( egressPort ) 1641 1642 handle = self.sendline( cmd ) 1643 # If error, return error message 1644 if re.search( "Error", handle ): 1645 main.log.error( "Error in adding mpls intent" ) 1646 return None 1647 else: 1648 # TODO: print out all the options in this message? 1649 main.log.info( "MPLS intent installed between " + 1650 str( ingressDevice ) + " and " + 1651 str( egressDevice ) ) 1652 match = re.search('id=0x([\da-f]+),', handle) 1653 if match: 1654 return match.group()[3:-1] 1655 else: 1656 main.log.error( "Error, intent ID not found" ) 1657 return None 1658 except TypeError: 1659 main.log.exception( self.name + ": Object not as expected" ) 1660 return None 1661 except pexpect.EOF: 1662 main.log.error( self.name + ": EOF exception found" ) 1663 main.log.error( self.name + ": " + self.handle.before ) 1664 main.cleanup() 1665 main.exit() 1666 except Exception: 1667 main.log.exception( self.name + ": Uncaught exception!" ) 1668 main.cleanup() 1669 main.exit()
1670
1671 - def removeIntent( self, intentId, app='org.onosproject.cli', 1672 purge=False, sync=False ):
1673 """ 1674 Remove intent for specified application id and intent id 1675 Optional args:- 1676 -s or --sync: Waits for the removal before returning 1677 -p or --purge: Purge the intent from the store after removal 1678 1679 Returns: 1680 main.False on error and 1681 cli output otherwise 1682 """ 1683 try: 1684 cmdStr = "remove-intent" 1685 if purge: 1686 cmdStr += " -p" 1687 if sync: 1688 cmdStr += " -s" 1689 1690 cmdStr += " " + app + " " + str( intentId ) 1691 handle = self.sendline( cmdStr ) 1692 if re.search( "Error", handle ): 1693 main.log.error( "Error in removing intent" ) 1694 return main.FALSE 1695 else: 1696 # TODO: Should this be main.TRUE 1697 return handle 1698 except TypeError: 1699 main.log.exception( self.name + ": Object not as expected" ) 1700 return None 1701 except pexpect.EOF: 1702 main.log.error( self.name + ": EOF exception found" ) 1703 main.log.error( self.name + ": " + self.handle.before ) 1704 main.cleanup() 1705 main.exit() 1706 except Exception: 1707 main.log.exception( self.name + ": Uncaught exception!" ) 1708 main.cleanup() 1709 main.exit()
1710
1711 - def purgeWithdrawnIntents( self ):
1712 """ 1713 Purges all WITHDRAWN Intents 1714 """ 1715 try: 1716 cmdStr = "purge-intents" 1717 handle = self.sendline( cmdStr ) 1718 if re.search( "Error", handle ): 1719 main.log.error( "Error in purging intents" ) 1720 return main.FALSE 1721 else: 1722 return main.TRUE 1723 except TypeError: 1724 main.log.exception( self.name + ": Object not as expected" ) 1725 return None 1726 except pexpect.EOF: 1727 main.log.error( self.name + ": EOF exception found" ) 1728 main.log.error( self.name + ": " + self.handle.before ) 1729 main.cleanup() 1730 main.exit() 1731 except Exception: 1732 main.log.exception( self.name + ": Uncaught exception!" ) 1733 main.cleanup() 1734 main.exit()
1735
1736 - def routes( self, jsonFormat=False ):
1737 """ 1738 NOTE: This method should be used after installing application: 1739 onos-app-sdnip 1740 Optional: 1741 * jsonFormat: enable output formatting in json 1742 Description: 1743 Obtain all routes in the system 1744 """ 1745 try: 1746 cmdStr = "routes" 1747 if jsonFormat: 1748 cmdStr += " -j" 1749 handle = self.sendline( cmdStr ) 1750 return handle 1751 except TypeError: 1752 main.log.exception( self.name + ": Object not as expected" ) 1753 return None 1754 except pexpect.EOF: 1755 main.log.error( self.name + ": EOF exception found" ) 1756 main.log.error( self.name + ": " + self.handle.before ) 1757 main.cleanup() 1758 main.exit() 1759 except Exception: 1760 main.log.exception( self.name + ": Uncaught exception!" ) 1761 main.cleanup() 1762 main.exit()
1763
1764 - def intents( self, jsonFormat=True ):
1765 """ 1766 Optional: 1767 * jsonFormat: enable output formatting in json 1768 Description: 1769 Obtain intents currently installed 1770 """ 1771 try: 1772 cmdStr = "intents" 1773 if jsonFormat: 1774 cmdStr += " -j" 1775 handle = self.sendline( cmdStr ) 1776 return handle 1777 except TypeError: 1778 main.log.exception( self.name + ": Object not as expected" ) 1779 return None 1780 except pexpect.EOF: 1781 main.log.error( self.name + ": EOF exception found" ) 1782 main.log.error( self.name + ": " + self.handle.before ) 1783 main.cleanup() 1784 main.exit() 1785 except Exception: 1786 main.log.exception( self.name + ": Uncaught exception!" ) 1787 main.cleanup() 1788 main.exit()
1789
1790 - def getIntentState(self, intentsId, intentsJson=None):
1791 """ 1792 Check intent state. 1793 Accepts a single intent ID (string type) or a list of intent IDs. 1794 Returns the state(string type) of the id if a single intent ID is 1795 accepted. 1796 Returns a dictionary with intent IDs as the key and its 1797 corresponding states as the values 1798 Parameters: 1799 intentId: intent ID (string type) 1800 intentsJson: parsed json object from the onos:intents api 1801 Returns: 1802 state = An intent's state- INSTALL,WITHDRAWN etc. 1803 stateDict = Dictionary of intent's state. intent ID as the keys and 1804 state as the values. 1805 """ 1806 try: 1807 state = "State is Undefined" 1808 if not intentsJson: 1809 intentsJsonTemp = json.loads( self.intents() ) 1810 else: 1811 intentsJsonTemp = json.loads( intentsJson ) 1812 if isinstance( intentsId, types.StringType ): 1813 for intent in intentsJsonTemp: 1814 if intentsId == intent[ 'id' ]: 1815 state = intent[ 'state' ] 1816 return state 1817 main.log.info( "Cannot find intent ID" + str( intentsId ) + 1818 " on the list" ) 1819 return state 1820 elif isinstance( intentsId, types.ListType ): 1821 dictList = [] 1822 for i in xrange( len( intentsId ) ): 1823 stateDict = {} 1824 for intents in intentsJsonTemp: 1825 if intentsId[ i ] == intents[ 'id' ]: 1826 stateDict[ 'state' ] = intents[ 'state' ] 1827 stateDict[ 'id' ] = intentsId[ i ] 1828 dictList.append( stateDict ) 1829 break 1830 if len( intentsId ) != len( dictList ): 1831 main.log.info( "Cannot find some of the intent ID state" ) 1832 return dictList 1833 else: 1834 main.log.info( "Invalid intents ID entry" ) 1835 return None 1836 except TypeError: 1837 main.log.exception( self.name + ": Object not as expected" ) 1838 return None 1839 except pexpect.EOF: 1840 main.log.error( self.name + ": EOF exception found" ) 1841 main.log.error( self.name + ": " + self.handle.before ) 1842 main.cleanup() 1843 main.exit() 1844 except Exception: 1845 main.log.exception( self.name + ": Uncaught exception!" ) 1846 main.cleanup() 1847 main.exit()
1848
1849 - def checkIntentState( self, intentsId, expectedState='INSTALLED' ):
1850 """ 1851 Description: 1852 Check intents state 1853 Required: 1854 intentsId - List of intents ID to be checked 1855 Optional: 1856 expectedState - Check the expected state(s) of each intents 1857 state in the list. 1858 *NOTE: You can pass in a list of expected state, 1859 Eg: expectedState = [ 'INSTALLED' , 'INSTALLING' ] 1860 Return: 1861 Returns main.TRUE only if all intent are the same as expected states 1862 , otherwise, returns main.FALSE. 1863 """ 1864 try: 1865 # Generating a dictionary: intent id as a key and state as value 1866 returnValue = main.TRUE 1867 intentsDict = self.getIntentState( intentsId ) 1868 1869 #print "len of intentsDict ", str( len( intentsDict ) ) 1870 if len( intentsId ) != len( intentsDict ): 1871 main.log.info( self.name + "There is something wrong " + 1872 "getting intents state" ) 1873 return main.FALSE 1874 1875 if isinstance( expectedState, types.StringType ): 1876 for intents in intentsDict: 1877 if intents.get( 'state' ) != expectedState: 1878 main.log.debug( self.name + " : Intent ID - " + 1879 intents.get( 'id' ) + 1880 " actual state = " + 1881 intents.get( 'state' ) 1882 + " does not equal expected state = " 1883 + expectedState ) 1884 returnValue = main.FALSE 1885 1886 elif isinstance( expectedState, types.ListType ): 1887 for intents in intentsDict: 1888 if not any( state == intents.get( 'state' ) for state in 1889 expectedState ): 1890 main.log.debug( self.name + " : Intent ID - " + 1891 intents.get( 'id' ) + 1892 " actual state = " + 1893 intents.get( 'state' ) + 1894 " does not equal expected states = " 1895 + str( expectedState ) ) 1896 returnValue = main.FALSE 1897 1898 if returnValue == main.TRUE: 1899 main.log.info( self.name + ": All " + 1900 str( len( intentsDict ) ) + 1901 " intents are in " + str( expectedState ) + 1902 " state" ) 1903 return returnValue 1904 except TypeError: 1905 main.log.exception( self.name + ": Object not as expected" ) 1906 return None 1907 except pexpect.EOF: 1908 main.log.error( self.name + ": EOF exception found" ) 1909 main.log.error( self.name + ": " + self.handle.before ) 1910 main.cleanup() 1911 main.exit() 1912 except Exception: 1913 main.log.exception( self.name + ": Uncaught exception!" ) 1914 main.cleanup() 1915 main.exit()
1916
1917 - def flows( self, jsonFormat=True ):
1918 """ 1919 Optional: 1920 * jsonFormat: enable output formatting in json 1921 Description: 1922 Obtain flows currently installed 1923 """ 1924 try: 1925 cmdStr = "flows" 1926 if jsonFormat: 1927 cmdStr += " -j" 1928 handle = self.sendline( cmdStr ) 1929 if re.search( "Error:", handle ): 1930 main.log.error( self.name + ": flows() response: " + 1931 str( handle ) ) 1932 return handle 1933 except TypeError: 1934 main.log.exception( self.name + ": Object not as expected" ) 1935 return None 1936 except pexpect.EOF: 1937 main.log.error( self.name + ": EOF exception found" ) 1938 main.log.error( self.name + ": " + self.handle.before ) 1939 main.cleanup() 1940 main.exit() 1941 except Exception: 1942 main.log.exception( self.name + ": Uncaught exception!" ) 1943 main.cleanup() 1944 main.exit()
1945
1946 - def checkFlowsState( self ):
1947 """ 1948 Description: 1949 Check the if all the current flows are in ADDED state or 1950 PENDING_ADD state 1951 Return: 1952 returnValue - Returns main.TRUE only if all flows are in 1953 ADDED state or PENDING_ADD, return main.FALSE 1954 otherwise. 1955 """ 1956 try: 1957 tempFlows = json.loads( self.flows() ) 1958 #print tempFlows[0] 1959 returnValue = main.TRUE 1960 1961 for device in tempFlows: 1962 for flow in device.get( 'flows' ): 1963 if flow.get( 'state' ) != 'ADDED' and flow.get( 'state' ) != \ 1964 'PENDING_ADD': 1965 1966 main.log.info( self.name + ": flow Id: " + 1967 str( flow.get( 'groupId' ) ) + 1968 " | state:" + 1969 str( flow.get( 'state' ) ) ) 1970 returnValue = main.FALSE 1971 1972 return returnValue 1973 except TypeError: 1974 main.log.exception( self.name + ": Object not as expected" ) 1975 return None 1976 except pexpect.EOF: 1977 main.log.error( self.name + ": EOF exception found" ) 1978 main.log.error( self.name + ": " + self.handle.before ) 1979 main.cleanup() 1980 main.exit() 1981 except Exception: 1982 main.log.exception( self.name + ": Uncaught exception!" ) 1983 main.cleanup() 1984 main.exit()
1985
1986 - def pushTestIntents( self, dpidSrc, dpidDst, numIntents, 1987 numMult="", appId="", report=True ):
1988 """ 1989 Description: 1990 Push a number of intents in a batch format to 1991 a specific point-to-point intent definition 1992 Required: 1993 * dpidSrc: specify source dpid 1994 * dpidDst: specify destination dpid 1995 * numIntents: specify number of intents to push 1996 Optional: 1997 * numMult: number multiplier for multiplying 1998 the number of intents specified 1999 * appId: specify the application id init to further 2000 modularize the intents 2001 * report: default True, returns latency information 2002 """ 2003 try: 2004 cmd = "push-test-intents " +\ 2005 str( dpidSrc ) + " " + str( dpidDst ) + " " +\ 2006 str( numIntents ) 2007 if numMult: 2008 cmd += " " + str( numMult ) 2009 # If app id is specified, then numMult 2010 # must exist because of the way this command 2011 if appId: 2012 cmd += " " + str( appId ) 2013 handle = self.sendline( cmd ) 2014 if report: 2015 latResult = [] 2016 main.log.info( handle ) 2017 # Split result by newline 2018 newline = handle.split( "\r\r\n" ) 2019 # Ignore the first object of list, which is empty 2020 newline = newline[ 1: ] 2021 # Some sloppy parsing method to get the latency 2022 for result in newline: 2023 result = result.split( ": " ) 2024 # Append the first result of second parse 2025 latResult.append( result[ 1 ].split( " " )[ 0 ] ) 2026 main.log.info( latResult ) 2027 return latResult 2028 else: 2029 return main.TRUE 2030 except TypeError: 2031 main.log.exception( self.name + ": Object not as expected" ) 2032 return None 2033 except pexpect.EOF: 2034 main.log.error( self.name + ": EOF exception found" ) 2035 main.log.error( self.name + ": " + self.handle.before ) 2036 main.cleanup() 2037 main.exit() 2038 except Exception: 2039 main.log.exception( self.name + ": Uncaught exception!" ) 2040 main.cleanup() 2041 main.exit()
2042
2043 - def intentsEventsMetrics( self, jsonFormat=True ):
2044 """ 2045 Description:Returns topology metrics 2046 Optional: 2047 * jsonFormat: enable json formatting of output 2048 """ 2049 try: 2050 cmdStr = "intents-events-metrics" 2051 if jsonFormat: 2052 cmdStr += " -j" 2053 handle = self.sendline( cmdStr ) 2054 return handle 2055 except TypeError: 2056 main.log.exception( self.name + ": Object not as expected" ) 2057 return None 2058 except pexpect.EOF: 2059 main.log.error( self.name + ": EOF exception found" ) 2060 main.log.error( self.name + ": " + self.handle.before ) 2061 main.cleanup() 2062 main.exit() 2063 except Exception: 2064 main.log.exception( self.name + ": Uncaught exception!" ) 2065 main.cleanup() 2066 main.exit()
2067
2068 - def topologyEventsMetrics( self, jsonFormat=True ):
2069 """ 2070 Description:Returns topology metrics 2071 Optional: 2072 * jsonFormat: enable json formatting of output 2073 """ 2074 try: 2075 cmdStr = "topology-events-metrics" 2076 if jsonFormat: 2077 cmdStr += " -j" 2078 handle = self.sendline( cmdStr ) 2079 if handle: 2080 return handle 2081 elif jsonFormat: 2082 # Return empty json 2083 return '{}' 2084 else: 2085 return handle 2086 except TypeError: 2087 main.log.exception( self.name + ": Object not as expected" ) 2088 return None 2089 except pexpect.EOF: 2090 main.log.error( self.name + ": EOF exception found" ) 2091 main.log.error( self.name + ": " + self.handle.before ) 2092 main.cleanup() 2093 main.exit() 2094 except Exception: 2095 main.log.exception( self.name + ": Uncaught exception!" ) 2096 main.cleanup() 2097 main.exit()
2098 2099 # Wrapper functions **************** 2100 # Wrapper functions use existing driver 2101 # functions and extends their use case. 2102 # For example, we may use the output of 2103 # a normal driver function, and parse it 2104 # using a wrapper function 2105
2106 - def getAllIntentsId( self ):
2107 """ 2108 Description: 2109 Obtain all intent id's in a list 2110 """ 2111 try: 2112 # Obtain output of intents function 2113 intentsStr = self.intents(jsonFormat=False) 2114 intentIdList = [] 2115 2116 # Parse the intents output for ID's 2117 intentsList = [ s.strip() for s in intentsStr.splitlines() ] 2118 for intents in intentsList: 2119 match = re.search('id=0x([\da-f]+),', intents) 2120 if match: 2121 tmpId = match.group()[3:-1] 2122 intentIdList.append( tmpId ) 2123 return intentIdList 2124 2125 except TypeError: 2126 main.log.exception( self.name + ": Object not as expected" ) 2127 return None 2128 except pexpect.EOF: 2129 main.log.error( self.name + ": EOF exception found" ) 2130 main.log.error( self.name + ": " + self.handle.before ) 2131 main.cleanup() 2132 main.exit() 2133 except Exception: 2134 main.log.exception( self.name + ": Uncaught exception!" ) 2135 main.cleanup() 2136 main.exit()
2137
2138 - def FlowAddedCount( self, deviceId ):
2139 """ 2140 Determine the number of flow rules for the given device id that are 2141 in the added state 2142 """ 2143 try: 2144 cmdStr = "flows any " + str( deviceId ) + " | " +\ 2145 "grep 'state=ADDED' | wc -l" 2146 handle = self.sendline( cmdStr ) 2147 return handle 2148 except pexpect.EOF: 2149 main.log.error( self.name + ": EOF exception found" ) 2150 main.log.error( self.name + ": " + self.handle.before ) 2151 main.cleanup() 2152 main.exit() 2153 except Exception: 2154 main.log.exception( self.name + ": Uncaught exception!" ) 2155 main.cleanup() 2156 main.exit()
2157
2158 - def getAllDevicesId( self ):
2159 """ 2160 Use 'devices' function to obtain list of all devices 2161 and parse the result to obtain a list of all device 2162 id's. Returns this list. Returns empty list if no 2163 devices exist 2164 List is ordered sequentially 2165 2166 This function may be useful if you are not sure of the 2167 device id, and wish to execute other commands using 2168 the ids. By obtaining the list of device ids on the fly, 2169 you can iterate through the list to get mastership, etc. 2170 """ 2171 try: 2172 # Call devices and store result string 2173 devicesStr = self.devices( jsonFormat=False ) 2174 idList = [] 2175 2176 if not devicesStr: 2177 main.log.info( "There are no devices to get id from" ) 2178 return idList 2179 2180 # Split the string into list by comma 2181 deviceList = devicesStr.split( "," ) 2182 # Get temporary list of all arguments with string 'id=' 2183 tempList = [ dev for dev in deviceList if "id=" in dev ] 2184 # Split list further into arguments before and after string 2185 # 'id='. Get the latter portion ( the actual device id ) and 2186 # append to idList 2187 for arg in tempList: 2188 idList.append( arg.split( "id=" )[ 1 ] ) 2189 return idList 2190 2191 except TypeError: 2192 main.log.exception( self.name + ": Object not as expected" ) 2193 return None 2194 except pexpect.EOF: 2195 main.log.error( self.name + ": EOF exception found" ) 2196 main.log.error( self.name + ": " + self.handle.before ) 2197 main.cleanup() 2198 main.exit() 2199 except Exception: 2200 main.log.exception( self.name + ": Uncaught exception!" ) 2201 main.cleanup() 2202 main.exit()
2203
2204 - def getAllNodesId( self ):
2205 """ 2206 Uses 'nodes' function to obtain list of all nodes 2207 and parse the result of nodes to obtain just the 2208 node id's. 2209 Returns: 2210 list of node id's 2211 """ 2212 try: 2213 nodesStr = self.nodes( jsonFormat=True ) 2214 idList = [] 2215 # Sample nodesStr output 2216 # id=local, address=127.0.0.1:9876, state=ACTIVE * 2217 if not nodesStr: 2218 main.log.info( "There are no nodes to get id from" ) 2219 return idList 2220 nodesJson = json.loads( nodesStr ) 2221 idList = [ node.get('id') for node in nodesJson ] 2222 return idList 2223 2224 except TypeError: 2225 main.log.exception( self.name + ": Object not as expected" ) 2226 return None 2227 except pexpect.EOF: 2228 main.log.error( self.name + ": EOF exception found" ) 2229 main.log.error( self.name + ": " + self.handle.before ) 2230 main.cleanup() 2231 main.exit() 2232 except Exception: 2233 main.log.exception( self.name + ": Uncaught exception!" ) 2234 main.cleanup() 2235 main.exit()
2236
2237 - def getDevice( self, dpid=None ):
2238 """ 2239 Return the first device from the devices api whose 'id' contains 'dpid' 2240 Return None if there is no match 2241 """ 2242 try: 2243 if dpid is None: 2244 return None 2245 else: 2246 dpid = dpid.replace( ':', '' ) 2247 rawDevices = self.devices() 2248 devicesJson = json.loads( rawDevices ) 2249 # search json for the device with dpid then return the device 2250 for device in devicesJson: 2251 # print "%s in %s?" % ( dpid, device[ 'id' ] ) 2252 if dpid in device[ 'id' ]: 2253 return device 2254 return None 2255 except TypeError: 2256 main.log.exception( self.name + ": Object not as expected" ) 2257 return None 2258 except pexpect.EOF: 2259 main.log.error( self.name + ": EOF exception found" ) 2260 main.log.error( self.name + ": " + self.handle.before ) 2261 main.cleanup() 2262 main.exit() 2263 except Exception: 2264 main.log.exception( self.name + ": Uncaught exception!" ) 2265 main.cleanup() 2266 main.exit()
2267
2268 - def checkStatus( self, ip, numoswitch, numolink, logLevel="info" ):
2269 """ 2270 Checks the number of switches & links that ONOS sees against the 2271 supplied values. By default this will report to main.log, but the 2272 log level can be specified. 2273 2274 Params: ip = ip used for the onos cli 2275 numoswitch = expected number of switches 2276 numolink = expected number of links 2277 logLevel = level to log to. Currently accepts 2278 'info', 'warn' and 'report' 2279 2280 2281 logLevel can 2282 2283 Returns: main.TRUE if the number of switches and links are correct, 2284 main.FALSE if the number of switches and links is incorrect, 2285 and main.ERROR otherwise 2286 """ 2287 try: 2288 topology = self.getTopology( ip ) 2289 if topology == {}: 2290 return main.ERROR 2291 output = "" 2292 # Is the number of switches is what we expected 2293 devices = topology.get( 'devices', False ) 2294 links = topology.get( 'links', False ) 2295 if devices is False or links is False: 2296 return main.ERROR 2297 switchCheck = ( int( devices ) == int( numoswitch ) ) 2298 # Is the number of links is what we expected 2299 linkCheck = ( int( links ) == int( numolink ) ) 2300 if ( switchCheck and linkCheck ): 2301 # We expected the correct numbers 2302 output += "The number of links and switches match " +\ 2303 "what was expected" 2304 result = main.TRUE 2305 else: 2306 output += "The number of links and switches does not match " +\ 2307 "what was expected" 2308 result = main.FALSE 2309 output = output + "\n ONOS sees %i devices (%i expected) \ 2310 and %i links (%i expected)" % ( 2311 int( devices ), int( numoswitch ), int( links ), 2312 int( numolink ) ) 2313 if logLevel == "report": 2314 main.log.report( output ) 2315 elif logLevel == "warn": 2316 main.log.warn( output ) 2317 else: 2318 main.log.info( self.name + ": " + output ) 2319 return result 2320 except TypeError: 2321 main.log.exception( self.name + ": Object not as expected" ) 2322 return None 2323 except pexpect.EOF: 2324 main.log.error( self.name + ": EOF exception found" ) 2325 main.log.error( self.name + ": " + self.handle.before ) 2326 main.cleanup() 2327 main.exit() 2328 except Exception: 2329 main.log.exception( self.name + ": Uncaught exception!" ) 2330 main.cleanup() 2331 main.exit()
2332
2333 - def deviceRole( self, deviceId, onosNode, role="master" ):
2334 """ 2335 Calls the device-role cli command. 2336 deviceId must be the id of a device as seen in the onos devices command 2337 onosNode is the ip of one of the onos nodes in the cluster 2338 role must be either master, standby, or none 2339 2340 Returns: 2341 main.TRUE or main.FALSE based on argument verification and 2342 main.ERROR if command returns and error 2343 """ 2344 try: 2345 if role.lower() == "master" or role.lower() == "standby" or\ 2346 role.lower() == "none": 2347 cmdStr = "device-role " +\ 2348 str( deviceId ) + " " +\ 2349 str( onosNode ) + " " +\ 2350 str( role ) 2351 handle = self.sendline( cmdStr ) 2352 if re.search( "Error", handle ): 2353 # end color output to escape any colours 2354 # from the cli 2355 main.log.error( self.name + ": " + 2356 handle + '\033[0m' ) 2357 return main.ERROR 2358 return main.TRUE 2359 else: 2360 main.log.error( "Invalid 'role' given to device_role(). " + 2361 "Value was '" + str(role) + "'." ) 2362 return main.FALSE 2363 except TypeError: 2364 main.log.exception( self.name + ": Object not as expected" ) 2365 return None 2366 except pexpect.EOF: 2367 main.log.error( self.name + ": EOF exception found" ) 2368 main.log.error( self.name + ": " + self.handle.before ) 2369 main.cleanup() 2370 main.exit() 2371 except Exception: 2372 main.log.exception( self.name + ": Uncaught exception!" ) 2373 main.cleanup() 2374 main.exit()
2375
2376 - def clusters( self, jsonFormat=True ):
2377 """ 2378 Lists all clusters 2379 Optional argument: 2380 * jsonFormat - boolean indicating if you want output in json 2381 """ 2382 try: 2383 cmdStr = "clusters" 2384 if jsonFormat: 2385 cmdStr += " -j" 2386 handle = self.sendline( cmdStr ) 2387 return handle 2388 except TypeError: 2389 main.log.exception( self.name + ": Object not as expected" ) 2390 return None 2391 except pexpect.EOF: 2392 main.log.error( self.name + ": EOF exception found" ) 2393 main.log.error( self.name + ": " + self.handle.before ) 2394 main.cleanup() 2395 main.exit() 2396 except Exception: 2397 main.log.exception( self.name + ": Uncaught exception!" ) 2398 main.cleanup() 2399 main.exit()
2400
2401 - def electionTestLeader( self ):
2402 """ 2403 CLI command to get the current leader for the Election test application 2404 NOTE: Requires installation of the onos-app-election feature 2405 Returns: Node IP of the leader if one exists 2406 None if none exists 2407 Main.FALSE on error 2408 """ 2409 try: 2410 cmdStr = "election-test-leader" 2411 response = self.sendline( cmdStr ) 2412 # Leader 2413 leaderPattern = "The\scurrent\sleader\sfor\sthe\sElection\s" +\ 2414 "app\sis\s(?P<node>.+)\." 2415 nodeSearch = re.search( leaderPattern, response ) 2416 if nodeSearch: 2417 node = nodeSearch.group( 'node' ) 2418 main.log.info( "Election-test-leader on " + str( self.name ) + 2419 " found " + node + " as the leader" ) 2420 return node 2421 # no leader 2422 nullPattern = "There\sis\scurrently\sno\sleader\selected\sfor\s" +\ 2423 "the\sElection\sapp" 2424 nullSearch = re.search( nullPattern, response ) 2425 if nullSearch: 2426 main.log.info( "Election-test-leader found no leader on " + 2427 self.name ) 2428 return None 2429 # error 2430 errorPattern = "Command\snot\sfound" 2431 if re.search( errorPattern, response ): 2432 main.log.error( "Election app is not loaded on " + self.name ) 2433 # TODO: Should this be main.ERROR? 2434 return main.FALSE 2435 else: 2436 main.log.error( "Error in electionTestLeader on " + self.name + 2437 ": " + "unexpected response" ) 2438 main.log.error( repr( response ) ) 2439 return main.FALSE 2440 except TypeError: 2441 main.log.exception( self.name + ": Object not as expected" ) 2442 return main.FALSE 2443 except pexpect.EOF: 2444 main.log.error( self.name + ": EOF exception found" ) 2445 main.log.error( self.name + ": " + self.handle.before ) 2446 main.cleanup() 2447 main.exit() 2448 except Exception: 2449 main.log.exception( self.name + ": Uncaught exception!" ) 2450 main.cleanup() 2451 main.exit()
2452
2453 - def electionTestRun( self ):
2454 """ 2455 CLI command to run for leadership of the Election test application. 2456 NOTE: Requires installation of the onos-app-election feature 2457 Returns: Main.TRUE on success 2458 Main.FALSE on error 2459 """ 2460 try: 2461 cmdStr = "election-test-run" 2462 response = self.sendline( cmdStr ) 2463 # success 2464 successPattern = "Entering\sleadership\selections\sfor\sthe\s" +\ 2465 "Election\sapp." 2466 search = re.search( successPattern, response ) 2467 if search: 2468 main.log.info( self.name + " entering leadership elections " + 2469 "for the Election app." ) 2470 return main.TRUE 2471 # error 2472 errorPattern = "Command\snot\sfound" 2473 if re.search( errorPattern, response ): 2474 main.log.error( "Election app is not loaded on " + self.name ) 2475 return main.FALSE 2476 else: 2477 main.log.error( "Error in electionTestRun on " + self.name + 2478 ": " + "unexpected response" ) 2479 main.log.error( repr( response ) ) 2480 return main.FALSE 2481 except TypeError: 2482 main.log.exception( self.name + ": Object not as expected" ) 2483 return main.FALSE 2484 except pexpect.EOF: 2485 main.log.error( self.name + ": EOF exception found" ) 2486 main.log.error( self.name + ": " + self.handle.before ) 2487 main.cleanup() 2488 main.exit() 2489 except Exception: 2490 main.log.exception( self.name + ": Uncaught exception!" ) 2491 main.cleanup() 2492 main.exit()
2493
2494 - def electionTestWithdraw( self ):
2495 """ 2496 * CLI command to withdraw the local node from leadership election for 2497 * the Election test application. 2498 #NOTE: Requires installation of the onos-app-election feature 2499 Returns: Main.TRUE on success 2500 Main.FALSE on error 2501 """ 2502 try: 2503 cmdStr = "election-test-withdraw" 2504 response = self.sendline( cmdStr ) 2505 # success 2506 successPattern = "Withdrawing\sfrom\sleadership\selections\sfor" +\ 2507 "\sthe\sElection\sapp." 2508 if re.search( successPattern, response ): 2509 main.log.info( self.name + " withdrawing from leadership " + 2510 "elections for the Election app." ) 2511 return main.TRUE 2512 # error 2513 errorPattern = "Command\snot\sfound" 2514 if re.search( errorPattern, response ): 2515 main.log.error( "Election app is not loaded on " + self.name ) 2516 return main.FALSE 2517 else: 2518 main.log.error( "Error in electionTestWithdraw on " + 2519 self.name + ": " + "unexpected response" ) 2520 main.log.error( repr( response ) ) 2521 return main.FALSE 2522 except TypeError: 2523 main.log.exception( self.name + ": Object not as expected" ) 2524 return main.FALSE 2525 except pexpect.EOF: 2526 main.log.error( self.name + ": EOF exception found" ) 2527 main.log.error( self.name + ": " + self.handle.before ) 2528 main.cleanup() 2529 main.exit() 2530 except Exception: 2531 main.log.exception( self.name + ": Uncaught exception!" ) 2532 main.cleanup() 2533 main.exit()
2534
2535 - def getDevicePortsEnabledCount( self, dpid ):
2536 """ 2537 Get the count of all enabled ports on a particular device/switch 2538 """ 2539 try: 2540 dpid = str( dpid ) 2541 cmdStr = "onos:ports -e " + dpid + " | wc -l" 2542 output = self.sendline( cmdStr ) 2543 if re.search( "No such device", output ): 2544 main.log.error( "Error in getting ports" ) 2545 return ( output, "Error" ) 2546 else: 2547 return output 2548 except TypeError: 2549 main.log.exception( self.name + ": Object not as expected" ) 2550 return ( output, "Error" ) 2551 except pexpect.EOF: 2552 main.log.error( self.name + ": EOF exception found" ) 2553 main.log.error( self.name + ": " + self.handle.before ) 2554 main.cleanup() 2555 main.exit() 2556 except Exception: 2557 main.log.exception( self.name + ": Uncaught exception!" ) 2558 main.cleanup() 2559 main.exit()
2560
2561 - def getDeviceLinksActiveCount( self, dpid ):
2562 """ 2563 Get the count of all enabled ports on a particular device/switch 2564 """ 2565 try: 2566 dpid = str( dpid ) 2567 cmdStr = "onos:links " + dpid + " | grep ACTIVE | wc -l" 2568 output = self.sendline( cmdStr ) 2569 if re.search( "No such device", output ): 2570 main.log.error( "Error in getting ports " ) 2571 return ( output, "Error " ) 2572 else: 2573 return output 2574 except TypeError: 2575 main.log.exception( self.name + ": Object not as expected" ) 2576 return ( output, "Error " ) 2577 except pexpect.EOF: 2578 main.log.error( self.name + ": EOF exception found" ) 2579 main.log.error( self.name + ": " + self.handle.before ) 2580 main.cleanup() 2581 main.exit() 2582 except Exception: 2583 main.log.exception( self.name + ": Uncaught exception!" ) 2584 main.cleanup() 2585 main.exit()
2586
2587 - def getAllIntentIds( self ):
2588 """ 2589 Return a list of all Intent IDs 2590 """ 2591 try: 2592 cmdStr = "onos:intents | grep id=" 2593 output = self.sendline( cmdStr ) 2594 if re.search( "Error", output ): 2595 main.log.error( "Error in getting ports" ) 2596 return ( output, "Error" ) 2597 else: 2598 return output 2599 except TypeError: 2600 main.log.exception( self.name + ": Object not as expected" ) 2601 return ( output, "Error" ) 2602 except pexpect.EOF: 2603 main.log.error( self.name + ": EOF exception found" ) 2604 main.log.error( self.name + ": " + self.handle.before ) 2605 main.cleanup() 2606 main.exit() 2607 except Exception: 2608 main.log.exception( self.name + ": Uncaught exception!" ) 2609 main.cleanup() 2610 main.exit()
2611
2612 - def intentSummary( self ):
2613 """ 2614 Returns a dictionary containing the current intent states and the count 2615 """ 2616 try: 2617 intents = self.intents( ) 2618 states = [] 2619 for intent in json.loads( intents ): 2620 states.append( intent.get( 'state', None ) ) 2621 out = [ ( i, states.count( i ) ) for i in set( states ) ] 2622 main.log.info( dict( out ) ) 2623 return dict( out ) 2624 except TypeError: 2625 main.log.exception( self.name + ": Object not as expected" ) 2626 return None 2627 except pexpect.EOF: 2628 main.log.error( self.name + ": EOF exception found" ) 2629 main.log.error( self.name + ": " + self.handle.before ) 2630 main.cleanup() 2631 main.exit() 2632 except Exception: 2633 main.log.exception( self.name + ": Uncaught exception!" ) 2634 main.cleanup() 2635 main.exit()
2636
2637 - def leaders( self, jsonFormat=True ):
2638 """ 2639 Returns the output of the leaders command. 2640 Optional argument: 2641 * jsonFormat - boolean indicating if you want output in json 2642 """ 2643 try: 2644 cmdStr = "onos:leaders" 2645 if jsonFormat: 2646 cmdStr += " -j" 2647 output = self.sendline( cmdStr ) 2648 return output 2649 except TypeError: 2650 main.log.exception( self.name + ": Object not as expected" ) 2651 return None 2652 except pexpect.EOF: 2653 main.log.error( self.name + ": EOF exception found" ) 2654 main.log.error( self.name + ": " + self.handle.before ) 2655 main.cleanup() 2656 main.exit() 2657 except Exception: 2658 main.log.exception( self.name + ": Uncaught exception!" ) 2659 main.cleanup() 2660 main.exit()
2661
2662 - def leaderCandidates( self, jsonFormat=True ):
2663 """ 2664 Returns the output of the leaders -c command. 2665 Optional argument: 2666 * jsonFormat - boolean indicating if you want output in json 2667 """ 2668 try: 2669 cmdStr = "onos:leaders -c" 2670 if jsonFormat: 2671 cmdStr += " -j" 2672 output = self.sendline( cmdStr ) 2673 return output 2674 except TypeError: 2675 main.log.exception( self.name + ": Object not as expected" ) 2676 return None 2677 except pexpect.EOF: 2678 main.log.error( self.name + ": EOF exception found" ) 2679 main.log.error( self.name + ": " + self.handle.before ) 2680 main.cleanup() 2681 main.exit() 2682 except Exception: 2683 main.log.exception( self.name + ": Uncaught exception!" ) 2684 main.cleanup() 2685 main.exit()
2686
2687 - def specificLeaderCandidate(self,topic):
2688 """ 2689 Returns a list in format [leader,candidate1,candidate2,...] for a given 2690 topic parameter and an empty list if the topic doesn't exist 2691 If no leader is elected leader in the returned list will be "none" 2692 Returns None if there is a type error processing the json object 2693 """ 2694 try: 2695 cmdStr = "onos:leaders -c -j" 2696 output = self.sendline( cmdStr ) 2697 output = json.loads(output) 2698 results = [] 2699 for dict in output: 2700 if dict["topic"] == topic: 2701 leader = dict["leader"] 2702 candidates = re.split(", ",dict["candidates"][1:-1]) 2703 results.append(leader) 2704 results.extend(candidates) 2705 return results 2706 except TypeError: 2707 main.log.exception( self.name + ": Object not as expected" ) 2708 return None 2709 except pexpect.EOF: 2710 main.log.error( self.name + ": EOF exception found" ) 2711 main.log.error( self.name + ": " + self.handle.before ) 2712 main.cleanup() 2713 main.exit() 2714 except Exception: 2715 main.log.exception( self.name + ": Uncaught exception!" ) 2716 main.cleanup() 2717 main.exit()
2718
2719 - def pendingMap( self, jsonFormat=True ):
2720 """ 2721 Returns the output of the intent Pending map. 2722 """ 2723 try: 2724 cmdStr = "onos:intents -p" 2725 if jsonFormat: 2726 cmdStr += " -j" 2727 output = self.sendline( cmdStr ) 2728 return output 2729 except TypeError: 2730 main.log.exception( self.name + ": Object not as expected" ) 2731 return None 2732 except pexpect.EOF: 2733 main.log.error( self.name + ": EOF exception found" ) 2734 main.log.error( self.name + ": " + self.handle.before ) 2735 main.cleanup() 2736 main.exit() 2737 except Exception: 2738 main.log.exception( self.name + ": Uncaught exception!" ) 2739 main.cleanup() 2740 main.exit()
2741
2742 - def partitions( self, jsonFormat=True ):
2743 """ 2744 Returns the output of the raft partitions command for ONOS. 2745 """ 2746 # Sample JSON 2747 # { 2748 # "leader": "tcp://10.128.30.11:7238", 2749 # "members": [ 2750 # "tcp://10.128.30.11:7238", 2751 # "tcp://10.128.30.17:7238", 2752 # "tcp://10.128.30.13:7238", 2753 # ], 2754 # "name": "p1", 2755 # "term": 3 2756 # }, 2757 try: 2758 cmdStr = "onos:partitions" 2759 if jsonFormat: 2760 cmdStr += " -j" 2761 output = self.sendline( cmdStr ) 2762 return output 2763 except TypeError: 2764 main.log.exception( self.name + ": Object not as expected" ) 2765 return None 2766 except pexpect.EOF: 2767 main.log.error( self.name + ": EOF exception found" ) 2768 main.log.error( self.name + ": " + self.handle.before ) 2769 main.cleanup() 2770 main.exit() 2771 except Exception: 2772 main.log.exception( self.name + ": Uncaught exception!" ) 2773 main.cleanup() 2774 main.exit()
2775
2776 - def apps( self, jsonFormat=True ):
2777 """ 2778 Returns the output of the apps command for ONOS. This command lists 2779 information about installed ONOS applications 2780 """ 2781 # Sample JSON object 2782 # [{"name":"org.onosproject.openflow","id":0,"version":"1.2.0", 2783 # "description":"ONOS OpenFlow protocol southbound providers", 2784 # "origin":"ON.Lab","permissions":"[]","featuresRepo":"", 2785 # "features":"[onos-openflow]","state":"ACTIVE"}] 2786 try: 2787 cmdStr = "onos:apps" 2788 if jsonFormat: 2789 cmdStr += " -j" 2790 output = self.sendline( cmdStr ) 2791 assert "Error executing command" not in output 2792 return output 2793 # FIXME: look at specific exceptions/Errors 2794 except AssertionError: 2795 main.log.error( "Error in processing onos:app command: " + 2796 str( output ) ) 2797 return None 2798 except TypeError: 2799 main.log.exception( self.name + ": Object not as expected" ) 2800 return None 2801 except pexpect.EOF: 2802 main.log.error( self.name + ": EOF exception found" ) 2803 main.log.error( self.name + ": " + self.handle.before ) 2804 main.cleanup() 2805 main.exit() 2806 except Exception: 2807 main.log.exception( self.name + ": Uncaught exception!" ) 2808 main.cleanup() 2809 main.exit()
2810
2811 - def appStatus( self, appName ):
2812 """ 2813 Uses the onos:apps cli command to return the status of an application. 2814 Returns: 2815 "ACTIVE" - If app is installed and activated 2816 "INSTALLED" - If app is installed and deactivated 2817 "UNINSTALLED" - If app is not installed 2818 None - on error 2819 """ 2820 try: 2821 if not isinstance( appName, types.StringType ): 2822 main.log.error( self.name + ".appStatus(): appName must be" + 2823 " a string" ) 2824 return None 2825 output = self.apps( jsonFormat=True ) 2826 appsJson = json.loads( output ) 2827 state = None 2828 for app in appsJson: 2829 if appName == app.get('name'): 2830 state = app.get('state') 2831 break 2832 if state == "ACTIVE" or state == "INSTALLED": 2833 return state 2834 elif state is None: 2835 return "UNINSTALLED" 2836 elif state: 2837 main.log.error( "Unexpected state from 'onos:apps': " + 2838 str( state ) ) 2839 return state 2840 except TypeError: 2841 main.log.exception( self.name + ": Object not as expected" ) 2842 return None 2843 except pexpect.EOF: 2844 main.log.error( self.name + ": EOF exception found" ) 2845 main.log.error( self.name + ": " + self.handle.before ) 2846 main.cleanup() 2847 main.exit() 2848 except Exception: 2849 main.log.exception( self.name + ": Uncaught exception!" ) 2850 main.cleanup() 2851 main.exit()
2852
2853 - def app( self, appName, option ):
2854 """ 2855 Interacts with the app command for ONOS. This command manages 2856 application inventory. 2857 """ 2858 try: 2859 # Validate argument types 2860 valid = True 2861 if not isinstance( appName, types.StringType ): 2862 main.log.error( self.name + ".app(): appName must be a " + 2863 "string" ) 2864 valid = False 2865 if not isinstance( option, types.StringType ): 2866 main.log.error( self.name + ".app(): option must be a string" ) 2867 valid = False 2868 if not valid: 2869 return main.FALSE 2870 # Validate Option 2871 option = option.lower() 2872 # NOTE: Install may become a valid option 2873 if option == "activate": 2874 pass 2875 elif option == "deactivate": 2876 pass 2877 elif option == "uninstall": 2878 pass 2879 else: 2880 # Invalid option 2881 main.log.error( "The ONOS app command argument only takes " + 2882 "the values: (activate|deactivate|uninstall)" + 2883 "; was given '" + option + "'") 2884 return main.FALSE 2885 cmdStr = "onos:app " + option + " " + appName 2886 output = self.sendline( cmdStr ) 2887 if "Error executing command" in output: 2888 main.log.error( "Error in processing onos:app command: " + 2889 str( output ) ) 2890 return main.FALSE 2891 elif "No such application" in output: 2892 main.log.error( "The application '" + appName + 2893 "' is not installed in ONOS" ) 2894 return main.FALSE 2895 elif "Command not found:" in output: 2896 main.log.error( "Error in processing onos:app command: " + 2897 str( output ) ) 2898 return main.FALSE 2899 elif "Unsupported command:" in output: 2900 main.log.error( "Incorrect command given to 'app': " + 2901 str( output ) ) 2902 # NOTE: we may need to add more checks here 2903 # else: Command was successful 2904 # main.log.debug( "app response: " + repr( output ) ) 2905 return main.TRUE 2906 except TypeError: 2907 main.log.exception( self.name + ": Object not as expected" ) 2908 return main.ERROR 2909 except pexpect.EOF: 2910 main.log.error( self.name + ": EOF exception found" ) 2911 main.log.error( self.name + ": " + self.handle.before ) 2912 main.cleanup() 2913 main.exit() 2914 except Exception: 2915 main.log.exception( self.name + ": Uncaught exception!" ) 2916 main.cleanup() 2917 main.exit()
2918
2919 - def activateApp( self, appName, check=True ):
2920 """ 2921 Activate an app that is already installed in ONOS 2922 appName is the hierarchical app name, not the feature name 2923 If check is True, method will check the status of the app after the 2924 command is issued 2925 Returns main.TRUE if the command was successfully sent 2926 main.FALSE if the cli responded with an error or given 2927 incorrect input 2928 """ 2929 try: 2930 if not isinstance( appName, types.StringType ): 2931 main.log.error( self.name + ".activateApp(): appName must be" + 2932 " a string" ) 2933 return main.FALSE 2934 status = self.appStatus( appName ) 2935 if status == "INSTALLED": 2936 response = self.app( appName, "activate" ) 2937 if check and response == main.TRUE: 2938 for i in range(10): # try 10 times then give up 2939 # TODO: Check with Thomas about this delay 2940 status = self.appStatus( appName ) 2941 if status == "ACTIVE": 2942 return main.TRUE 2943 else: 2944 main.log.debug( "The state of application " + 2945 appName + " is " + status ) 2946 time.sleep( 1 ) 2947 return main.FALSE 2948 else: # not 'check' or command didn't succeed 2949 return response 2950 elif status == "ACTIVE": 2951 return main.TRUE 2952 elif status == "UNINSTALLED": 2953 main.log.error( self.name + ": Tried to activate the " + 2954 "application '" + appName + "' which is not " + 2955 "installed." ) 2956 else: 2957 main.log.error( "Unexpected return value from appStatus: " + 2958 str( status ) ) 2959 return main.ERROR 2960 except TypeError: 2961 main.log.exception( self.name + ": Object not as expected" ) 2962 return main.ERROR 2963 except pexpect.EOF: 2964 main.log.error( self.name + ": EOF exception found" ) 2965 main.log.error( self.name + ": " + self.handle.before ) 2966 main.cleanup() 2967 main.exit() 2968 except Exception: 2969 main.log.exception( self.name + ": Uncaught exception!" ) 2970 main.cleanup() 2971 main.exit()
2972
2973 - def deactivateApp( self, appName, check=True ):
2974 """ 2975 Deactivate an app that is already activated in ONOS 2976 appName is the hierarchical app name, not the feature name 2977 If check is True, method will check the status of the app after the 2978 command is issued 2979 Returns main.TRUE if the command was successfully sent 2980 main.FALSE if the cli responded with an error or given 2981 incorrect input 2982 """ 2983 try: 2984 if not isinstance( appName, types.StringType ): 2985 main.log.error( self.name + ".deactivateApp(): appName must " + 2986 "be a string" ) 2987 return main.FALSE 2988 status = self.appStatus( appName ) 2989 if status == "INSTALLED": 2990 return main.TRUE 2991 elif status == "ACTIVE": 2992 response = self.app( appName, "deactivate" ) 2993 if check and response == main.TRUE: 2994 for i in range(10): # try 10 times then give up 2995 status = self.appStatus( appName ) 2996 if status == "INSTALLED": 2997 return main.TRUE 2998 else: 2999 time.sleep( 1 ) 3000 return main.FALSE 3001 else: # not check or command didn't succeed 3002 return response 3003 elif status == "UNINSTALLED": 3004 main.log.warn( self.name + ": Tried to deactivate the " + 3005 "application '" + appName + "' which is not " + 3006 "installed." ) 3007 return main.TRUE 3008 else: 3009 main.log.error( "Unexpected return value from appStatus: " + 3010 str( status ) ) 3011 return main.ERROR 3012 except TypeError: 3013 main.log.exception( self.name + ": Object not as expected" ) 3014 return main.ERROR 3015 except pexpect.EOF: 3016 main.log.error( self.name + ": EOF exception found" ) 3017 main.log.error( self.name + ": " + self.handle.before ) 3018 main.cleanup() 3019 main.exit() 3020 except Exception: 3021 main.log.exception( self.name + ": Uncaught exception!" ) 3022 main.cleanup() 3023 main.exit()
3024
3025 - def uninstallApp( self, appName, check=True ):
3026 """ 3027 Uninstall an app that is already installed in ONOS 3028 appName is the hierarchical app name, not the feature name 3029 If check is True, method will check the status of the app after the 3030 command is issued 3031 Returns main.TRUE if the command was successfully sent 3032 main.FALSE if the cli responded with an error or given 3033 incorrect input 3034 """ 3035 # TODO: check with Thomas about the state machine for apps 3036 try: 3037 if not isinstance( appName, types.StringType ): 3038 main.log.error( self.name + ".uninstallApp(): appName must " + 3039 "be a string" ) 3040 return main.FALSE 3041 status = self.appStatus( appName ) 3042 if status == "INSTALLED": 3043 response = self.app( appName, "uninstall" ) 3044 if check and response == main.TRUE: 3045 for i in range(10): # try 10 times then give up 3046 status = self.appStatus( appName ) 3047 if status == "UNINSTALLED": 3048 return main.TRUE 3049 else: 3050 time.sleep( 1 ) 3051 return main.FALSE 3052 else: # not check or command didn't succeed 3053 return response 3054 elif status == "ACTIVE": 3055 main.log.warn( self.name + ": Tried to uninstall the " + 3056 "application '" + appName + "' which is " + 3057 "currently active." ) 3058 response = self.app( appName, "uninstall" ) 3059 if check and response == main.TRUE: 3060 for i in range(10): # try 10 times then give up 3061 status = self.appStatus( appName ) 3062 if status == "UNINSTALLED": 3063 return main.TRUE 3064 else: 3065 time.sleep( 1 ) 3066 return main.FALSE 3067 else: # not check or command didn't succeed 3068 return response 3069 elif status == "UNINSTALLED": 3070 return main.TRUE 3071 else: 3072 main.log.error( "Unexpected return value from appStatus: " + 3073 str( status ) ) 3074 return main.ERROR 3075 except TypeError: 3076 main.log.exception( self.name + ": Object not as expected" ) 3077 return main.ERROR 3078 except pexpect.EOF: 3079 main.log.error( self.name + ": EOF exception found" ) 3080 main.log.error( self.name + ": " + self.handle.before ) 3081 main.cleanup() 3082 main.exit() 3083 except Exception: 3084 main.log.exception( self.name + ": Uncaught exception!" ) 3085 main.cleanup() 3086 main.exit()
3087
3088 - def appIDs( self, jsonFormat=True ):
3089 """ 3090 Show the mappings between app id and app names given by the 'app-ids' 3091 cli command 3092 """ 3093 try: 3094 cmdStr = "app-ids" 3095 if jsonFormat: 3096 cmdStr += " -j" 3097 output = self.sendline( cmdStr ) 3098 assert "Error executing command" not in output 3099 return output 3100 except AssertionError: 3101 main.log.error( "Error in processing onos:app-ids command: " + 3102 str( output ) ) 3103 return None 3104 except TypeError: 3105 main.log.exception( self.name + ": Object not as expected" ) 3106 return None 3107 except pexpect.EOF: 3108 main.log.error( self.name + ": EOF exception found" ) 3109 main.log.error( self.name + ": " + self.handle.before ) 3110 main.cleanup() 3111 main.exit() 3112 except Exception: 3113 main.log.exception( self.name + ": Uncaught exception!" ) 3114 main.cleanup() 3115 main.exit()
3116
3117 - def appToIDCheck( self ):
3118 """ 3119 This method will check that each application's ID listed in 'apps' is 3120 the same as the ID listed in 'app-ids'. The check will also check that 3121 there are no duplicate IDs issued. Note that an app ID should be 3122 a globaly unique numerical identifier for app/app-like features. Once 3123 an ID is registered, the ID is never freed up so that if an app is 3124 reinstalled it will have the same ID. 3125 3126 Returns: main.TRUE if the check passes and 3127 main.FALSE if the check fails or 3128 main.ERROR if there is some error in processing the test 3129 """ 3130 try: 3131 bail = False 3132 ids = self.appIDs( jsonFormat=True ) 3133 if ids: 3134 ids = json.loads( ids ) 3135 else: 3136 main.log.error( "app-ids returned nothing:" + repr( ids ) ) 3137 bail = True 3138 apps = self.apps( jsonFormat=True ) 3139 if apps: 3140 apps = json.loads( apps ) 3141 else: 3142 main.log.error( "apps returned nothing:" + repr( apps ) ) 3143 bail = True 3144 if bail: 3145 return main.FALSE 3146 result = main.TRUE 3147 for app in apps: 3148 appID = app.get( 'id' ) 3149 if appID is None: 3150 main.log.error( "Error parsing app: " + str( app ) ) 3151 result = main.FALSE 3152 appName = app.get( 'name' ) 3153 if appName is None: 3154 main.log.error( "Error parsing app: " + str( app ) ) 3155 result = main.FALSE 3156 # get the entry in ids that has the same appID 3157 current = filter( lambda item: item[ 'id' ] == appID, ids ) 3158 # main.log.debug( "Comparing " + str( app ) + " to " + 3159 # str( current ) ) 3160 if not current: # if ids doesn't have this id 3161 result = main.FALSE 3162 main.log.error( "'app-ids' does not have the ID for " + 3163 str( appName ) + " that apps does." ) 3164 elif len( current ) > 1: 3165 # there is more than one app with this ID 3166 result = main.FALSE 3167 # We will log this later in the method 3168 elif not current[0][ 'name' ] == appName: 3169 currentName = current[0][ 'name' ] 3170 result = main.FALSE 3171 main.log.error( "'app-ids' has " + str( currentName ) + 3172 " registered under id:" + str( appID ) + 3173 " but 'apps' has " + str( appName ) ) 3174 else: 3175 pass # id and name match! 3176 # now make sure that app-ids has no duplicates 3177 idsList = [] 3178 namesList = [] 3179 for item in ids: 3180 idsList.append( item[ 'id' ] ) 3181 namesList.append( item[ 'name' ] ) 3182 if len( idsList ) != len( set( idsList ) ) or\ 3183 len( namesList ) != len( set( namesList ) ): 3184 main.log.error( "'app-ids' has some duplicate entries: \n" 3185 + json.dumps( ids, 3186 sort_keys=True, 3187 indent=4, 3188 separators=( ',', ': ' ) ) ) 3189 result = main.FALSE 3190 return result 3191 except ( ValueError, TypeError ): 3192 main.log.exception( self.name + ": Object not as expected" ) 3193 return main.ERROR 3194 except pexpect.EOF: 3195 main.log.error( self.name + ": EOF exception found" ) 3196 main.log.error( self.name + ": " + self.handle.before ) 3197 main.cleanup() 3198 main.exit() 3199 except Exception: 3200 main.log.exception( self.name + ": Uncaught exception!" ) 3201 main.cleanup() 3202 main.exit()
3203
3204 - def getCfg( self, component=None, propName=None, short=False, 3205 jsonFormat=True ):
3206 """ 3207 Get configuration settings from onos cli 3208 Optional arguments: 3209 component - Optionally only list configurations for a specific 3210 component. If None, all components with configurations 3211 are displayed. Case Sensitive string. 3212 propName - If component is specified, propName option will show 3213 only this specific configuration from that component. 3214 Case Sensitive string. 3215 jsonFormat - Returns output as json. Note that this will override 3216 the short option 3217 short - Short, less verbose, version of configurations. 3218 This is overridden by the json option 3219 returns: 3220 Output from cli as a string or None on error 3221 """ 3222 try: 3223 baseStr = "cfg" 3224 cmdStr = " get" 3225 componentStr = "" 3226 if component: 3227 componentStr += " " + component 3228 if propName: 3229 componentStr += " " + propName 3230 if jsonFormat: 3231 baseStr += " -j" 3232 elif short: 3233 baseStr += " -s" 3234 output = self.sendline( baseStr + cmdStr + componentStr ) 3235 assert "Error executing command" not in output 3236 return output 3237 except AssertionError: 3238 main.log.error( "Error in processing 'cfg get' command: " + 3239 str( output ) ) 3240 return None 3241 except TypeError: 3242 main.log.exception( self.name + ": Object not as expected" ) 3243 return None 3244 except pexpect.EOF: 3245 main.log.error( self.name + ": EOF exception found" ) 3246 main.log.error( self.name + ": " + self.handle.before ) 3247 main.cleanup() 3248 main.exit() 3249 except Exception: 3250 main.log.exception( self.name + ": Uncaught exception!" ) 3251 main.cleanup() 3252 main.exit()
3253
3254 - def setCfg( self, component, propName, value=None, check=True ):
3255 """ 3256 Set/Unset configuration settings from ONOS cli 3257 Required arguments: 3258 component - The case sensitive name of the component whose 3259 property is to be set 3260 propName - The case sensitive name of the property to be set/unset 3261 Optional arguments: 3262 value - The value to set the property to. If None, will unset the 3263 property and revert it to it's default value(if applicable) 3264 check - Boolean, Check whether the option was successfully set this 3265 only applies when a value is given. 3266 returns: 3267 main.TRUE on success or main.FALSE on failure. If check is False, 3268 will return main.TRUE unless there is an error 3269 """ 3270 try: 3271 baseStr = "cfg" 3272 cmdStr = " set " + str( component ) + " " + str( propName ) 3273 if value is not None: 3274 cmdStr += " " + str( value ) 3275 output = self.sendline( baseStr + cmdStr ) 3276 assert "Error executing command" not in output 3277 if value and check: 3278 results = self.getCfg( component=str( component ), 3279 propName=str( propName ), 3280 jsonFormat=True ) 3281 # Check if current value is what we just set 3282 try: 3283 jsonOutput = json.loads( results ) 3284 current = jsonOutput[ 'value' ] 3285 except ( ValueError, TypeError ): 3286 main.log.exception( "Error parsing cfg output" ) 3287 main.log.error( "output:" + repr( results ) ) 3288 return main.FALSE 3289 if current == str( value ): 3290 return main.TRUE 3291 return main.FALSE 3292 return main.TRUE 3293 except AssertionError: 3294 main.log.error( "Error in processing 'cfg set' command: " + 3295 str( output ) ) 3296 return main.FALSE 3297 except TypeError: 3298 main.log.exception( self.name + ": Object not as expected" ) 3299 return main.FALSE 3300 except pexpect.EOF: 3301 main.log.error( self.name + ": EOF exception found" ) 3302 main.log.error( self.name + ": " + self.handle.before ) 3303 main.cleanup() 3304 main.exit() 3305 except Exception: 3306 main.log.exception( self.name + ": Uncaught exception!" ) 3307 main.cleanup() 3308 main.exit()
3309
3310 - def setTestAdd( self, setName, values ):
3311 """ 3312 CLI command to add elements to a distributed set. 3313 Arguments: 3314 setName - The name of the set to add to. 3315 values - The value(s) to add to the set, space seperated. 3316 Example usages: 3317 setTestAdd( "set1", "a b c" ) 3318 setTestAdd( "set2", "1" ) 3319 returns: 3320 main.TRUE on success OR 3321 main.FALSE if elements were already in the set OR 3322 main.ERROR on error 3323 """ 3324 try: 3325 cmdStr = "set-test-add " + str( setName ) + " " + str( values ) 3326 output = self.sendline( cmdStr ) 3327 try: 3328 # TODO: Maybe make this less hardcoded 3329 # ConsistentMap Exceptions 3330 assert "org.onosproject.store.service" not in output 3331 # Node not leader 3332 assert "java.lang.IllegalStateException" not in output 3333 except AssertionError: 3334 main.log.error( "Error in processing '" + cmdStr + "' " + 3335 "command: " + str( output ) ) 3336 retryTime = 30 # Conservative time, given by Madan 3337 main.log.info( "Waiting " + str( retryTime ) + 3338 "seconds before retrying." ) 3339 time.sleep( retryTime ) # Due to change in mastership 3340 output = self.sendline( cmdStr ) 3341 assert "Error executing command" not in output 3342 positiveMatch = "\[(.*)\] was added to the set " + str( setName ) 3343 negativeMatch = "\[(.*)\] was already in set " + str( setName ) 3344 main.log.info( self.name + ": " + output ) 3345 if re.search( positiveMatch, output): 3346 return main.TRUE 3347 elif re.search( negativeMatch, output): 3348 return main.FALSE 3349 else: 3350 main.log.error( self.name + ": setTestAdd did not" + 3351 " match expected output" ) 3352 main.log.debug( self.name + " actual: " + repr( output ) ) 3353 return main.ERROR 3354 except AssertionError: 3355 main.log.error( "Error in processing '" + cmdStr + "' command: " + 3356 str( output ) ) 3357 return main.ERROR 3358 except TypeError: 3359 main.log.exception( self.name + ": Object not as expected" ) 3360 return main.ERROR 3361 except pexpect.EOF: 3362 main.log.error( self.name + ": EOF exception found" ) 3363 main.log.error( self.name + ": " + self.handle.before ) 3364 main.cleanup() 3365 main.exit() 3366 except Exception: 3367 main.log.exception( self.name + ": Uncaught exception!" ) 3368 main.cleanup() 3369 main.exit()
3370
3371 - def setTestRemove( self, setName, values, clear=False, retain=False ):
3372 """ 3373 CLI command to remove elements from a distributed set. 3374 Required arguments: 3375 setName - The name of the set to remove from. 3376 values - The value(s) to remove from the set, space seperated. 3377 Optional arguments: 3378 clear - Clear all elements from the set 3379 retain - Retain only the given values. (intersection of the 3380 original set and the given set) 3381 returns: 3382 main.TRUE on success OR 3383 main.FALSE if the set was not changed OR 3384 main.ERROR on error 3385 """ 3386 try: 3387 cmdStr = "set-test-remove " 3388 if clear: 3389 cmdStr += "-c " + str( setName ) 3390 elif retain: 3391 cmdStr += "-r " + str( setName ) + " " + str( values ) 3392 else: 3393 cmdStr += str( setName ) + " " + str( values ) 3394 output = self.sendline( cmdStr ) 3395 try: 3396 # TODO: Maybe make this less hardcoded 3397 # ConsistentMap Exceptions 3398 assert "org.onosproject.store.service" not in output 3399 # Node not leader 3400 assert "java.lang.IllegalStateException" not in output 3401 except AssertionError: 3402 main.log.error( "Error in processing '" + cmdStr + "' " + 3403 "command: " + str( output ) ) 3404 retryTime = 30 # Conservative time, given by Madan 3405 main.log.info( "Waiting " + str( retryTime ) + 3406 "seconds before retrying." ) 3407 time.sleep( retryTime ) # Due to change in mastership 3408 output = self.sendline( cmdStr ) 3409 assert "Error executing command" not in output 3410 main.log.info( self.name + ": " + output ) 3411 if clear: 3412 pattern = "Set " + str( setName ) + " cleared" 3413 if re.search( pattern, output ): 3414 return main.TRUE 3415 elif retain: 3416 positivePattern = str( setName ) + " was pruned to contain " +\ 3417 "only elements of set \[(.*)\]" 3418 negativePattern = str( setName ) + " was not changed by " +\ 3419 "retaining only elements of the set " +\ 3420 "\[(.*)\]" 3421 if re.search( positivePattern, output ): 3422 return main.TRUE 3423 elif re.search( negativePattern, output ): 3424 return main.FALSE 3425 else: 3426 positivePattern = "\[(.*)\] was removed from the set " +\ 3427 str( setName ) 3428 if ( len( values.split() ) == 1 ): 3429 negativePattern = "\[(.*)\] was not in set " +\ 3430 str( setName ) 3431 else: 3432 negativePattern = "No element of \[(.*)\] was in set " +\ 3433 str( setName ) 3434 if re.search( positivePattern, output ): 3435 return main.TRUE 3436 elif re.search( negativePattern, output ): 3437 return main.FALSE 3438 main.log.error( self.name + ": setTestRemove did not" + 3439 " match expected output" ) 3440 main.log.debug( self.name + " expected: " + pattern ) 3441 main.log.debug( self.name + " actual: " + repr( output ) ) 3442 return main.ERROR 3443 except AssertionError: 3444 main.log.error( "Error in processing '" + cmdStr + "' command: " + 3445 str( output ) ) 3446 return main.ERROR 3447 except TypeError: 3448 main.log.exception( self.name + ": Object not as expected" ) 3449 return main.ERROR 3450 except pexpect.EOF: 3451 main.log.error( self.name + ": EOF exception found" ) 3452 main.log.error( self.name + ": " + self.handle.before ) 3453 main.cleanup() 3454 main.exit() 3455 except Exception: 3456 main.log.exception( self.name + ": Uncaught exception!" ) 3457 main.cleanup() 3458 main.exit()
3459
3460 - def setTestGet( self, setName, values="" ):
3461 """ 3462 CLI command to get the elements in a distributed set. 3463 Required arguments: 3464 setName - The name of the set to remove from. 3465 Optional arguments: 3466 values - The value(s) to check if in the set, space seperated. 3467 returns: 3468 main.ERROR on error OR 3469 A list of elements in the set if no optional arguments are 3470 supplied OR 3471 A tuple containing the list then: 3472 main.FALSE if the given values are not in the set OR 3473 main.TRUE if the given values are in the set OR 3474 """ 3475 try: 3476 values = str( values ).strip() 3477 setName = str( setName ).strip() 3478 length = len( values.split() ) 3479 containsCheck = None 3480 # Patterns to match 3481 setPattern = "\[(.*)\]" 3482 pattern = "Items in set " + setName + ":\n" + setPattern 3483 containsTrue = "Set " + setName + " contains the value " + values 3484 containsFalse = "Set " + setName + " did not contain the value " +\ 3485 values 3486 containsAllTrue = "Set " + setName + " contains the the subset " +\ 3487 setPattern 3488 containsAllFalse = "Set " + setName + " did not contain the the" +\ 3489 " subset " + setPattern 3490 3491 cmdStr = "set-test-get " 3492 cmdStr += setName + " " + values 3493 output = self.sendline( cmdStr ) 3494 try: 3495 # TODO: Maybe make this less hardcoded 3496 # ConsistentMap Exceptions 3497 assert "org.onosproject.store.service" not in output 3498 # Node not leader 3499 assert "java.lang.IllegalStateException" not in output 3500 except AssertionError: 3501 main.log.error( "Error in processing '" + cmdStr + "' " + 3502 "command: " + str( output ) ) 3503 retryTime = 30 # Conservative time, given by Madan 3504 main.log.info( "Waiting " + str( retryTime ) + 3505 "seconds before retrying." ) 3506 time.sleep( retryTime ) # Due to change in mastership 3507 output = self.sendline( cmdStr ) 3508 assert "Error executing command" not in output 3509 main.log.info( self.name + ": " + output ) 3510 3511 if length == 0: 3512 match = re.search( pattern, output ) 3513 else: # if given values 3514 if length == 1: # Contains output 3515 patternTrue = pattern + "\n" + containsTrue 3516 patternFalse = pattern + "\n" + containsFalse 3517 else: # ContainsAll output 3518 patternTrue = pattern + "\n" + containsAllTrue 3519 patternFalse = pattern + "\n" + containsAllFalse 3520 matchTrue = re.search( patternTrue, output ) 3521 matchFalse = re.search( patternFalse, output ) 3522 if matchTrue: 3523 containsCheck = main.TRUE 3524 match = matchTrue 3525 elif matchFalse: 3526 containsCheck = main.FALSE 3527 match = matchFalse 3528 else: 3529 main.log.error( self.name + " setTestGet did not match " +\ 3530 "expected output" ) 3531 main.log.debug( self.name + " expected: " + pattern ) 3532 main.log.debug( self.name + " actual: " + repr( output ) ) 3533 match = None 3534 if match: 3535 setMatch = match.group( 1 ) 3536 if setMatch == '': 3537 setList = [] 3538 else: 3539 setList = setMatch.split( ", " ) 3540 if length > 0: 3541 return ( setList, containsCheck ) 3542 else: 3543 return setList 3544 else: # no match 3545 main.log.error( self.name + ": setTestGet did not" + 3546 " match expected output" ) 3547 main.log.debug( self.name + " expected: " + pattern ) 3548 main.log.debug( self.name + " actual: " + repr( output ) ) 3549 return main.ERROR 3550 except AssertionError: 3551 main.log.error( "Error in processing '" + cmdStr + "' command: " + 3552 str( output ) ) 3553 return main.ERROR 3554 except TypeError: 3555 main.log.exception( self.name + ": Object not as expected" ) 3556 return main.ERROR 3557 except pexpect.EOF: 3558 main.log.error( self.name + ": EOF exception found" ) 3559 main.log.error( self.name + ": " + self.handle.before ) 3560 main.cleanup() 3561 main.exit() 3562 except Exception: 3563 main.log.exception( self.name + ": Uncaught exception!" ) 3564 main.cleanup() 3565 main.exit()
3566
3567 - def setTestSize( self, setName ):
3568 """ 3569 CLI command to get the elements in a distributed set. 3570 Required arguments: 3571 setName - The name of the set to remove from. 3572 returns: 3573 The integer value of the size returned or 3574 None on error 3575 """ 3576 try: 3577 # TODO: Should this check against the number of elements returned 3578 # and then return true/false based on that? 3579 setName = str( setName ).strip() 3580 # Patterns to match 3581 setPattern = "\[(.*)\]" 3582 pattern = "There are (\d+) items in set " + setName + ":\n" +\ 3583 setPattern 3584 cmdStr = "set-test-get -s " 3585 cmdStr += setName 3586 output = self.sendline( cmdStr ) 3587 try: 3588 # TODO: Maybe make this less hardcoded 3589 # ConsistentMap Exceptions 3590 assert "org.onosproject.store.service" not in output 3591 # Node not leader 3592 assert "java.lang.IllegalStateException" not in output 3593 except AssertionError: 3594 main.log.error( "Error in processing '" + cmdStr + "' " + 3595 "command: " + str( output ) ) 3596 retryTime = 30 # Conservative time, given by Madan 3597 main.log.info( "Waiting " + str( retryTime ) + 3598 "seconds before retrying." ) 3599 time.sleep( retryTime ) # Due to change in mastership 3600 output = self.sendline( cmdStr ) 3601 assert "Error executing command" not in output 3602 main.log.info( self.name + ": " + output ) 3603 match = re.search( pattern, output ) 3604 if match: 3605 setSize = int( match.group( 1 ) ) 3606 setMatch = match.group( 2 ) 3607 if len( setMatch.split() ) == setSize: 3608 main.log.info( "The size returned by " + self.name + 3609 " matches the number of elements in " + 3610 "the returned set" ) 3611 else: 3612 main.log.error( "The size returned by " + self.name + 3613 " does not match the number of " + 3614 "elements in the returned set." ) 3615 return setSize 3616 else: # no match 3617 main.log.error( self.name + ": setTestGet did not" + 3618 " match expected output" ) 3619 main.log.debug( self.name + " expected: " + pattern ) 3620 main.log.debug( self.name + " actual: " + repr( output ) ) 3621 return None 3622 except AssertionError: 3623 main.log.error( "Error in processing '" + cmdStr + "' command: " + 3624 str( output ) ) 3625 return None 3626 except TypeError: 3627 main.log.exception( self.name + ": Object not as expected" ) 3628 return None 3629 except pexpect.EOF: 3630 main.log.error( self.name + ": EOF exception found" ) 3631 main.log.error( self.name + ": " + self.handle.before ) 3632 main.cleanup() 3633 main.exit() 3634 except Exception: 3635 main.log.exception( self.name + ": Uncaught exception!" ) 3636 main.cleanup() 3637 main.exit()
3638
3639 - def counters( self, jsonFormat=True ):
3640 """ 3641 Command to list the various counters in the system. 3642 returns: 3643 if jsonFormat, a string of the json object returned by the cli 3644 command 3645 if not jsonFormat, the normal string output of the cli command 3646 None on error 3647 """ 3648 try: 3649 counters = {} 3650 cmdStr = "counters" 3651 if jsonFormat: 3652 cmdStr += " -j" 3653 output = self.sendline( cmdStr ) 3654 assert "Error executing command" not in output 3655 main.log.info( self.name + ": " + output ) 3656 return output 3657 except AssertionError: 3658 main.log.error( "Error in processing 'counters' command: " + 3659 str( output ) ) 3660 return None 3661 except TypeError: 3662 main.log.exception( self.name + ": Object not as expected" ) 3663 return None 3664 except pexpect.EOF: 3665 main.log.error( self.name + ": EOF exception found" ) 3666 main.log.error( self.name + ": " + self.handle.before ) 3667 main.cleanup() 3668 main.exit() 3669 except Exception: 3670 main.log.exception( self.name + ": Uncaught exception!" ) 3671 main.cleanup() 3672 main.exit()
3673
3674 - def counterTestAddAndGet( self, counter, delta=1, inMemory=False ):
3675 """ 3676 CLI command to add a delta to then get a distributed counter. 3677 Required arguments: 3678 counter - The name of the counter to increment. 3679 Optional arguments: 3680 delta - The long to add to the counter 3681 inMemory - use in memory map for the counter 3682 returns: 3683 integer value of the counter or 3684 None on Error 3685 """ 3686 try: 3687 counter = str( counter ) 3688 delta = int( delta ) 3689 cmdStr = "counter-test-increment " 3690 if inMemory: 3691 cmdStr += "-i " 3692 cmdStr += counter 3693 if delta != 1: 3694 cmdStr += " " + str( delta ) 3695 output = self.sendline( cmdStr ) 3696 try: 3697 # TODO: Maybe make this less hardcoded 3698 # ConsistentMap Exceptions 3699 assert "org.onosproject.store.service" not in output 3700 # Node not leader 3701 assert "java.lang.IllegalStateException" not in output 3702 except AssertionError: 3703 main.log.error( "Error in processing '" + cmdStr + "' " + 3704 "command: " + str( output ) ) 3705 retryTime = 30 # Conservative time, given by Madan 3706 main.log.info( "Waiting " + str( retryTime ) + 3707 "seconds before retrying." ) 3708 time.sleep( retryTime ) # Due to change in mastership 3709 output = self.sendline( cmdStr ) 3710 assert "Error executing command" not in output 3711 main.log.info( self.name + ": " + output ) 3712 pattern = counter + " was updated to (-?\d+)" 3713 match = re.search( pattern, output ) 3714 if match: 3715 return int( match.group( 1 ) ) 3716 else: 3717 main.log.error( self.name + ": counterTestAddAndGet did not" + 3718 " match expected output." ) 3719 main.log.debug( self.name + " expected: " + pattern ) 3720 main.log.debug( self.name + " actual: " + repr( output ) ) 3721 return None 3722 except AssertionError: 3723 main.log.error( "Error in processing '" + cmdStr + "'" + 3724 " command: " + str( output ) ) 3725 return None 3726 except TypeError: 3727 main.log.exception( self.name + ": Object not as expected" ) 3728 return None 3729 except pexpect.EOF: 3730 main.log.error( self.name + ": EOF exception found" ) 3731 main.log.error( self.name + ": " + self.handle.before ) 3732 main.cleanup() 3733 main.exit() 3734 except Exception: 3735 main.log.exception( self.name + ": Uncaught exception!" ) 3736 main.cleanup() 3737 main.exit()
3738
3739 - def counterTestGetAndAdd( self, counter, delta=1, inMemory=False ):
3740 """ 3741 CLI command to get a distributed counter then add a delta to it. 3742 Required arguments: 3743 counter - The name of the counter to increment. 3744 Optional arguments: 3745 delta - The long to add to the counter 3746 inMemory - use in memory map for the counter 3747 returns: 3748 integer value of the counter or 3749 None on Error 3750 """ 3751 try: 3752 counter = str( counter ) 3753 delta = int( delta ) 3754 cmdStr = "counter-test-increment -g " 3755 if inMemory: 3756 cmdStr += "-i " 3757 cmdStr += counter 3758 if delta != 1: 3759 cmdStr += " " + str( delta ) 3760 output = self.sendline( cmdStr ) 3761 try: 3762 # TODO: Maybe make this less hardcoded 3763 # ConsistentMap Exceptions 3764 assert "org.onosproject.store.service" not in output 3765 # Node not leader 3766 assert "java.lang.IllegalStateException" not in output 3767 except AssertionError: 3768 main.log.error( "Error in processing '" + cmdStr + "' " + 3769 "command: " + str( output ) ) 3770 retryTime = 30 # Conservative time, given by Madan 3771 main.log.info( "Waiting " + str( retryTime ) + 3772 "seconds before retrying." ) 3773 time.sleep( retryTime ) # Due to change in mastership 3774 output = self.sendline( cmdStr ) 3775 assert "Error executing command" not in output 3776 main.log.info( self.name + ": " + output ) 3777 pattern = counter + " was updated to (-?\d+)" 3778 match = re.search( pattern, output ) 3779 if match: 3780 return int( match.group( 1 ) ) 3781 else: 3782 main.log.error( self.name + ": counterTestGetAndAdd did not" + 3783 " match expected output." ) 3784 main.log.debug( self.name + " expected: " + pattern ) 3785 main.log.debug( self.name + " actual: " + repr( output ) ) 3786 return None 3787 except AssertionError: 3788 main.log.error( "Error in processing '" + cmdStr + "'" + 3789 " command: " + str( output ) ) 3790 return None 3791 except TypeError: 3792 main.log.exception( self.name + ": Object not as expected" ) 3793 return None 3794 except pexpect.EOF: 3795 main.log.error( self.name + ": EOF exception found" ) 3796 main.log.error( self.name + ": " + self.handle.before ) 3797 main.cleanup() 3798 main.exit() 3799 except Exception: 3800 main.log.exception( self.name + ": Uncaught exception!" ) 3801 main.cleanup() 3802 main.exit()
3803 3804
3805 - def summary( self, jsonFormat=True ):
3806 """ 3807 Description: Execute summary command in onos 3808 Returns: json object ( summary -j ), returns main.FALSE if there is 3809 no output 3810 3811 """ 3812 try: 3813 cmdStr = "summary" 3814 if jsonFormat: 3815 cmdStr += " -j" 3816 handle = self.sendline( cmdStr ) 3817 3818 if re.search( "Error:", handle ): 3819 main.log.error( self.name + ": summary() response: " + 3820 str( handle ) ) 3821 if not handle: 3822 main.log.error( self.name + ": There is no output in " + 3823 "summary command" ) 3824 return main.FALSE 3825 return handle 3826 except TypeError: 3827 main.log.exception( self.name + ": Object not as expected" ) 3828 return None 3829 except pexpect.EOF: 3830 main.log.error( self.name + ": EOF exception found" ) 3831 main.log.error( self.name + ": " + self.handle.before ) 3832 main.cleanup() 3833 main.exit() 3834 except Exception: 3835 main.log.exception( self.name + ": Uncaught exception!" ) 3836 main.cleanup() 3837 main.exit()
3838