Disconnect switch when Device was admin removed.

Change-Id: I8d55eda686d29b43540f5467739983564afde5af
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 c07328f..4427c72 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
@@ -28,6 +28,10 @@
 import org.apache.felix.scr.annotations.Service;
 import org.onosproject.cfg.ComponentConfigService;
 import org.onosproject.core.CoreService;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceEvent.Type;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.driver.DefaultDriverProviderService;
 import org.onosproject.net.driver.DriverService;
 import org.onosproject.openflow.controller.DefaultOpenFlowPacketContext;
@@ -72,6 +76,7 @@
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -82,6 +87,7 @@
 import java.util.concurrent.locks.ReentrantLock;
 
 import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.openflow.controller.Dpid.dpid;
 
 @Component(immediate = true)
 @Service
@@ -106,6 +112,10 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected ComponentConfigService cfgService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceService deviceService;
+
+
     @Property(name = "openflowPorts", value = DEFAULT_OFPORT,
             label = "Port numbers (comma separated) used by OpenFlow protocol; default is 6633,6653")
     private String openflowPorts = DEFAULT_OFPORT;
@@ -161,11 +171,13 @@
             ArrayListMultimap.create();
 
     private final Controller ctrl = new Controller();
+    private InternalDeviceListener listener = new InternalDeviceListener();
 
     @Activate
     public void activate(ComponentContext context) {
         coreService.registerApplication(APP_ID, this::cleanup);
         cfgService.registerProperties(getClass());
+        deviceService.addListener(listener);
         ctrl.setConfigParams(context.getProperties());
         ctrl.start(agent, driverService);
     }
@@ -182,6 +194,7 @@
 
     @Deactivate
     public void deactivate() {
+        deviceService.removeListener(listener);
         cleanup();
         cfgService.unregisterProperties(getClass(), false);
     }
@@ -521,6 +534,46 @@
         sw.setRole(role);
     }
 
+    class InternalDeviceListener implements DeviceListener {
+
+        @Override
+        public boolean isRelevant(DeviceEvent event) {
+            return event.type() == Type.DEVICE_REMOVED;
+        }
+
+        @Override
+        public void event(DeviceEvent event) {
+            switch (event.type()) {
+            case DEVICE_ADDED:
+                break;
+            case DEVICE_AVAILABILITY_CHANGED:
+                break;
+            case DEVICE_REMOVED:
+                // Device administratively removed, disconnect
+                Optional.ofNullable(getSwitch(dpid(event.subject().id().uri())))
+                        .ifPresent(OpenFlowSwitch::disconnectSwitch);
+                break;
+            case DEVICE_SUSPENDED:
+                break;
+            case DEVICE_UPDATED:
+                break;
+            case PORT_ADDED:
+                break;
+            case PORT_REMOVED:
+                break;
+            case PORT_STATS_UPDATED:
+                break;
+            case PORT_UPDATED:
+                break;
+            default:
+                break;
+
+            }
+
+        }
+
+    }
+
     /**
      * Implementation of an OpenFlow Agent which is responsible for
      * keeping track of connected switches and the state in which
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 d475ba1..8aa53ef 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
@@ -33,6 +33,7 @@
 import org.onlab.junit.TestTools;
 import org.onosproject.cfg.ComponentConfigService;
 import org.onosproject.core.CoreService;
+import org.onosproject.net.device.DeviceServiceAdapter;
 import org.onosproject.openflow.OpenflowSwitchDriverAdapter;
 import org.onosproject.openflow.controller.Dpid;
 import org.onosproject.openflow.controller.OpenFlowSwitch;
@@ -143,6 +144,8 @@
         controller.cfgService = mockConfigService;
         replay(mockConfigService);
 
+        controller.deviceService = new DeviceServiceAdapter();
+
         ComponentContext mockContext = EasyMock.createMock(ComponentContext.class);
         Dictionary<String, Object> properties = new Hashtable<>();
         properties.put("openflowPorts",