Add functions to check the size of raft logs

- Function to check the size of a file/folder using du
- Check the size of the raft logs in HA cleanup function
- Check is based on max segment size of the raft instance(s)

Change-Id: I5259bb8520bbe962c8c2970b77164e6ff2e1000b
diff --git a/TestON/drivers/common/cli/onosclusterdriver.py b/TestON/drivers/common/cli/onosclusterdriver.py
index 63bee60..5093cfe 100755
--- a/TestON/drivers/common/cli/onosclusterdriver.py
+++ b/TestON/drivers/common/cli/onosclusterdriver.py
@@ -39,10 +39,10 @@
     def __repr__( self ):
         #TODO use repr() for components?
         return "%s<IP=%s, CLI=%s, REST=%s, Bench=%s >" % ( self.name,
-                                                          self.ipAddress,
-                                                          self.CLI,
-                                                          self.REST,
-                                                          self.Bench )
+                                                           self.ipAddress,
+                                                           self.CLI,
+                                                           self.REST,
+                                                           self.Bench )
 
     def __getattr__( self, name ):
         """
@@ -79,7 +79,7 @@
 
 
 
-    def __init__( self, name, ipAddress, CLI=None, REST=None, Bench=None, pos=None, userName=None ):
+    def __init__( self, name, ipAddress, CLI=None, REST=None, Bench=None, pos=None, userName=None, server=None ):
         #TODO: validate these arguments
         self.name = str( name )
         self.ipAddress = ipAddress
@@ -90,6 +90,7 @@
         self.pos = pos
         self.ip_address = ipAddress
         self.user_name = userName
+        self.server = server
 
 class OnosClusterDriver( CLI ):
 
@@ -365,7 +366,56 @@
             main.log.error( name + " component already exists!" )
             main.cleanAndExit()
 
-    def createComponents( self, prefix='' ):
+
+    def setServerOptions( self, name, ipAddress ):
+        """
+        Parse the cluster options to create an ONOS "server" component with the given name
+
+        Arguments:
+            name - The name of the server componet
+            ipAddress - The ip address of the server
+        """
+        main.componentDictionary[name] = main.componentDictionary[self.name].copy()
+        main.componentDictionary[name]['type'] = "OnosDriver"
+        main.componentDictionary[name]['host'] = ipAddress
+        home = main.componentDictionary[name]['COMPONENTS'].get( "onos_home", None )
+        main.componentDictionary[name]['home'] = self.checkOptions( home, None )
+        main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
+        main.log.debug( main.componentDictionary[name] )
+
+
+    def createServerComponent( self, name, ipAddress ):
+        """
+        Creates a new onos "server" component. This will be connected to the
+        node ONOS is running on.
+
+        Arguments:
+            name - The string of the name of this component. The new component
+                   will be assigned to main.<name> .
+                   In addition, main.<name>.name = str( name )
+            ipAddress - The ip address of the server
+        """
+        try:
+            # look to see if this component already exists
+            getattr( main, name )
+        except AttributeError:
+            # namespace is clear, creating component
+            self.setServerOptions( name, ipAddress )
+            return main.componentInit( name )
+        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()
+        else:
+            # namespace is not clear!
+            main.log.error( name + " component already exists!" )
+            main.cleanAndExit()
+
+
+    def createComponents( self, prefix='', createServer=True ):
         """
         Creates a CLI and REST component for each nodes in the cluster
         """
@@ -373,11 +423,12 @@
         cliPrefix = prefix + "cli"
         restPrefix = prefix + "rest"
         benchPrefix = prefix + "bench"
-        #self.nodes = []
+        serverPrefix = prefix + "server"
         for i in xrange( 1, self.maxNodes + 1 ):
             cliName = cliPrefix + str( i  )
             restName = restPrefix + str( i )
             benchName = benchPrefix + str( i )
+            serverName = serverPrefix + str( i )
 
             # Unfortunately this means we need to have a cell set beofre running TestON,
             # Even if it is just the entire possible cluster size
@@ -386,4 +437,5 @@
             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, i - 1, self.user_name ) )
\ No newline at end of file
+            server = self.createServerComponent( serverName, ip ) if createServer else None
+            self.nodes.append( Controller( prefix + str( i ), ip, cli, rest, bench, i - 1, self.user_name, server=server ) )
diff --git a/TestON/drivers/common/clidriver.py b/TestON/drivers/common/clidriver.py
index 55f05ba..b7ad8c8 100644
--- a/TestON/drivers/common/clidriver.py
+++ b/TestON/drivers/common/clidriver.py
@@ -80,15 +80,14 @@
         self.handle.logfile = self.logfile_handler
         i = 5
         while i == 5:
-            i = self.handle.expect( [
-                                    ssh_newkey,
-                                    'password:|Password:',
-                                    pexpect.EOF,
-                                    pexpect.TIMEOUT,
-                                    refused,
-                                    'teston>',
-                                    self.prompt ],
-                            120 )
+            i = self.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" )
                 self.handle.sendline( 'yes' )
@@ -97,7 +96,7 @@
             if i == 1:  # Password required
                 if self.pwd:
                     main.log.info(
-                    "ssh connection asked for password, gave password" )
+                            "ssh connection asked for password, gave password" )
                 else:
                     main.log.info( "Server asked for password, but none was "
                                     "given in the .topo file. Trying "
@@ -327,7 +326,7 @@
                 main.log.error( "Permission denied. Check folder permissions" )
                 returnVal = main.FALSE
             elif i == 6:  # prompt returned
-               return returnVal
+                return returnVal
             elif i == 7:  # EOF
                 main.log.error( "Pexpect.EOF found!!!" )
                 main.cleanAndExit()
@@ -378,15 +377,14 @@
 
         i = 5
         while i == 5:
-            i = handle.expect( [
-                                    ssh_newkey,
-                                    'password:|Password:',
-                                    pexpect.EOF,
-                                    pexpect.TIMEOUT,
-                                    refused,
-                                    'teston>',
-                                    self.prompt ],
-                            120 )
+            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' )
@@ -395,7 +393,7 @@
             if i == 1:  # Password required
                 if pwd:
                     main.log.info(
-                    "ssh connection asked for password, gave password" )
+                            "ssh connection asked for password, gave password" )
                 else:
                     main.log.info( "Server asked for password, but none was "
                                     "given in the .topo file. Trying "
@@ -434,14 +432,14 @@
         handle.sendline( "cd" )
         handle.expect( self.prompt )
 
-        main.log.info ( "Successfully ssh to " + ipAddress + "." )
+        main.log.info( "Successfully ssh to " + ipAddress + "." )
         return handle
 
     def exitFromSsh( self, handle, ipAddress ):
         try:
             handle.sendline( "logout" )
             handle.expect( "closed." )
-            main.log.info ( "Successfully closed ssh connection from " + ipAddress )
+            main.log.info( "Successfully closed ssh connection from " + ipAddress )
         except pexpect.EOF:
             main.log.error( "Failed to close the connection from " + ipAddress )
         try:
@@ -451,3 +449,67 @@
         except pexpect.EOF:
             main.log.error( self.handle.before )
             main.log.error( "EOF after closing ssh connection" )
+
+    def folderSize( self, path, size='10', unit='M', ignoreRoot=True ):
+        """
+        Run `du -h` on the folder path and verifies the folder(s) size is
+        less than the given size. Note that if multiple subdirectories are
+        present, the result will be the OR of all the individual subdirectories.
+
+        Arguments:
+        path - A string containing the path supplied to the du command
+        size - The number portion of the file size that the results will be compared to
+        unit - The unit portion of the file size that the results will be compared to
+        ignoreRoot - If True, will ignore the "root" of the path supplied to du. I.E. will ignore `.`
+
+        Returns True if the folder(s) size(s) are less than SIZE UNITS, else returns False
+        """
+        sizeRe = r'(?P<number>\d+\.*\d*)(?P<unit>\D)'
+        unitsList = [ 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' ]
+        try:
+            # make sure we convert units if size is too big
+            size = float( size )
+            if size >= 1000:
+                size = size / 1000
+                unit = unitsList[ unitsList.index( unit + 1 ) ]
+            cmdStr = "du -h " + path
+            self.handle.sendline( cmdStr )
+            self.handle.expect( self.prompt )
+            output = self.handle.before
+            assert "cannot access" not in output
+            assert "command not found" not in output
+            main.log.debug( output )
+            lines = [ line for line in output.splitlines() ]
+            retValue = True
+            if ignoreRoot:
+                lastIndex = -2
+            else:
+                lastIndex = -1
+            for line in lines[1:lastIndex]:
+                parsed = line.split()
+                sizeMatch = parsed[0]
+                folder = parsed[1]
+                match = re.search( sizeRe, sizeMatch )
+                num = match.group( 'number' )
+                unitMatch = match.group( 'unit' )
+                if unitsList.index( unitMatch ) < unitsList.index( unit ):
+                    retValue &= True
+                elif unitsList.index( unitMatch ) == unitsList.index( unit ):
+                    if float( num ) < float( size ):
+                        retValue &= True
+                    else:
+                        retValue &= False
+                elif unitsList.index( unitMatch ) > unitsList.index( unit ):
+                    retValue &= False
+            return retValue
+        except AssertionError:
+            main.log.error( self.name + ": Could not execute command: " + output )
+            return False
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": TIMEOUT exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            return False
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanAndExit()