ONOS-3411 Disconnect switches and stop stat collectors when openflow-base is being deactivated

Change-Id: I9a1b5fbb60a9e7135cd586fe717c18f83e3d864d
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
index c717419..08444b1 100644
--- a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
@@ -98,6 +98,7 @@
 
     @Override
     public final void disconnectSwitch() {
+        setConnected(false);
         this.channel.close();
     }
 
diff --git a/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java b/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java
index b97c336..b410158 100644
--- a/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java
+++ b/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImpl.java
@@ -27,6 +27,7 @@
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
 import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.core.CoreService;
 import org.onosproject.net.driver.DefaultDriverProviderService;
 import org.onosproject.net.driver.DriverService;
 import org.onosproject.openflow.controller.DefaultOpenFlowPacketContext;
@@ -83,6 +84,7 @@
 @Component(immediate = true)
 @Service
 public class OpenFlowControllerImpl implements OpenFlowController {
+    private static final String APP_ID = "org.onosproject.openflow-base";
     private static final String DEFAULT_OFPORT = "6633,6653";
     private static final int DEFAULT_WORKER_THREADS = 16;
 
@@ -90,6 +92,9 @@
             LoggerFactory.getLogger(OpenFlowControllerImpl.class);
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DriverService driverService;
 
     // References exists merely for sequencing purpose to assure drivers are loaded
@@ -147,15 +152,24 @@
 
     @Activate
     public void activate(ComponentContext context) {
+        coreService.registerApplication(APP_ID, this::preDeactivate);
         cfgService.registerProperties(getClass());
         ctrl.setConfigParams(context.getProperties());
         ctrl.start(agent, driverService);
     }
 
+    private void preDeactivate() {
+        // Close listening channel and all OF channels before deactivating
+        ctrl.stop();
+        connectedSwitches.values().forEach(OpenFlowSwitch::disconnectSwitch);
+    }
+
     @Deactivate
     public void deactivate() {
         cfgService.unregisterProperties(getClass(), false);
-        ctrl.stop();
+        connectedSwitches.clear();
+        activeMasterSwitches.clear();
+        activeEqualSwitches.clear();
     }
 
     @Modified
diff --git a/protocols/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImplTest.java b/protocols/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImplTest.java
index e079c59..56d422a 100644
--- a/protocols/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImplTest.java
+++ b/protocols/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/OpenFlowControllerImplTest.java
@@ -32,6 +32,7 @@
 import org.junit.Test;
 import org.onlab.junit.TestTools;
 import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.core.CoreService;
 import org.onosproject.openflow.OpenflowSwitchDriverAdapter;
 import org.onosproject.openflow.controller.Dpid;
 import org.onosproject.openflow.controller.OpenFlowSwitch;
@@ -127,6 +128,10 @@
         switchListener = new TestSwitchListener();
         controller.addListener(switchListener);
 
+        CoreService mockCoreService =
+                EasyMock.createMock(CoreService.class);
+        controller.coreService = mockCoreService;
+
         ComponentConfigService mockConfigService =
                 EasyMock.createMock(ComponentConfigService.class);
         expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of());
diff --git a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
index e69fd6b..6c646d0 100644
--- a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
+++ b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
@@ -128,7 +128,8 @@
     public void deactivate() {
         providerRegistry.unregister(this);
         providerService = null;
-
+        collectors.values().forEach(GroupStatsCollector::stop);
+        collectors.clear();
         log.info("Stopped");
     }
 
diff --git a/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java b/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java
index f5a777b..e411379 100644
--- a/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java
+++ b/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java
@@ -132,6 +132,8 @@
     @Deactivate
     public void deactivate() {
         providerRegistry.unregister(this);
+        collectors.values().forEach(MeterStatsCollector::stop);
+        collectors.clear();
         controller.removeEventListener(listener);
         controller.removeListener(listener);
         providerService = null;