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 2a5e48c3e87292516ad6d31897faa03fcf6f963d..145e2ac6d7d0f951cd3baa5c11d88d0c00f7c67f 100644 (file)
@@ -8,20 +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.AsyncDataTreeChangeListenerBase;
-import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
 import org.opendaylight.genius.interfacemanager.IfmConstants;
-import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceTopologyStateAddHelper;
-import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceTopologyStateRemoveHelper;
+import org.opendaylight.genius.interfacemanager.IfmUtil;
+import org.opendaylight.genius.interfacemanager.InterfacemgrProvider;
+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.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;
@@ -31,14 +41,27 @@ import org.slf4j.LoggerFactory;
 
 @Singleton
 public class InterfaceTopologyStateListener
-        extends AsyncDataTreeChangeListenerBase<OvsdbBridgeAugmentation, 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) {
+    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);
     }
 
@@ -53,14 +76,24 @@ public class InterfaceTopologyStateListener
         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: {}", identifier,
-                bridgeOld);
-        DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
-        RendererStateRemoveWorker rendererStateRemoveWorker = new RendererStateRemoveWorker(identifier, bridgeOld);
-        jobCoordinator.enqueueJob(bridgeOld.getBridgeName().getValue(), rendererStateRemoveWorker,
+        LOG.debug("Received Remove DataChange Notification for identifier: {}, ovsdbBridgeAugmentation: {}",
+                identifier, bridgeOld);
+
+        InstanceIdentifier<Node> nodeIid = identifier.firstIdentifierOf(Node.class);
+        interfaceMgrProvider.removeBridgeForNodeIid(nodeIid);
+
+        runOnlyInOwnerNode("OVSDB bridge removed", () -> {
+            RendererStateRemoveWorker rendererStateRemoveWorker = new RendererStateRemoveWorker(identifier, bridgeOld);
+            coordinator.enqueueJob(bridgeOld.getBridgeName().getValue(), rendererStateRemoveWorker,
                 IfmConstants.JOB_MAX_RETRIES);
+        });
     }
 
     @Override
@@ -69,30 +102,39 @@ public class InterfaceTopologyStateListener
         LOG.debug(
                 "Received Update DataChange Notification for identifier: {}, ovsdbBridgeAugmentation old: {}, new: {}.",
                 identifier, bridgeOld, bridgeNew);
-        DatapathId oldDpid = bridgeOld.getDatapathId();
-        DatapathId newDpid = bridgeNew.getDatapathId();
-        if (oldDpid == null && newDpid != null) {
-            DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
-            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);
-        }
+
+        InstanceIdentifier<Node> nodeIid = identifier.firstIdentifierOf(Node.class);
+        interfaceMgrProvider.addBridgeForNodeIid(nodeIid, bridgeNew);
+
+        runOnlyInOwnerNode("OVSDB bridge updated", () -> {
+            DatapathId oldDpid = bridgeOld.getDatapathId();
+            DatapathId newDpid = bridgeNew.getDatapathId();
+            if (oldDpid == null && newDpid != null) {
+                RendererStateAddWorker rendererStateAddWorker = new RendererStateAddWorker(identifier, bridgeNew);
+                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);
+            }
+        });
     }
 
     @Override
     protected void add(InstanceIdentifier<OvsdbBridgeAugmentation> identifier, OvsdbBridgeAugmentation bridgeNew) {
-        LOG.debug("Received Add DataChange Notification for identifier: {}, ovsdbBridgeAugmentation: {}", identifier,
-                bridgeNew);
-        DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
-        RendererStateAddWorker rendererStateAddWorker = new RendererStateAddWorker(identifier, bridgeNew);
-        jobCoordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker,
+        LOG.debug("Received Add DataChange Notification for identifier: {}, ovsdbBridgeAugmentation: {}",
+                identifier, bridgeNew);
+
+        InstanceIdentifier<Node> nodeIid = identifier.firstIdentifierOf(Node.class);
+        interfaceMgrProvider.addBridgeForNodeIid(nodeIid, bridgeNew);
+
+        runOnlyInOwnerNode("OVSDB bridge added", () -> {
+            RendererStateAddWorker rendererStateAddWorker = new RendererStateAddWorker(identifier, bridgeNew);
+            coordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker,
                 IfmConstants.JOB_MAX_RETRIES);
+        });
     }
 
     private class RendererStateAddWorker implements Callable<List<ListenableFuture<Void>>> {
@@ -107,10 +149,29 @@ public class InterfaceTopologyStateListener
 
         @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;
         }
     }
 
@@ -126,11 +187,26 @@ public class InterfaceTopologyStateListener
 
         @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());
         }
     }
 
@@ -148,11 +224,7 @@ public class InterfaceTopologyStateListener
 
         @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);
         }
     }
 }