Few core changes in preparation of P4Runtime subsystem refactoring

Refactoring aims at providing a more robust connection procedure of
P4Runtime-based devices.

Refactoring requires devices to be registered to the core with
available=false (i.e. offline), and marked online only when the P4
pipeline has been deployed to the device. Also, it leaves the duty of
handling pipeconf-specific drivers to the driver subsystem, instead of
having the GeneralDeviceProvider take care of it, which resulted to be
brittle.

Changes include:
- Choose not to mark device online when re-asserting mastership role by
declaring special device annotation.
- Lookup drivers in device projectable model unsing driver service
device-based method, which is consistent with the way other subsystems
look for device drivers.
- In DriverManager, when looking for device drivers, consider the case
of pipeconf-programmable devices, in which case a special "merged"
driver needs to instantiated at runtime.
- In PacketManager, push flow objectives only if device is available
(i.e. after pipeline has been deployed).

Change-Id: I80f78a4f40730a06cb82fa55fefab08a91a89268
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java
index 5be4a26..0e2ea82 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java
@@ -27,7 +27,6 @@
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
 import org.onlab.util.ItemNotFoundException;
-import org.onosproject.cluster.ClusterService;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.config.ConfigFactory;
 import org.onosproject.net.config.NetworkConfigRegistry;
@@ -40,7 +39,6 @@
 import org.onosproject.net.driver.DriverEvent;
 import org.onosproject.net.driver.DriverListener;
 import org.onosproject.net.driver.DriverProvider;
-import org.onosproject.net.driver.DriverService;
 import org.onosproject.net.pi.model.PiPipeconf;
 import org.onosproject.net.pi.model.PiPipeconfId;
 import org.onosproject.net.pi.service.PiPipeconfConfig;
@@ -81,17 +79,11 @@
     protected NetworkConfigRegistry cfgService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected DriverService driverService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DriverAdminService driverAdminService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     private PiPipeconfMappingStore pipeconfMappingStore;
 
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ClusterService clusterService;
-
     // Registered pipeconf are replicated through the app subsystem and
     // registered on app activated events. Hence, there should be no need of
     // distributing this map.
@@ -117,7 +109,7 @@
     @Activate
     public void activate() {
         cfgService.registerConfigFactory(configFactory);
-        driverService.addListener(driverListener);
+        driverAdminService.addListener(driverListener);
         checkMissingMergedDrivers();
         log.info("Started");
     }
@@ -127,12 +119,11 @@
     public void deactivate() {
         executor.shutdown();
         cfgService.unregisterConfigFactory(configFactory);
-        driverService.removeListener(driverListener);
+        driverAdminService.removeListener(driverListener);
         pipeconfs.clear();
         missingMergedDrivers.clear();
         cfgService = null;
         driverAdminService = null;
-        driverService = null;
         log.info("Stopped");
     }
 
@@ -170,11 +161,17 @@
 
     @Override
     public void bindToDevice(PiPipeconfId pipeconfId, DeviceId deviceId) {
+        PiPipeconfId existingPipeconfId = pipeconfMappingStore.getPipeconfId(deviceId);
+        if (existingPipeconfId != null && !existingPipeconfId.equals(pipeconfId)) {
+            log.error("Cannot set binding for {} to {} as one already exists ({})",
+                      deviceId, pipeconfId, existingPipeconfId);
+            return;
+        }
         pipeconfMappingStore.createOrUpdateBinding(deviceId, pipeconfId);
     }
 
     @Override
-    public String mergeDriver(DeviceId deviceId, PiPipeconfId pipeconfId) {
+    public String getMergedDriver(DeviceId deviceId, PiPipeconfId pipeconfId) {
         log.debug("Starting device driver merge of {} with {}...", deviceId, pipeconfId);
         final BasicDeviceConfig basicDeviceConfig = cfgService.getConfig(
                 deviceId, BasicDeviceConfig.class);
@@ -298,7 +295,7 @@
 
     private Driver getDriver(String name) {
         try {
-            return driverService.getDriver(name);
+            return driverAdminService.getDriver(name);
         } catch (ItemNotFoundException e) {
             return null;
         }