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 41c71739f311cc1f5add6f57d7f893cbb3d0a943..145e2ac6d7d0f951cd3baa5c11d88d0c00f7c67f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -8,18 +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.DataChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.genius.datastoreutils.AsyncDataChangeListenerBase;
-import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
-import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
+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.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;
@@ -27,22 +39,36 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.List;
-import java.util.concurrent.Callable;
-
-public class InterfaceTopologyStateListener extends AsyncDataTreeChangeListenerBase<OvsdbBridgeAugmentation, InterfaceTopologyStateListener> {
+@Singleton
+public class InterfaceTopologyStateListener
+        extends AsyncClusteredDataTreeChangeListenerBase<OvsdbBridgeAugmentation, InterfaceTopologyStateListener> {
     private static final Logger LOG = LoggerFactory.getLogger(InterfaceTopologyStateListener.class);
-    private DataBroker dataBroker;
-
-    public InterfaceTopologyStateListener(DataBroker dataBroker) {
+    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,
+            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);
     }
 
     @Override
     protected InstanceIdentifier<OvsdbBridgeAugmentation> getWildCardPath() {
-        return InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class)
-                .child(Node.class).augmentation(OvsdbBridgeAugmentation.class).build();
+        return InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class).child(Node.class)
+                .augmentation(OvsdbBridgeAugmentation.class).build();
     }
 
     @Override
@@ -50,57 +76,102 @@ public class InterfaceTopologyStateListener extends AsyncDataTreeChangeListenerB
         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, IfmConstants.JOB_MAX_RETRIES);
+
+        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
     protected void update(InstanceIdentifier<OvsdbBridgeAugmentation> identifier, OvsdbBridgeAugmentation bridgeOld,
-                          OvsdbBridgeAugmentation bridgeNew) {
-        LOG.debug("Received Update DataChange Notification for identifier: {}, ovsdbBridgeAugmentation old: {}, new: {}.",
+            OvsdbBridgeAugmentation bridgeNew) {
+        LOG.debug(
+                "Received Update DataChange Notification for identifier: {}, ovsdbBridgeAugmentation old: {}, new: {}.",
                 identifier, bridgeOld, bridgeNew);
-        if(bridgeOld.getDatapathId()== null && bridgeNew.getDatapathId()!= null){
-            DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
-            RendererStateAddWorker rendererStateAddWorker = new RendererStateAddWorker(identifier, bridgeNew);
-            jobCoordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker, IfmConstants.JOB_MAX_RETRIES);
-        } else if(!bridgeOld.getDatapathId().equals(bridgeNew.getDatapathId())){
-            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, IfmConstants.JOB_MAX_RETRIES);
+
+        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>>> {
         InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
         OvsdbBridgeAugmentation bridgeNew;
 
-
-        public RendererStateAddWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
-                                      OvsdbBridgeAugmentation bridgeNew) {
+        RendererStateAddWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
+                OvsdbBridgeAugmentation bridgeNew) {
             this.instanceIdentifier = instanceIdentifier;
             this.bridgeNew = bridgeNew;
         }
 
         @Override
-        public List<ListenableFuture<Void>> call() throws Exception {
-            // 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);
+        public List<ListenableFuture<Void>> call() {
+            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;
         }
     }
 
@@ -108,40 +179,52 @@ public class InterfaceTopologyStateListener extends AsyncDataTreeChangeListenerB
         InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
         OvsdbBridgeAugmentation bridgeNew;
 
-
-        public RendererStateRemoveWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
-                                         OvsdbBridgeAugmentation bridgeNew) {
+        RendererStateRemoveWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
+                OvsdbBridgeAugmentation bridgeNew) {
             this.instanceIdentifier = instanceIdentifier;
             this.bridgeNew = bridgeNew;
         }
 
         @Override
-        public List<ListenableFuture<Void>> call() throws Exception {
-            // 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);
+        public List<ListenableFuture<Void>> call() {
+            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());
         }
     }
+
     private class RendererStateUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
         InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
         OvsdbBridgeAugmentation bridgeNew;
         OvsdbBridgeAugmentation bridgeOld;
 
-
-        public RendererStateUpdateWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
-                                         OvsdbBridgeAugmentation bridgeNew, OvsdbBridgeAugmentation bridgeOld) {
+        RendererStateUpdateWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
+                OvsdbBridgeAugmentation bridgeNew, OvsdbBridgeAugmentation bridgeOld) {
             this.instanceIdentifier = instanceIdentifier;
             this.bridgeNew = bridgeNew;
             this.bridgeOld = bridgeOld;
         }
 
         @Override
-        public List<ListenableFuture<Void>> call() throws Exception {
-            // 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);
+        public List<ListenableFuture<Void>> call() {
+            return ovsInterfaceTopologyStateUpdateHelper.updateBridgeRefEntry(instanceIdentifier, bridgeNew, bridgeOld);
         }
     }
-}
\ No newline at end of file
+}