CHO test fixes: Check host IPs and make sure dhcp servers are always connected in HAGG topo

Change-Id: I26d8ecadce38c37f50c4bfef05ff555018b088b4
(cherry picked from commit 469d4ac4b19655db1215ce03946e24f3e563c3f6)
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index 27e1bf6..64e267a 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -1931,7 +1931,7 @@
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanAndExit()
 
-    def getSwitchRandom( self, timeout=60, nonCut=True, switchClasses=None, excludeNodes=[] ):
+    def getSwitchRandom( self, timeout=60, nonCut=True, switchClasses=None, excludeNodes=[], excludeSwitches=[] ):
         """
         Randomly get a switch from Mininet topology.
         If nonCut is True, it gets a list of non-cut switches (the deletion
@@ -1940,6 +1940,7 @@
         it just randomly returns one switch from all current switches in
         Mininet.
         excludeNodes will be pased to getGraphDict method
+        Switches specified in excludeSwitches will be excluded
         Returns the name of the chosen switch.
         """
         import random
@@ -1958,6 +1959,7 @@
                     return None
                 self.graph.update( graphDict )
                 candidateSwitches = self.graph.getNonCutVertices()
+                candidateSwitches = [ switch for switch in candidateSwitches if switch not in excludeSwitches ]
             if candidateSwitches is None:
                 return None
             elif len( candidateSwitches ) == 0:
diff --git a/TestON/tests/CHOTestMonkey/CHOTestMonkey.params b/TestON/tests/CHOTestMonkey/CHOTestMonkey.params
index 80a0b0b..1452741 100644
--- a/TestON/tests/CHOTestMonkey/CHOTestMonkey.params
+++ b/TestON/tests/CHOTestMonkey/CHOTestMonkey.params
@@ -407,6 +407,7 @@
         </topo4>
         <mininetArgs></mininetArgs>
         <loadTopoSleep>5</loadTopoSleep>
+        <excludeSwitches></excludeSwitches>
     </TOPO>
 
     <CASE1>
diff --git a/TestON/tests/CHOTestMonkey/CHOTestMonkey.params.trellis b/TestON/tests/CHOTestMonkey/CHOTestMonkey.params.trellis
index fc839ec..f6aa628 100644
--- a/TestON/tests/CHOTestMonkey/CHOTestMonkey.params.trellis
+++ b/TestON/tests/CHOTestMonkey/CHOTestMonkey.params.trellis
@@ -6,11 +6,13 @@
     # 5. Load topology and balances all switches
     # 6. Collect and store device and link data from ONOS
     # 7. Collect and store host data from ONOS
+    # 10. Run all enabled checks
     # 70. Run randomly generated events
+    # 80. Replay events from log file
     # 100. Do nothing
 
     <testcases>
-        0,2,4,5,6,7,70
+        0,2,4,5,6,7,10,70,100
     </testcases>
 
     <GIT>
@@ -114,7 +116,7 @@
             <CLI>check-traffic</CLI>
             <CLIParamNum>0</CLIParamNum>
             <rerunInterval>10</rerunInterval>
-            <maxRerunNum>10</maxRerunNum>
+            <maxRerunNum>5</maxRerunNum>
             <pingWait>1</pingWait>
             <pingTimeout>10</pingTimeout>
         </TrafficCheck>
@@ -305,7 +307,8 @@
             <fileName>hagg.py</fileName>
         </topo10>
         <mininetArgs>--dhcp=1 --routers=1 --ipv6=1 --ipv4=1</mininetArgs>
-        <loadTopoSleep>90</loadTopoSleep>
+        <loadTopoSleep>120</loadTopoSleep>
+        <excludeSwitches>leaf5</excludeSwitches>
     </TOPO>
 
     <CASE2>
@@ -319,7 +322,7 @@
     </CASE4>
 
     <CASE70>
-        <sleepSec>30</sleepSec>
+        <sleepSec>60</sleepSec>
         <addHostIntentWeight>0</addHostIntentWeight>
         <addPointIntentWeight>0</addPointIntentWeight>
         <linkDownWeight>0</linkDownWeight>
diff --git a/TestON/tests/CHOTestMonkey/dependencies/events/CheckEvent.py b/TestON/tests/CHOTestMonkey/dependencies/events/CheckEvent.py
index ccb5831..22380cf 100644
--- a/TestON/tests/CHOTestMonkey/dependencies/events/CheckEvent.py
+++ b/TestON/tests/CHOTestMonkey/dependencies/events/CheckEvent.py
@@ -134,7 +134,7 @@
         checkResult = EventStates().PASS
         upLinkNum = 0
         upDeviceNum = 0
-        upHostNum = 0
+        upHostList = []
         with main.variableLock:
             for link in main.links:
                 if not link.isDown() and not link.isRemoved():
@@ -144,11 +144,22 @@
                     upDeviceNum += 1
             for host in main.hosts:
                 if not host.isDown() and not host.isRemoved():
-                    upHostNum += 1
+                    upHostList.append( host )
         clusterNum = 1
+        # Verify host IPs
+        if hasattr( main, "expectedHosts" ):
+            for host in upHostList:
+                ipResult = main.Mininet1.verifyHostIp( hostList=[ host.name ],
+                                                       prefix=main.expectedHosts[ 'network' ][ host.name ],
+                                                       update=False )
+                if not ipResult:
+                    checkResult = EventStates().FAIL
+                    main.log.warn( "Topo Check - Failed to verify IP address on host %s" % ( host.name ) )
+        '''
         with main.mininetLock:
             graphDictMininet = main.Mininet1.getGraphDict( useId=True, switchClasses=r"(OVSSwitch)",
                                                            excludeNodes=[ 'bgp', 'cs', 'nat', 'dhcp', 'r' ] )
+        '''
         for controller in main.controllers:
             if controller.isUp():
                 with controller.CLILock:
@@ -186,9 +197,17 @@
                         hosts = json.loads( hosts )
                         if hasattr( main, "expectedHosts" ):
                             hosts = [ host for host in hosts if host[ 'id' ] in main.expectedHosts[ 'onos' ].keys() ]
-                        if not len( hosts ) == upHostNum:
+                        if not len( hosts ) == len( upHostList ):
                             # checkResult = EventStates().FAIL
-                            main.log.warn( "Topo Check - host number discoverd by ONOS%s is incorrect: %s expected and %s actual" % ( controller.index, upHostNum, len( hosts ) ) )
+                            main.log.warn( "Topo Check - host number discoverd by ONOS%s is incorrect: %s expected and %s actual" % ( controller.index, len( upHostList ), len( hosts ) ) )
+                        # Check Host IPs
+                        if hasattr( main, "expectedHosts" ):
+                            for host in upHostList:
+                                ipResult = controller.CLI.verifyHostIp( hostList=[ host.id ],
+                                                                        prefix=main.expectedHosts[ 'onos' ][ host.id ] )
+                                if not ipResult:
+                                    checkResult = EventStates().FAIL
+                                    main.log.warn( "Topo Check - ONOS%s failed to verify IP address on host %s" % ( controller.index, host.id ) )
                         # Check clusters
                         clusters = controller.CLI.clusters()
                         clusters = json.loads( clusters )
diff --git a/TestON/tests/CHOTestMonkey/dependencies/events/NetworkEvent.py b/TestON/tests/CHOTestMonkey/dependencies/events/NetworkEvent.py
index 935226c..7a2e84f 100644
--- a/TestON/tests/CHOTestMonkey/dependencies/events/NetworkEvent.py
+++ b/TestON/tests/CHOTestMonkey/dependencies/events/NetworkEvent.py
@@ -188,9 +188,14 @@
             if args[ 0 ] == 'random':
                 import random
                 if self.typeIndex == EventType().NETWORK_DEVICE_DOWN:
+                    if main.params[ 'TOPO' ][ 'excludeSwitches' ]:
+                        excludeSwitches = main.params[ 'TOPO' ][ 'excludeSwitches' ].split( ',' )
+                    else:
+                        excludeSwitches = []
                     with main.mininetLock:
                         switchRandom = main.Mininet1.getSwitchRandom( switchClasses=r"(OVSSwitch)",
-                                                                      excludeNodes=[ 'bgp', 'cs', 'nat', 'dhcp', 'r' ] )
+                                                                      excludeNodes=[ 'bgp', 'cs', 'nat', 'dhcp', 'r' ],
+                                                                      excludeSwitches=excludeSwitches )
                     if switchRandom is None:
                         main.log.warn( "No switch available, aborting event" )
                         return EventStates().ABORT