Follow-up to https://git.opendaylight.org/gerrit/#/c/64492/
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / listeners / InterfaceTopologyStateListener.java
index 3b35c62d660c02f6cfa1b4789ccc50e5cb034c6d..145e2ac6d7d0f951cd3baa5c11d88d0c00f7c67f 100644 (file)
@@ -8,22 +8,30 @@
 package org.opendaylight.genius.interfacemanager.listeners;
 
 import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.Callable;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
-import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.interfacemanager.IfmConstants;
+import org.opendaylight.genius.interfacemanager.IfmUtil;
 import org.opendaylight.genius.interfacemanager.InterfacemgrProvider;
-import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceTopologyStateAddHelper;
-import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceTopologyStateRemoveHelper;
+import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceTopologyStateUpdateHelper;
-import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.IfmClusterUtils;
+import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
+import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge._interface.info.BridgeEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
@@ -32,17 +40,28 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Singleton
-public class InterfaceTopologyStateListener extends AsyncClusteredDataTreeChangeListenerBase<OvsdbBridgeAugmentation, InterfaceTopologyStateListener> {
+public class InterfaceTopologyStateListener
+        extends AsyncClusteredDataTreeChangeListenerBase<OvsdbBridgeAugmentation, InterfaceTopologyStateListener> {
     private static final Logger LOG = LoggerFactory.getLogger(InterfaceTopologyStateListener.class);
     private final DataBroker dataBroker;
     private final InterfacemgrProvider interfaceMgrProvider;
+    private final EntityOwnershipUtils entityOwnershipUtils;
+    private final JobCoordinator coordinator;
+    private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
+    private final OvsInterfaceTopologyStateUpdateHelper ovsInterfaceTopologyStateUpdateHelper;
 
     @Inject
-    public InterfaceTopologyStateListener(final DataBroker dataBroker,
-                                          final InterfacemgrProvider interfaceMgrProvider) {
+    public InterfaceTopologyStateListener(final DataBroker dataBroker, final InterfacemgrProvider interfaceMgrProvider,
+            final EntityOwnershipUtils entityOwnershipUtils, final JobCoordinator coordinator,
+            final InterfaceManagerCommonUtils interfaceManagerCommonUtils,
+            final OvsInterfaceTopologyStateUpdateHelper ovsInterfaceTopologyStateUpdateHelper) {
         super(OvsdbBridgeAugmentation.class, InterfaceTopologyStateListener.class);
         this.dataBroker = dataBroker;
         this.interfaceMgrProvider = interfaceMgrProvider;
+        this.entityOwnershipUtils = entityOwnershipUtils;
+        this.coordinator = coordinator;
+        this.interfaceManagerCommonUtils = interfaceManagerCommonUtils;
+        this.ovsInterfaceTopologyStateUpdateHelper = ovsInterfaceTopologyStateUpdateHelper;
         this.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
     }
 
@@ -57,6 +76,11 @@ public class InterfaceTopologyStateListener extends AsyncClusteredDataTreeChange
         return InterfaceTopologyStateListener.this;
     }
 
+    private void runOnlyInOwnerNode(String jobDesc, Runnable job) {
+        entityOwnershipUtils.runOnlyInOwnerNode(IfmConstants.INTERFACE_CONFIG_ENTITY,
+                IfmConstants.INTERFACE_CONFIG_ENTITY, coordinator, jobDesc, job);
+    }
+
     @Override
     protected void remove(InstanceIdentifier<OvsdbBridgeAugmentation> identifier, OvsdbBridgeAugmentation bridgeOld) {
         LOG.debug("Received Remove DataChange Notification for identifier: {}, ovsdbBridgeAugmentation: {}",
@@ -65,12 +89,11 @@ public class InterfaceTopologyStateListener extends AsyncClusteredDataTreeChange
         InstanceIdentifier<Node> nodeIid = identifier.firstIdentifierOf(Node.class);
         interfaceMgrProvider.removeBridgeForNodeIid(nodeIid);
 
-        IfmClusterUtils.runOnlyInLeaderNode(() -> {
-            DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
+        runOnlyInOwnerNode("OVSDB bridge removed", () -> {
             RendererStateRemoveWorker rendererStateRemoveWorker = new RendererStateRemoveWorker(identifier, bridgeOld);
-            jobCoordinator.enqueueJob(bridgeOld.getBridgeName().getValue(), rendererStateRemoveWorker,
+            coordinator.enqueueJob(bridgeOld.getBridgeName().getValue(), rendererStateRemoveWorker,
                 IfmConstants.JOB_MAX_RETRIES);
-        }, IfmClusterUtils.INTERFACE_CONFIG_ENTITY);
+        });
     }
 
     @Override
@@ -83,21 +106,20 @@ public class InterfaceTopologyStateListener extends AsyncClusteredDataTreeChange
         InstanceIdentifier<Node> nodeIid = identifier.firstIdentifierOf(Node.class);
         interfaceMgrProvider.addBridgeForNodeIid(nodeIid, bridgeNew);
 
-        IfmClusterUtils.runOnlyInLeaderNode(() -> {
+        runOnlyInOwnerNode("OVSDB bridge updated", () -> {
             DatapathId oldDpid = bridgeOld.getDatapathId();
             DatapathId newDpid = bridgeNew.getDatapathId();
-            if(oldDpid == null && newDpid != null){
-                DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
+            if (oldDpid == null && newDpid != null) {
                 RendererStateAddWorker rendererStateAddWorker = new RendererStateAddWorker(identifier, bridgeNew);
-                jobCoordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker,
-                    IfmConstants.JOB_MAX_RETRIES);
-            } else if(oldDpid != null && !oldDpid.equals(newDpid)){
-                DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
-                RendererStateUpdateWorker rendererStateAddWorker = new RendererStateUpdateWorker(identifier, bridgeNew, bridgeOld);
-                jobCoordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker,
-                    IfmConstants.JOB_MAX_RETRIES);
+                coordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker,
+                        IfmConstants.JOB_MAX_RETRIES);
+            } else if (oldDpid != null && !oldDpid.equals(newDpid)) {
+                RendererStateUpdateWorker rendererStateAddWorker = new RendererStateUpdateWorker(identifier, bridgeNew,
+                        bridgeOld);
+                coordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker,
+                        IfmConstants.JOB_MAX_RETRIES);
             }
-        }, IfmClusterUtils.INTERFACE_CONFIG_ENTITY);
+        });
     }
 
     @Override
@@ -108,12 +130,11 @@ public class InterfaceTopologyStateListener extends AsyncClusteredDataTreeChange
         InstanceIdentifier<Node> nodeIid = identifier.firstIdentifierOf(Node.class);
         interfaceMgrProvider.addBridgeForNodeIid(nodeIid, bridgeNew);
 
-        IfmClusterUtils.runOnlyInLeaderNode(() -> {
-            DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
+        runOnlyInOwnerNode("OVSDB bridge added", () -> {
             RendererStateAddWorker rendererStateAddWorker = new RendererStateAddWorker(identifier, bridgeNew);
-            jobCoordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker,
+            coordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker,
                 IfmConstants.JOB_MAX_RETRIES);
-        }, IfmClusterUtils.INTERFACE_CONFIG_ENTITY);
+        });
     }
 
     private class RendererStateAddWorker implements Callable<List<ListenableFuture<Void>>> {
@@ -128,10 +149,29 @@ public class InterfaceTopologyStateListener extends AsyncClusteredDataTreeChange
 
         @Override
         public List<ListenableFuture<Void>> call() {
-            // If another renderer(for eg : CSS) needs to be supported, check
-            // can be performed here
-            // to call the respective helpers.
-            return OvsInterfaceTopologyStateAddHelper.addPortToBridge(instanceIdentifier, bridgeNew, dataBroker);
+            List<ListenableFuture<Void>> futures = new ArrayList<>();
+
+            if (bridgeNew.getDatapathId() == null) {
+                LOG.info("DataPathId found as null for Bridge Augmentation: {}... returning...", bridgeNew);
+                return futures;
+            }
+            BigInteger dpnId = IfmUtil.getDpnId(bridgeNew.getDatapathId());
+            LOG.debug("adding bridge references for bridge: {}, dpn: {}", bridgeNew, dpnId);
+            // create bridge reference entry in interface meta operational DS
+            WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+            InterfaceMetaUtils.createBridgeRefEntry(dpnId, instanceIdentifier, writeTransaction);
+
+            // handle pre-provisioning of tunnels for the newly connected dpn
+            BridgeEntry bridgeEntry = InterfaceMetaUtils.getBridgeEntryFromConfigDS(dpnId, dataBroker);
+            if (bridgeEntry == null) {
+                LOG.debug("Bridge entry not found in config DS for dpn: {}", dpnId);
+                futures.add(writeTransaction.submit());
+                return futures;
+            }
+            futures.add(writeTransaction.submit());
+            SouthboundUtils.addAllPortsToBridge(bridgeEntry, dataBroker, interfaceManagerCommonUtils,
+                    instanceIdentifier, bridgeNew);
+            return futures;
         }
     }
 
@@ -147,11 +187,26 @@ public class InterfaceTopologyStateListener extends AsyncClusteredDataTreeChange
 
         @Override
         public List<ListenableFuture<Void>> call() {
-            // If another renderer(for eg : CSS) needs to be supported, check
-            // can be performed here
-            // to call the respective helpers.
-            return OvsInterfaceTopologyStateRemoveHelper.removePortFromBridge(instanceIdentifier, bridgeNew,
-                    dataBroker);
+            BigInteger dpnId = IfmUtil.getDpnId(bridgeNew.getDatapathId());
+
+            if (dpnId == null) {
+                LOG.warn("Got Null DPID for Bridge: {}", bridgeNew);
+                return Collections.emptyList();
+            }
+
+            WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+            LOG.debug("removing bridge references for bridge: {}, dpn: {}", bridgeNew, dpnId);
+            // delete bridge reference entry in interface meta operational DS
+            InterfaceMetaUtils.deleteBridgeRefEntry(dpnId, transaction);
+
+            // the bridge reference is copied to dpn-tunnel interfaces map, so that
+            // whenever a northbound delete
+            // happens when bridge is not connected, we need the bridge reference to
+            // clean up the topology config DS
+            InterfaceMetaUtils.addBridgeRefToBridgeInterfaceEntry(dpnId, new OvsdbBridgeRef(instanceIdentifier),
+                    transaction);
+
+            return Collections.singletonList(transaction.submit());
         }
     }
 
@@ -169,11 +224,7 @@ public class InterfaceTopologyStateListener extends AsyncClusteredDataTreeChange
 
         @Override
         public List<ListenableFuture<Void>> call() {
-            // If another renderer(for eg : CSS) needs to be supported, check
-            // can be performed here
-            // to call the respective helpers.
-            return OvsInterfaceTopologyStateUpdateHelper.updateBridgeRefEntry(instanceIdentifier, bridgeNew, bridgeOld,
-                    dataBroker);
+            return ovsInterfaceTopologyStateUpdateHelper.updateBridgeRefEntry(instanceIdentifier, bridgeNew, bridgeOld);
         }
     }
 }