[SDFAB-284] Paired Leaves Upstream link failure test

TODO: TO test performance, we need to choose a target not on the
internet. Currently just pinging 8.8.8.8

Change-Id: I164f6bb44d6fa9685c7a466a8a0a83a5926ac395
diff --git a/TestON/drivers/common/cli/hostdriver.py b/TestON/drivers/common/cli/hostdriver.py
index 7111c74..080f6cc 100644
--- a/TestON/drivers/common/cli/hostdriver.py
+++ b/TestON/drivers/common/cli/hostdriver.py
@@ -39,6 +39,7 @@
         self.inband = False
         self.prompt = "\$"
         self.scapyPrompt = ">>>"
+        self.tempRoutes = []
 
     def connect( self, **connectargs ):
         """
@@ -120,6 +121,9 @@
         try:
             if self.handle:
                 self.preDisconnect()
+                if self.tempRoutes:
+                    for r in self.tempRoutes:
+                        self.deleteRoute( *r )
                 # Disconnect from the host
                 if not self.options[ 'inband' ] == 'True':
                     self.handle.sendline( "" )
@@ -219,6 +223,132 @@
             main.log.error( self.name + ":     " + self.handle.before )
             return main.FALSE
 
+    def getRoutes( self ):
+        """
+        Returns the output of 'ip route show' command
+        # TODO: process and return a a list or json object
+        """
+        try:
+            cmd = "ip route show"
+            self.handle.sendline( cmd )
+            i = self.handle.expect( [ "password|Password", self.prompt ]  )
+            if i == 0:
+                self.handle.sendline( self.pwd )
+                j = self.handle.expect( [ "password|Password", self.prompt ] )
+                if j != 1:
+                    main.log.error( "Incorrect password" )
+                    return main.FALSE
+            return self.handle.before
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":     " + self.handle.before )
+            return main.FALSE
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.log.error( self.name + ":     " + self.handle.before )
+            return main.FALSE
+
+    def addRoute( self, route, gw, interface=None, sudoRequired=True, purgeOnDisconnect=True ):
+        """
+        Adds a static route to the host
+        Arguments:
+        * route - String, CIDR notation for the destination subnet
+        * gw - String, IP address of gateway
+        Optional Arguments:
+        * interface - String, The interface to use for this route, defaults to None, or the default interface
+        * sudoRequired - Boolean, whether sudo is needed for this command, defaults to True
+        * purgeOnDisconnect - Boolean, remove this route before disconnecting from component
+        """
+        try:
+            cmd = "ip route add %s via %s" % ( route, gw )
+            if sudoRequired:
+                cmd = "sudo %s" % cmd
+            if interface:
+                cmd = "%s dev %s" % ( cmd, interface )
+            if purgeOnDisconnect:
+                self.tempRoutes.append( (route, gw, interface, sudoRequired ) )
+            self.handle.sendline( cmd )
+            i = self.handle.expect( [ "password|Password", self.prompt, "Error" ]  )
+            output = ""
+            if i == 2:
+                output += self.handle.before + self.handle.after
+                self.handle.expect( self.prompt )
+                output += self.handle.before + self.handle.after
+                main.log.error( "%s: Erorr in ip route command: %s" % ( self.name, output ) )
+                return main.FALSE
+            elif i == 0:
+                self.handle.sendline( self.pwd )
+                j = self.handle.expect( [ "password|Password", self.prompt, "Error" ] )
+                if j == 0:
+                    main.log.error( "Incorrect password" )
+                    return main.FALSE
+                elif j == 2:
+                    output += self.handle.before + self.handle.after
+                    self.handle.expect( self.prompt )
+                    output += self.handle.before + self.handle.after
+                    main.log.error( "%s: Erorr in ip route command: %s" % ( self.name, output ) )
+                    return main.FALSE
+            output += self.handle.before + self.handle.after
+            main.log.debug( output )
+            return self.handle.before
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":     " + self.handle.before )
+            return main.FALSE
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.log.error( self.name + ":     " + self.handle.before )
+            return main.FALSE
+
+    def deleteRoute( self, route, gw, interface=None, sudoRequired=True ):
+        """
+        Deletess a static route from the host
+        Arguments:
+        * route - String, CIDR notation for the destination subnet
+        * gw - String, IP address of gateway
+        Optional Arguments:
+        * interface - String, The interface to use for this route, defaults to None, or the default interface
+        * sudoRequired - Boolean, whether sudo is needed for this command, defaults to True
+        """
+        try:
+            cmd = "ip route del %s via %s" % ( route, gw )
+            if sudoRequired:
+                cmd = "sudo %s" % cmd
+            if interface:
+                cmd = "%s dev %s" % ( cmd, interface )
+            self.handle.sendline( cmd )
+            i = self.handle.expect( [ "password|Password", self.prompt, "Error" ]  )
+            output = ""
+            if i == 2:
+                output += self.handle.before + self.handle.after
+                self.handle.expect( self.prompt )
+                output += self.handle.before + self.handle.after
+                main.log.error( "%s: Erorr in ip route command: %s" % ( self.name, output ) )
+                return main.FALSE
+            elif i == 0:
+                self.handle.sendline( self.pwd )
+                j = self.handle.expect( [ "password|Password", self.prompt, "Error" ] )
+                if j == 0:
+                    main.log.error( "Incorrect password" )
+                    return main.FALSE
+                elif j == 2:
+                    output += self.handle.before + self.handle.after
+                    self.handle.expect( self.prompt )
+                    output += self.handle.before + self.handle.after
+                    main.log.error( "%s: Erorr in ip route command: %s" % ( self.name, output ) )
+                    return main.FALSE
+            output += self.handle.before + self.handle.after
+            main.log.debug( output )
+            return self.handle.before
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":     " + self.handle.before )
+            return main.FALSE
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.log.error( self.name + ":     " + self.handle.before )
+            return main.FALSE
+
     def getIPAddress( self, iface=None, proto='IPV4' ):
         """
         Returns IP address of the host
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 7c2acb5..bafa284 100755
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -6908,3 +6908,85 @@
         except Exception:
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanAndExit()
+
+    def routeAdd( self, prefix, nextHop, jsonFormat=True ):
+        """
+        Add a route with the given prefix and nextHop
+        """
+        try:
+            cmdStr = "route-add %s %s %s" % ( "-j" if jsonFormat else "", prefix, nextHop )
+            handle = self.sendline( cmdStr )
+            assert handle is not None, "Error in sendline"
+            assert "Command not found:" not in handle, handle
+            assert "Unsupported command:" not in handle, handle
+            assert "Error executing command" not in handle, handle
+            return handle
+        except AssertionError:
+            main.log.exception( "" )
+            return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanAndExit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanAndExit()
+
+    def routeRemove( self, prefix, nextHop, source=None, jsonFormat=True ):
+        """
+        Remove a route with the given prefix and nextHop
+        """
+        try:
+            if source:
+                raise NotImplemented
+            cmdStr = "route-remove %s %s %s" % ( "-j" if jsonFormat else "", prefix, nextHop )
+            handle = self.sendline( cmdStr )
+            assert handle is not None, "Error in sendline"
+            assert "Command not found:" not in handle, handle
+            assert "Unsupported command:" not in handle, handle
+            assert "Error executing command" not in handle, handle
+            return handle
+        except AssertionError:
+            main.log.exception( "" )
+            return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanAndExit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanAndExit()
+
+    def routes( self, jsonFormat=True, args="" ):
+        """
+        Get routes from ONOS
+        """
+        try:
+            cmdStr = "routes"
+            if jsonFormat:
+                cmdStr = cmdStr + " -j"
+            handle = self.sendline( cmdStr )
+            assert handle is not None, "Error in sendline"
+            assert "Command not found:" not in handle, handle
+            assert "Unsupported command:" not in handle, handle
+            assert "Error executing command" not in handle, handle
+            return handle
+        except AssertionError:
+            main.log.exception( "" )
+            return None
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanAndExit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanAndExit()