Update Cluster Driver

Change-Id: I8a3a57e19637ff210548e57d41178e6f194cf694
diff --git a/TestON/drivers/common/api/controller/onosrestdriver.py b/TestON/drivers/common/api/controller/onosrestdriver.py
index 8a1b43e..2af59d6 100755
--- a/TestON/drivers/common/api/controller/onosrestdriver.py
+++ b/TestON/drivers/common/api/controller/onosrestdriver.py
@@ -1929,18 +1929,16 @@
 
     def checkStatus(
             self,
-            numoswitch,
-            numolink,
-            numoctrl = -1,
+            numswitch,
+            numlink,
             logLevel="info" ):
         """
         Checks the number of switches & links that ONOS sees against the
         supplied values. By default this will report to main.log, but the
         log level can be specific.
 
-        Params: numoswitch = expected number of switches
-                numolink = expected number of links
-                numoctrl = expected number of controllers
+        Params: numswitch = expected number of switches
+                numlink = expected number of links
                 logLevel = level to log to.
                 Currently accepts 'info', 'warn' and 'report'
 
@@ -1950,20 +1948,19 @@
         """
         try:
             topology = self.getTopology( self.topology() )
+            #summary = self.summary()
             if topology == {}:
                 return main.ERROR
             output = ""
             # Is the number of switches is what we expected
             devices = topology.get( 'devices', False )
             links = topology.get( 'links', False )
-            nodes = topology.get( 'nodes' , False )
-            if devices is False or links is False or nodes is False:
+            if devices is False or links is False:
                 return main.ERROR
-            switchCheck = ( int( devices ) == int( numoswitch ) )
+            switchCheck = ( int( devices ) == int( numswitch ) )
             # Is the number of links is what we expected
-            linkCheck = ( int( links ) == int( numolink ) )
-            nodeCheck = ( int(nodes) == int(numoctrl) )or int(numoctrl) == -1
-            if switchCheck and linkCheck and nodeCheck:
+            linkCheck = ( int( links ) == int( numlink ) )
+            if switchCheck and linkCheck:
                 # We expected the correct numbers
                 output = output + "The number of links and switches match "\
                     + "what was expected"
@@ -1974,12 +1971,9 @@
                     "what was expected"
                 result = main.FALSE
             output = output + "\n ONOS sees %i devices" % int( devices )
-            output = output + " (%i expected) " % int( numoswitch )
+            output = output + " (%i expected) " % int( numswitch )
             output = output + "and %i links " % int( links )
-            output = output + "(%i expected)" % int( numolink )
-            if int( numoctrl ) > 0:
-                output = output + "and %i controllers " % int( nodes )
-                output = output + "(%i expected)" % int( numoctrl )
+            output = output + "(%i expected)" % int( numlink )
             if logLevel == "report":
                 main.log.report( output )
             elif logLevel == "warn":
diff --git a/TestON/drivers/common/cli/onosclusterdriver.py b/TestON/drivers/common/cli/onosclusterdriver.py
index 0a99d05..f531a3c 100755
--- a/TestON/drivers/common/cli/onosclusterdriver.py
+++ b/TestON/drivers/common/cli/onosclusterdriver.py
@@ -54,20 +54,32 @@
 
         We will look into each of the node's component handles to try to find the attreibute, looking at REST first
         """
+        usedDriver = False
         if hasattr( self.REST, name ):
-            main.log.debug( "Using Rest driver's attribute for '%s'" % ( name ) )
-            return getattr( self.REST, name)
+            main.log.warn( "Rest driver has attribute '%s'" % ( name ) )
+            if not usedDriver:
+                usedDriver = True
+                main.log.debug("Using Rest driver's attribute for '%s'" % (name))
+                f = getattr( self.REST, name)
         if hasattr( self.CLI, name ):
-            main.log.debug( "Using CLI driver's attribute for '%s'" % ( name ) )
-            return getattr( self.CLI, name)
+            main.log.warn( "CLI driver has attribute '%s'" % ( name ) )
+            if not usedDriver:
+                usedDriver = True
+                main.log.debug("Using CLI driver's attribute for '%s'" % (name))
+                f = getattr( self.CLI, name)
         if hasattr( self.Bench, name ):
-            main.log.debug( "Using Bench driver's attribute for '%s'" % ( name ) )
-            return getattr( self.Bench, name)
-        raise AttributeError( "Could not find the attribute %s in %s or it's component handles" % ( name, self ) )
+            main.log.warn( "Bench driver has attribute '%s'" % ( name ) )
+            if not usedDriver:
+                usedDriver = True
+                main.log.debug("Using Bench driver's attribute for '%s'" % (name))
+                f = getattr( self.Bench, name)
+        if usedDriver:
+            return f
+        raise AttributeError( "Could not find the attribute %s in %r or it's component handles" % ( name, self ) )
 
 
 
-    def __init__( self, name, ipAddress, CLI=None, REST=None, Bench=None ):
+    def __init__( self, name, ipAddress, CLI=None, REST=None, Bench=None, pos=None, userName=None ):
         #TODO: validate these arguments
         self.name = str( name )
         self.ipAddress = ipAddress
@@ -75,7 +87,9 @@
         self.REST = REST
         self.Bench = Bench
         self.active = False
-
+        self.pos = pos
+        self.ip_address = ipAddress
+        self.user_name = userName
 
 class OnosClusterDriver( CLI ):
 
@@ -229,16 +243,19 @@
             response = main.FALSE
         return response
 
-    def setCliOptions( self, name ):
+    def setCliOptions( self, name, host ):
         """
         Parse the cluster options to create an ONOS cli component with the given name
         """
         main.componentDictionary[name] = main.componentDictionary[self.name].copy()
+        clihost = main.componentDictionary[ name ][ 'COMPONENTS' ].get( "diff_clihost", "" )
+        if clihost == "True":
+            main.componentDictionary[ name ][ 'host' ] = host
         main.componentDictionary[name]['type'] = "OnosCliDriver"
         main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
         main.log.debug( main.componentDictionary[name] )
 
-    def createCliComponent( self, name ):
+    def createCliComponent( self, name, host ):
         """
         Creates a new onos cli component.
 
@@ -252,7 +269,7 @@
             getattr( main, name )
         except AttributeError:
             # namespace is clear, creating component
-            self.setCliOptions( name )
+            self.setCliOptions( name, host )
             return main.componentInit( name )
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
@@ -377,10 +394,10 @@
             # Even if it is just the entire possible cluster size
             ip = self.onosIps[ 'OC' + str( i ) ]
 
-            cli = self.createCliComponent( cliName )
+            cli = self.createCliComponent( cliName, ip )
             rest = self.createRestComponent( restName, ip )
             bench = self.createBenchComponent( benchName )
-            self.nodes.append( Controller( prefix + str( i ), ip, cli, rest, bench ) )
+            self.nodes.append( Controller( prefix + str( i ), ip, cli, rest, bench, i - 1, self.user_name ) )
 
         ## DEBUG ########################################################################
         print "Prininting NODES::"
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index 6923a29..f0ce0ce 100755
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -1406,6 +1406,29 @@
             main.cleanup()
             main.exit()
 
+    def preventAutoRespawn( self ):
+        """
+        Description:
+            This will prevent ONOSservice to automatically
+            respawn.
+        """
+        try:
+            self.handle.sendline( "sed -i -e 's/^respawn$/#respawn/g' tools/package/init/onos.conf" )
+            self.handle.expect( "\$" )  # $ from the command
+            self.handle.sendline( "sed -i -e 's/^Restart=always/Restart=no/g' tools/package/init/onos.service" )
+            self.handle.expect( "\$" )  # $ from the command
+            self.handle.expect( "\$" )  # $ from the prompt
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+
     def pushTestIntentsShell(
             self,
             dpidSrc,
diff --git a/TestON/drivers/common/clidriver.py b/TestON/drivers/common/clidriver.py
index 2dc1274..aa8a12e 100644
--- a/TestON/drivers/common/clidriver.py
+++ b/TestON/drivers/common/clidriver.py
@@ -362,3 +362,92 @@
                                 dstPath,
                                 pwd=remoteHost.pwd,
                                 direction=direction )
+
+    def sshToNode( self, ipAddress, uName="sdn", pwd="rocks" ):
+        ssh_newkey = 'Are you sure you want to continue connecting'
+        refused = "ssh: connect to host " + ipAddress + " port 22: Connection refused"
+        handle = pexpect.spawn( 'ssh -X ' +
+                                uName +
+                                '@' +
+                                ipAddress,
+                                env={ "TERM": "xterm-mono" },
+                                maxread=1000000,
+                                timeout=60 )
+
+        # set tty window size
+        handle.setwinsize( 24, 250 )
+
+        i = 5
+        while i == 5:
+            i = handle.expect( [
+                                    ssh_newkey,
+                                    'password:|Password:',
+                                    pexpect.EOF,
+                                    pexpect.TIMEOUT,
+                                    refused,
+                                    'teston>',
+                                    self.prompt ],
+                            120 )
+            if i == 0:  # Accept key, then expect either a password prompt or access
+                main.log.info( "ssh key confirmation received, send yes" )
+                handle.sendline( 'yes' )
+                i = 5  # Run the loop again
+                continue
+            if i == 1:  # Password required
+                if pwd:
+                    main.log.info(
+                    "ssh connection asked for password, gave password" )
+                else:
+                    main.log.info( "Server asked for password, but none was "
+                                    "given in the .topo file. Trying "
+                                    "no password.")
+                    pwd = ""
+                handle.sendline( pwd )
+                j = handle.expect( [ self.prompt,
+                                     'password:|Password:',
+                                     pexpect.EOF,
+                                     pexpect.TIMEOUT ],
+                                     120 )
+                if j != 0:
+                    main.log.error( "Incorrect Password" )
+                    main.cleanup()
+                    main.exit()
+            elif i == 2:
+                main.log.error( "Connection timeout" )
+                main.cleanup()
+                main.exit()
+            elif i == 3:  # timeout
+                main.log.error(
+                    "No route to the Host " +
+                    uName +
+                    "@" +
+                    ipAddress )
+                main.cleanup()
+                main.exit()
+            elif i == 4:
+                main.log.error(
+                    "ssh: connect to host " +
+                    ipAddress +
+                    " port 22: Connection refused" )
+                main.cleanup()
+                main.exit()
+            elif i == 6:
+                main.log.info( "Password not required logged in" )
+
+        handle.sendline( "" )
+        handle.expect( self.prompt )
+        handle.sendline( "cd" )
+        handle.expect( self.prompt )
+
+        main.log.info ( "Successfully ssh to " + ipAddress + "." )
+        return handle
+
+    def exitFromSsh( self, handle, ipAddress ):
+        handle.sendline( "logout" )
+        try:
+            handle.expect( "closed." )
+            main.log.info ( "Successfully closed ssh connection from " + ipAddress )
+        except pexpect.EOF:
+            main.log.error( "Failed to close the connection from " + ipAddress )
+        handle.sendline( "" )
+        handle.expect( self.prompt )
\ No newline at end of file
diff --git a/TestON/drivers/component.py b/TestON/drivers/component.py
index fd8ba67..968306e 100644
--- a/TestON/drivers/component.py
+++ b/TestON/drivers/component.py
@@ -114,7 +114,6 @@
         args = utilities.parse_args( [ "RETURNS" ], **kwargs )
         return args[ "RETURNS" ]
 
-
 if __name__ != "__main__":
     import sys
     sys.modules[ __name__ ] = Component()