WIP: HA updates, includes network partition
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 3103772..4f40b07 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -298,18 +298,28 @@
             logStr = "\"Sending CLI command: '" + cmdStr + "'\""
             self.log( logStr )
             self.handle.sendline( cmdStr )
-            self.handle.expect( "onos>" )
+            i = self.handle.expect( ["onos>", "\$", pexpect.TIMEOUT] )
+            response = self.handle.before
+            if i == 2:
+                self.handle.sendline()
+                self.handle.expect( "\$" )
+                response += self.handle.before
+                print response
+                try:
+                    print self.handle.after
+                except:
+                    pass
+            # TODO: do something with i
             main.log.info( "Command '" + str( cmdStr ) + "' sent to "
                            + self.name + "." )
-            handle = self.handle.before
             # Remove control strings from output
             ansiEscape = re.compile( r'\x1b[^m]*m' )
-            handle = ansiEscape.sub( '', handle )
+            response = ansiEscape.sub( '', response )
             # Remove extra return chars that get added
-            handle = re.sub(  r"\s\r", "", handle )
-            handle = handle.strip()
-            # parse for just the output, remove the cmd from handle
-            output = handle.split( cmdStr, 1 )[1]
+            response = re.sub(  r"\s\r", "", response )
+            response = response.strip()
+            # parse for just the output, remove the cmd from response
+            output = response.split( cmdStr, 1 )[1]
             return output
         except TypeError:
             main.log.exception( self.name + ": Object not as expected" )
@@ -2050,14 +2060,18 @@
             main.cleanup()
             main.exit()
 
-    def testExceptions( self, obj ):
+    def intentSummary( self ):
         """
-        Test exception logging
+        Returns a dictonary containing the current intent states and the count
         """
-        # FIXME: Remove this before you commit
-
         try:
-            return obj[ 'dedf' ]
+            intents = self.intents( )
+            intentStates = []
+            for intent in json.loads( intents ):  # Iter through intents of a node
+                intentStates.append( intent.get( 'state', None ) )
+            out = [ (i, intentStates.count( i ) ) for i in set( intentStates ) ]
+            main.log.info( dict( out ) )
+            return dict( out )
         except TypeError:
             main.log.exception( self.name + ": Object not as expected" )
             return None
@@ -2070,3 +2084,70 @@
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanup()
             main.exit()
+
+    def leaders( self ):
+        """
+        Returns the output of the leaders command.
+        """
+        # FIXME: add json output
+        try:
+            output = self.sendline( "onos:leaders" )
+            main.log.warn( output )
+            return output
+        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.cleanup()
+            main.exit()
+        except:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def pendingMap( self ):
+        """
+        Returns the output of the intent Pending map.
+        """
+        # FIXME: add json output
+        try:
+            output = self.sendline( "onos:intents -p" )
+            main.log.warn( output )
+            return output
+        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.cleanup()
+            main.exit()
+        except:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def partitions( self ):
+        """
+        Returns the output of the raft partitions command for ONOS.
+        """
+        # FIXME: add json output
+        try:
+            output = self.sendline( "partitions" )
+            main.log.warn( output )
+            return output
+        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.cleanup()
+            main.exit()
+        except:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index f45ad08..55a5c0e 100644
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -68,10 +68,8 @@
             main.log.error( self.name + ":     " + self.handle.before )
             main.cleanup()
             main.exit()
-        except:
-            main.log.info( self.name + ":" * 30 )
-            main.log.error( traceback.print_exc() )
-            main.log.info( ":" * 30 )
+        except Exception as e:
+            main.log.exception( "Uncaught exception!" )
             main.cleanup()
             main.exit()
 
@@ -1494,8 +1492,8 @@
             main.cleanup()
             main.exit()
 
-    def setIpTables( self, ip, port='', action='add', packet_type='tcp',
-                     direction='INPUT', rule='DROP' ):
+    def setIpTables( self, ip, port='', action='add', packet_type='',
+                     direction='INPUT', rule='DROP', states=True ):
         '''
         Description:
             add or remove iptables rule to DROP (default) packets from
@@ -1509,6 +1507,8 @@
         * optional packet type to block (default tcp)
         * optional iptables rule (default DROP)
         * optional direction to block (default 'INPUT')
+        * States boolean toggles adding all supported tcp states to the
+          firewall rule
         Returns:
             main.TRUE on success or
             main.FALSE if given invalid input or
@@ -1529,7 +1529,7 @@
         #       registered to the instance. If you are calling this function
         #       multiple times this sleep will prevent any errors.
         #       DO NOT REMOVE
-        time.sleep( 5 )
+        # time.sleep( 5 )
         try:
             # input validation
             action_type = action.lower()
@@ -1559,10 +1559,16 @@
             self.handle.expect( "\$" )
             cmd = "sudo iptables " + actionFlag + " " +\
                   direction +\
-                  " -p " + str( packet_type ) +\
                   " -s " + str( ip )
+                  # " -p " + str( packet_type ) +\
+            if packet_type:
+                cmd += " -p " + str( packet_type )
             if port:
                 cmd += " --dport " + str( port )
+            if states:
+                cmd += " -m state --state="
+                #FIXME- Allow user to configure which states to block
+                cmd += "INVALID,ESTABLISHED,NEW,RELATED,UNTRACKED"
             cmd += " -j " + str( rule )
 
             self.handle.sendline( cmd )
diff --git a/TestON/drivers/common/clidriver.py b/TestON/drivers/common/clidriver.py
index 6d7fb2a..44552ae 100644
--- a/TestON/drivers/common/clidriver.py
+++ b/TestON/drivers/common/clidriver.py
@@ -94,10 +94,17 @@
                 i = self.handle.expect(
                     [ ssh_newkey, 'password:', pexpect.EOF ] )
             if i == 1:
-                main.log.info(
-                    "ssh connection asked for password, gave password" )
-                self.handle.sendline( self.pwd )
-                self.handle.expect( '>|#|\$' )
+                if self.pwd:
+                    main.log.info(
+                        "ssh connection asked for password, gave password" )
+                    self.handle.sendline( self.pwd )
+                    self.handle.expect( '>|#|\$' )
+                else:
+                    # FIXME: TestON does not support a username having no
+                    #        password
+                    main.log.error( "Server asked for password, but none was "
+                                    "given in the .topo file" )
+                    main.exit()
             elif i == 2:
                 main.log.error( "Connection timeout" )
                 return main.FALSE