Merge "Minor fix to the x-axis of the FUNC, HA, and USECASE graph generator"
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()
diff --git a/TestON/tests/CHOTestMonkey/CHOTestMonkey.params b/TestON/tests/CHOTestMonkey/CHOTestMonkey.params
index 6bb3467..b1b9d0f 100644
--- a/TestON/tests/CHOTestMonkey/CHOTestMonkey.params
+++ b/TestON/tests/CHOTestMonkey/CHOTestMonkey.params
@@ -134,6 +134,14 @@
             <maxRerunNum>5</maxRerunNum>
         </ONOSCheck>
 
+        <RaftLogSizeCheck>
+            <status>on</status>
+            <typeIndex>15</typeIndex>
+            <typeString>CHECK_RAFT_LOG_SIZE</typeString>
+            <CLI>check-raft-size</CLI>
+            <CLIParamNum>0</CLIParamNum>
+        </RaftLogSizeCheck>
+
         <LinkDown>
             <status>on</status>
             <typeIndex>20</typeIndex>
diff --git a/TestON/tests/CHOTestMonkey/CHOTestMonkey.py b/TestON/tests/CHOTestMonkey/CHOTestMonkey.py
index 2a0dc55..3e21612 100644
--- a/TestON/tests/CHOTestMonkey/CHOTestMonkey.py
+++ b/TestON/tests/CHOTestMonkey/CHOTestMonkey.py
@@ -785,6 +785,7 @@
             main.eventGenerator.triggerEvent( EventType().CHECK_TRAFFIC, EventScheduleMethod().RUN_NON_BLOCK )
             main.eventGenerator.triggerEvent( EventType().CHECK_FLOW, EventScheduleMethod().RUN_NON_BLOCK )
             main.eventGenerator.triggerEvent( EventType().CHECK_INTENT, EventScheduleMethod().RUN_NON_BLOCK )
+            main.eventGenerator.triggerEvent( EventType().CHECK_RAFT_LOG_SIZE, EventScheduleMethod().RUN_NON_BLOCK )
             with main.eventScheduler.idleCondition:
                 while not main.eventScheduler.isIdle():
                     main.eventScheduler.idleCondition.wait()
diff --git a/TestON/tests/CHOTestMonkey/CHOTestMonkey.topo b/TestON/tests/CHOTestMonkey/CHOTestMonkey.topo
index 9930443..5fdf91d 100644
--- a/TestON/tests/CHOTestMonkey/CHOTestMonkey.topo
+++ b/TestON/tests/CHOTestMonkey/CHOTestMonkey.topo
@@ -33,4 +33,4 @@
         </Mininet1>
 
     </COMPONENT>
-</TOPOLOGY>
\ No newline at end of file
+</TOPOLOGY>
diff --git a/TestON/tests/CHOTestMonkey/dependencies/events/CheckEvent.py b/TestON/tests/CHOTestMonkey/dependencies/events/CheckEvent.py
index 786bfa8..fc03203 100644
--- a/TestON/tests/CHOTestMonkey/dependencies/events/CheckEvent.py
+++ b/TestON/tests/CHOTestMonkey/dependencies/events/CheckEvent.py
@@ -328,3 +328,19 @@
                 checkResult = EventStates().FAIL
                 main.log.warn( "Traffic Check - ping6 failed" )
         return checkResult
+
+class RaftLogSizeCheck( CheckEvent ):
+
+    def __init__( self ):
+        CheckEvent.__init__( self )
+        self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
+        self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
+
+    def startCheckEvent( self, args=None ):
+        checkResult = EventStates().PASS
+        main.log.info( "Starting checking Raft Log size" )
+        if not main.Cluster.checkPartitionSize():
+            checkResult = EventStates().FAIL
+            main.log.warn( "Raft Log Size Check - Raft log grew too big" )
+
+        return checkResult
diff --git a/TestON/tests/HA/dependencies/HA.py b/TestON/tests/HA/dependencies/HA.py
index f1ddaef..48b64c6 100644
--- a/TestON/tests/HA/dependencies/HA.py
+++ b/TestON/tests/HA/dependencies/HA.py
@@ -136,7 +136,8 @@
         main.log.warn( javaArgs )
         main.log.warn( repr( javaArgs ) )
         handle = main.ONOSbench.handle
-        sed = r"sed -i 's/bash/bash\nexport JAVA_OPTS=${{JAVA_OPTS:-{}}}\n/' {}".format( javaArgs, main.onosServicepath )
+        sed = r"sed -i 's/bash/bash\nexport JAVA_OPTS=${{JAVA_OPTS:-{}}}\n/' {}".format( javaArgs,
+                                                                                         main.onosServicepath )
         main.log.warn( sed )
         main.log.warn( repr( sed ) )
         handle.sendline( sed )
@@ -326,8 +327,6 @@
         """
         rest of initialSetup
         """
-
-
         if main.params[ 'tcpdump' ].lower() == "true":
             main.step( "Start Packet Capture MN" )
             main.Mininet2.startTcpdump(
@@ -450,7 +449,8 @@
             main.log.exception( "Error parsing leaders" )
             main.log.error( repr( leaders ) )
         if missing:
-            #NOTE Can we refactor this into the Cluster class? Maybe an option to print the output of a command from each node?
+            # NOTE Can we refactor this into the Cluster class?
+            #      Maybe an option to print the output of a command from each node?
             for ctrl in main.Cluster.active():
                 response = ctrl.CLI.leaders( jsonFormat=False )
                 main.log.debug( str( ctrl.name ) + " leaders output: \n" +
@@ -569,7 +569,7 @@
                 if re.search( "tcp:" + ctrl.ipAddress, response ):
                     mastershipCheck = mastershipCheck and main.TRUE
                 else:
-                    main.log.error( "Error, node " + repr( ctrl )+ " is " +
+                    main.log.error( "Error, node " + repr( ctrl ) + " is " +
                                     "not in the list of controllers s" +
                                     str( i ) + " is connecting to." )
                     mastershipCheck = main.FALSE
@@ -915,7 +915,7 @@
                                      indent=4,
                                      separators=( ',', ': ' ) )
             except ( ValueError, TypeError ):
-               output = repr( tmpIntents )
+                output = repr( tmpIntents )
             main.log.debug( "ONOS1 intents: " + output )
         utilities.assert_equals(
             expect=main.TRUE,
@@ -1099,14 +1099,12 @@
             mastershipCheck = main.TRUE
             mastershipState = ONOSMastership[ 0 ]
 
-
         global intentState
         intentState = []
         ONOSIntents, intentsResults = self.checkingIntents()
         intentCheck = main.FALSE
         consistentIntents = True
 
-
         main.step( "Check for consistency in Intents from each controller" )
         if all( [ sorted( i ) == sorted( ONOSIntents[ 0 ] ) for i in ONOSIntents ] ):
             main.log.info( "Intents are consistent across all ONOS " +
@@ -1178,7 +1176,7 @@
         main.step( "Get the flows from each controller" )
         global flowState
         flowState = []
-        ONOSFlows = main.Cluster.command( "flows", specificDriver=2 ) # TODO: Possible arg: sleep = 30
+        ONOSFlows = main.Cluster.command( "flows", specificDriver=2 )  # TODO: Possible arg: sleep = 30
         ONOSFlowsJson = []
         flowCheck = main.FALSE
         consistentFlows = True
@@ -2025,8 +2023,8 @@
             main.step( "Distributed Set clear()" )
             main.onosSet.clear()
             clearResponses = main.Cluster.command( "setTestRemove",
-                    args=[ main.onosSetName, " " ],  # Values doesn't matter
-                    kwargs={ "clear": True } )
+                                                   args=[ main.onosSetName, " " ],  # Values doesn't matter
+                                                   kwargs={ "clear": True } )
             # main.TRUE = successfully changed the set
             # main.FALSE = action resulted in no change in set
             # main.ERROR - Some error in executing the function
@@ -2536,7 +2534,17 @@
         colors = { 'cyan': '\033[96m', 'purple': '\033[95m',
                    'blue': '\033[94m', 'green': '\033[92m',
                    'yellow': '\033[93m', 'red': '\033[91m', 'end': '\033[0m' }
+
         main.case( "Test Cleanup" )
+
+        main.step( "Checking raft log size" )
+        # TODO: this is a flaky check, but the intent is to make sure the raft logs
+        #       get compacted periodically
+        logCheck = main.Cluster.checkPartitionSize()
+        utilities.assert_equals( expect=True, actual=logCheck,
+                                 onpass="Raft log size is not too big",
+                                 onfail="Raft logs grew too big" )
+
         main.step( "Killing tcpdumps" )
         main.Mininet2.stopTcpdump()
 
@@ -2780,11 +2788,11 @@
         utilities.assert_equals( expect=main.TRUE, actual=runResults,
                                  onpass="ONOS nodes reran for election topic",
                                  onfail="Errror rerunning for election" )
+
     def tempCell( self, cellName, ipList ):
         main.step( "Create cell file" )
         cellAppString = main.params[ 'ENV' ][ 'appString' ]
 
-
         main.ONOSbench.createCellFile( main.ONOSbench.ip_address, cellName,
                                        main.Mininet1.ip_address,
                                        cellAppString, ipList , main.ONOScli1.karafUser )
@@ -2792,7 +2800,6 @@
         cellResult = main.ONOSbench.setCell( cellName )
         verifyResult = main.ONOSbench.verifyCell()
 
-
     def checkStateAfterEvent( self, main, afterWhich, compareSwitch=False, isRestart=False ):
         """
         afterWhich :
@@ -3108,9 +3115,11 @@
             mnHosts = main.Mininet1.getHosts()
             for controller in range( len( main.Cluster.active() ) ):
                 controllerStr = str( main.Cluster.active( controller ) )
-                currentDevicesResult = main.topoRelated.compareDevicePort( main.Mininet1, controller,
-                                                          mnSwitches,
-                                                          devices, ports )
+                currentDevicesResult = main.topoRelated.compareDevicePort( main.Mininet1,
+                                                                           controller,
+                                                                           mnSwitches,
+                                                                           devices,
+                                                                           ports )
                 utilities.assert_equals( expect=main.TRUE,
                                          actual=currentDevicesResult,
                                          onpass=controllerStr +
@@ -3118,10 +3127,9 @@
                                          onfail=controllerStr +
                                          " Switches view is incorrect" )
 
-
                 currentLinksResult = main.topoRelated.compareBase( links, controller,
-                                                        main.Mininet1.compareLinks,
-                                                        [mnSwitches, mnLinks] )
+                                                                   main.Mininet1.compareLinks,
+                                                                   [ mnSwitches, mnLinks ] )
                 utilities.assert_equals( expect=main.TRUE,
                                          actual=currentLinksResult,
                                          onpass=controllerStr +
@@ -3428,7 +3436,7 @@
                       "working properly"
         main.case( description )
 
-        main.step( "Bring link between " + fromS + " and " + toS +" back up" )
+        main.step( "Bring link between " + fromS + " and " + toS + " back up" )
         LinkUp = main.Mininet1.link( END1=fromS, END2=toS, OPTION="up" )
         main.log.info( "Waiting " + str( linkSleep ) +
                        " seconds for link up to be discovered" )
diff --git a/TestON/tests/dependencies/Cluster.py b/TestON/tests/dependencies/Cluster.py
index 5c6e679..16dfd79 100644
--- a/TestON/tests/dependencies/Cluster.py
+++ b/TestON/tests/dependencies/Cluster.py
@@ -24,15 +24,14 @@
 
     def __str__( self ):
         return self.name
+
     def __repr__( self ):
-        #TODO use repr of cli's?
         controllers = []
         runningNodes = []
         for ctrl in self.controllers:
             controllers.append( str( ctrl ) )
         return "%s[%s]" % ( self.name, ", ".join( controllers ) )
 
-
     def __init__( self, ctrlList=[], name="Cluster" ):
         '''
             controllers : All the nodes
@@ -186,7 +185,7 @@
         """
         result = main.TRUE
         uninstallResult = self.command( "onosUninstall",
-                                        kwargs={ "nodeIp":"ipAddress" },
+                                        kwargs={ "nodeIp": "ipAddress" },
                                         specificDriver=1,
                                         getFrom=0 if uninstallMax else 1,
                                         funcFromCtrl=True )
@@ -206,12 +205,12 @@
         """
 
         setCellResult = self.command( "setCell",
-                      args=[ cellName ],
-                      specificDriver=1,
-                      getFrom=0 if installMax else 1 )
+                                      args=[ cellName ],
+                                      specificDriver=1,
+                                      getFrom=0 if installMax else 1 )
         verifyResult = self.command( "verifyCell",
-                      specificDriver=1,
-                      getFrom=0 if installMax else 1 )
+                                     specificDriver=1,
+                                     getFrom=0 if installMax else 1 )
         result = main.TRUE
         for i in range( len( setCellResult ) ):
             result = result and setCellResult[ i ] and verifyResult[ i ]
@@ -267,7 +266,7 @@
                                    specificDriver=1,
                                    getFrom=0 if killMax else 1,
                                    funcFromCtrl=True )
-        for i in range( len ( killResult ) ):
+        for i in range( len( killResult ) ):
             result = result and killResult[ i ]
             self.controllers[ i ].active = False
         return result
@@ -283,7 +282,7 @@
         """
         result = main.TRUE
         sshResult = self.command( "onosSecureSSH",
-                                   kwargs={ "node":"ipAddress" },
+                                   kwargs={ "node": "ipAddress" },
                                    specificDriver=1,
                                    getFrom=1,
                                    funcFromCtrl=True )
@@ -309,10 +308,10 @@
             if installMax and i >= self.numCtrls:
                 options = "-nf"
             if installParallel:
-                t= main.Thread( target=ctrl.Bench.onosInstall,
-                                name="install-" + ctrl.name,
-                                kwargs={ "node" : ctrl.ipAddress,
-                                         "options" : options } )
+                t = main.Thread( target=ctrl.Bench.onosInstall,
+                                 name="install-" + ctrl.name,
+                                 kwargs={ "node" : ctrl.ipAddress,
+                                          "options" : options } )
                 threads.append( t )
                 t.start()
             else:
@@ -338,7 +337,7 @@
                                    specificDriver=2,
                                    getFrom=1,
                                    funcFromCtrl=True )
-        for i in range ( len( cliResults ) ):
+        for i in range( len( cliResults ) ):
             result = result and cliResults[ i ]
             self.controllers[ i ].active = True
         return result
@@ -354,8 +353,8 @@
         Returns:
         """
         f = getattr( main.log, logLevel )
-        for i in range ( len ( results ) ):
-            f( activeList[ i ].name + "'s result : " + str ( results[ i ] ) )
+        for i in range( len( results ) ):
+            f( activeList[ i ].name + "'s result : " + str( results[ i ] ) )
 
     def allTrueResultCheck( self, results, activeList ):
         """
@@ -447,7 +446,7 @@
                             funcArgs.append( getattr( ctrl, args[ i ] ) )
                     if kwargs:
                         for k in kwargs:
-                            funcKwargs.update( { k:getattr( ctrl, kwargs[ k ] ) } )
+                            funcKwargs.update( { k: getattr( ctrl, kwargs[ k ] ) } )
             except AttributeError:
                 main.log.error( "Function " + function + " not found. Exiting the Test." )
                 main.cleanAndExit()
@@ -465,4 +464,16 @@
             return self.allTrueResultCheck( results, fromNode[ getFrom ] )
         elif contentCheck:
             return self.notEmptyResultCheck( results, fromNode[ getFrom ] )
-        return results
\ No newline at end of file
+        return results
+
+    def checkPartitionSize( self, segmentSize='64', units='M', multiplier='3' ):
+        # max segment size in bytes: 1024 * 1024 * 64
+        # multiplier is somewhat arbitrary, but the idea is the logs would have
+        # been compacted before this many segments are written
+
+        maxSize = float( segmentSize ) * float( multiplier )
+        ret = True
+        for n in self.runningNodes:
+            ret = ret and n.server.folderSize( "/opt/onos/apache-karaf-*/data/partitions/*/*.log",
+                                               size=maxSize, unit=units, ignoreRoot=False )
+        return ret