Implement an option in CPRM to reprogram the flows when device reconnecting

Also remove unused AsyncDeviceFetcher in FibInstaller

Change-Id: I52e778a51854efd6bfe47c56569efa5c27d7c7fb
diff --git a/apps/routing/cpr/src/main/java/org/onosproject/routing/cpr/ControlPlaneRedirectManager.java b/apps/routing/cpr/src/main/java/org/onosproject/routing/cpr/ControlPlaneRedirectManager.java
index 0c97bb1..f0f2927 100644
--- a/apps/routing/cpr/src/main/java/org/onosproject/routing/cpr/ControlPlaneRedirectManager.java
+++ b/apps/routing/cpr/src/main/java/org/onosproject/routing/cpr/ControlPlaneRedirectManager.java
@@ -22,6 +22,8 @@
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Modified;
+import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.onlab.packet.EthType;
@@ -30,7 +32,9 @@
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
+import org.onlab.util.Tools;
 import org.onosproject.app.ApplicationService;
+import org.onosproject.cfg.ComponentConfigService;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.incubator.net.intf.Interface;
@@ -63,8 +67,10 @@
 import org.onosproject.routing.config.RouterConfigHelper;
 import org.onosproject.routing.config.RoutersConfig;
 import org.onosproject.routing.config.RoutingConfigurationService;
+import org.osgi.service.component.ComponentContext;
 import org.slf4j.Logger;
 
+import java.util.Dictionary;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -127,6 +133,13 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected RoutingConfigurationService rs;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected ComponentConfigService cfgService;
+
+    @Property(name = "forceUnprovision", boolValue = false,
+            label = "Force unprovision when the device goes offline")
+    private boolean forceUnprovision = false;
+
     private static final String APP_NAME = "org.onosproject.cpr";
     private ApplicationId appId;
 
@@ -139,9 +152,12 @@
     private final InternalHostListener hostListener = new InternalHostListener();
 
     @Activate
-    protected void activate() {
+    protected void activate(ComponentContext context) {
         this.appId = coreService.registerApplication(APP_NAME);
 
+        cfgService.registerProperties(getClass());
+        modified(context);
+
         networkConfigService.addListener(networkConfigListener);
         hostService.addListener(hostListener);
 
@@ -153,10 +169,34 @@
 
     @Deactivate
     protected void deactivate() {
+        cfgService.unregisterProperties(getClass(), false);
         networkConfigService.removeListener(networkConfigListener);
         hostService.removeListener(hostListener);
     }
 
+    @Modified
+    protected void modified(ComponentContext context) {
+        if (context != null) {
+            readComponentConfiguration(context);
+            processRouterConfig();
+        }
+    }
+
+    private void readComponentConfiguration(ComponentContext context) {
+        Dictionary<?, ?> properties = context.getProperties();
+        Boolean flag;
+
+        flag = Tools.isPropertyEnabled(properties, "forceUnprovision");
+        if (flag == null) {
+            log.info("ForceUnprovision is not configured, " +
+                    "using current value of {}", forceUnprovision);
+        } else {
+            forceUnprovision = flag;
+            log.info("Configured. ForceUnprovision is {}",
+                    forceUnprovision ? "enabled" : "disabled");
+        }
+    }
+
     /**
      * Sets up the router interfaces if router config is available.
      */
@@ -174,7 +214,7 @@
                 if (r == null) {
                     return createRouter(RouterInfo.from(router));
                 } else {
-                    r.changeConfiguration(RouterInfo.from(router));
+                    r.changeConfiguration(RouterInfo.from(router), forceUnprovision);
                     return r;
                 }
             });
@@ -198,7 +238,8 @@
                 interfaceService,
                 deviceService,
                 this::provisionInterface,
-                this::unprovisionInterface);
+                this::unprovisionInterface,
+                forceUnprovision);
     }
 
     private void provisionInterface(InterfaceProvisionRequest intf) {
diff --git a/apps/routing/cpr/src/test/java/org/onosproject/routing/cpr/ControlPlaneRedirectManagerTest.java b/apps/routing/cpr/src/test/java/org/onosproject/routing/cpr/ControlPlaneRedirectManagerTest.java
index d399fc3..ffcce3b 100644
--- a/apps/routing/cpr/src/test/java/org/onosproject/routing/cpr/ControlPlaneRedirectManagerTest.java
+++ b/apps/routing/cpr/src/test/java/org/onosproject/routing/cpr/ControlPlaneRedirectManagerTest.java
@@ -21,6 +21,7 @@
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
+import org.onlab.osgi.ComponentContextAdapter;
 import org.onlab.packet.EthType;
 import org.onlab.packet.Ip6Address;
 import org.onlab.packet.IpAddress;
@@ -152,7 +153,7 @@
         controlPlaneRedirectManager.hostService = createNiceMock(HostService.class);
         controlPlaneRedirectManager.mastershipService = mastershipService;
         controlPlaneRedirectManager.applicationService = applicationService;
-        controlPlaneRedirectManager.activate();
+        controlPlaneRedirectManager.activate(new ComponentContextAdapter());
         verify(flowObjectiveService);
     }