Merge "Handle duplicate tunnel on multiple dpns"
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / listeners / InterfaceInventoryStateListener.java
index f4e489ec8a2f978fbc46cca62f0e3ad5330262b1..b7333697c32d8d76cce98945bf3face8881d8ec4 100644 (file)
@@ -9,9 +9,7 @@ package org.opendaylight.genius.interfacemanager.listeners;
 
 import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
-import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.interfacemanager.IfmConstants;
 import org.opendaylight.genius.interfacemanager.IfmUtil;
@@ -22,7 +20,6 @@ import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInt
 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceStateUpdateHelper;
 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.IfmClusterUtils;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.AlivenessMonitorService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
@@ -35,7 +32,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-
+import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Callable;
@@ -51,10 +48,10 @@ import java.util.concurrent.Callable;
 
 public class InterfaceInventoryStateListener extends AsyncClusteredDataTreeChangeListenerBase<FlowCapableNodeConnector, InterfaceInventoryStateListener> {
     private static final Logger LOG = LoggerFactory.getLogger(InterfaceInventoryStateListener.class);
-    private DataBroker dataBroker;
-    private IdManagerService idManager;
-    private IMdsalApiManager mdsalApiManager;
-    private AlivenessMonitorService alivenessMonitorService;
+    private final DataBroker dataBroker;
+    private final IdManagerService idManager;
+    private final IMdsalApiManager mdsalApiManager;
+    private final AlivenessMonitorService alivenessMonitorService;
 
     public InterfaceInventoryStateListener(final DataBroker dataBroker, final IdManagerService idManager,
                                            final IMdsalApiManager mdsalApiManager, final AlivenessMonitorService alivenessMonitorService) {
@@ -79,68 +76,69 @@ public class InterfaceInventoryStateListener extends AsyncClusteredDataTreeChang
     @Override
     protected void remove(InstanceIdentifier<FlowCapableNodeConnector> key,
                           FlowCapableNodeConnector flowCapableNodeConnectorOld) {
-        IfmClusterUtils.runOnlyInLeaderNode(new Runnable() {
-            @Override
-            public void run() {
-                LOG.debug("Received NodeConnector Remove Event: {}, {}", key, flowCapableNodeConnectorOld);
-                String portName = flowCapableNodeConnectorOld.getName();
-                NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
+        IfmClusterUtils.runOnlyInLeaderNode(() -> {
+            LOG.debug("Received NodeConnector Remove Event: {}, {}", key, flowCapableNodeConnectorOld);
+            String portName = flowCapableNodeConnectorOld.getName();
+            NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
 
-                if (!InterfaceManagerCommonUtils.isNovaOrTunnelPort(portName)) {
-                    portName = getDpnPrefixedPortName(nodeConnectorId, portName);
-                }
-                remove(nodeConnectorId, null, flowCapableNodeConnectorOld, portName, true);
+            if (!InterfaceManagerCommonUtils.isNovaOrTunnelPort(portName)) {
+                portName = getDpnPrefixedPortName(nodeConnectorId, portName);
             }
+            remove(nodeConnectorId, null, flowCapableNodeConnectorOld, portName, true);
         });
     }
 
     @Override
     protected void update(InstanceIdentifier<FlowCapableNodeConnector> key, FlowCapableNodeConnector fcNodeConnectorOld,
                           FlowCapableNodeConnector fcNodeConnectorNew) {
-        IfmClusterUtils.runOnlyInLeaderNode(new Runnable() {
-            @Override
-            public void run() {
-                LOG.debug("Received NodeConnector Update Event: {}, {}, {}", key, fcNodeConnectorOld, fcNodeConnectorNew);
-                String portName = fcNodeConnectorNew.getName();
-                DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+        IfmClusterUtils.runOnlyInLeaderNode(() -> {
+            LOG.debug("Received NodeConnector Update Event: {}, {}, {}", key, fcNodeConnectorOld, fcNodeConnectorNew);
+            String portName = fcNodeConnectorNew.getName();
+            DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
 
-                InterfaceStateUpdateWorker portStateUpdateWorker = new InterfaceStateUpdateWorker(key, fcNodeConnectorOld,
-                        fcNodeConnectorNew, portName);
-                coordinator.enqueueJob(portName, portStateUpdateWorker, IfmConstants.JOB_MAX_RETRIES);
-            }
+            InterfaceStateUpdateWorker portStateUpdateWorker = new InterfaceStateUpdateWorker(key, fcNodeConnectorOld,
+                    fcNodeConnectorNew, portName);
+            coordinator.enqueueJob(portName, portStateUpdateWorker, IfmConstants.JOB_MAX_RETRIES);
         });
     }
 
     @Override
     protected void add(InstanceIdentifier<FlowCapableNodeConnector> key, FlowCapableNodeConnector fcNodeConnectorNew) {
-        IfmClusterUtils.runOnlyInLeaderNode(new Runnable() {
-            @Override
-            public void run() {
-                LOG.debug("Received NodeConnector Add Event: {}, {}", key, fcNodeConnectorNew);
-                String portName = fcNodeConnectorNew.getName();
-                NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
+        IfmClusterUtils.runOnlyInLeaderNode(() -> {
+            LOG.debug("Received NodeConnector Add Event: {}, {}", key, fcNodeConnectorNew);
+            String portName = fcNodeConnectorNew.getName();
+            NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
 
-                //VM Migration: Delete existing interface entry for older DPN
-                if (InterfaceManagerCommonUtils.isNovaOrTunnelPort(portName)) {
-                    NodeConnectorId nodeConnectorIdOld = IfmUtil.getNodeConnectorIdFromInterface(portName, dataBroker);
-                    if (nodeConnectorIdOld != null && !nodeConnectorId.equals(nodeConnectorIdOld)) {
-                        LOG.debug("Triggering NodeConnector Remove Event for the interface: {}, {}, {}", portName, nodeConnectorId, nodeConnectorIdOld);
-                        remove(nodeConnectorId, nodeConnectorIdOld, fcNodeConnectorNew, portName, false);
-                        //Adding a delay of 10sec for VM migration, so applications can process remove and add events
-                        try {
-                            Thread.sleep(IfmConstants.DELAY_TIME_IN_MILLISECOND);
-                        } catch (InterruptedException e) {
-                            LOG.error("Error while waiting for the vm migration remove events to get processed");
+            //VM Migration: Delete existing interface entry for older DPN
+            if (InterfaceManagerCommonUtils.isNovaOrTunnelPort(portName)) {
+                NodeConnectorId nodeConnectorIdOld = IfmUtil.getNodeConnectorIdFromInterface(portName, dataBroker);
+                if (nodeConnectorIdOld != null && !nodeConnectorId.equals(nodeConnectorIdOld)) {
+                    if (InterfaceManagerCommonUtils.isTunnelPort(portName)) {
+                        BigInteger oldDpnId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorIdOld);
+                        BigInteger newDpnId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
+                        LOG.warn("DPNID changed for tunnel interface {}: old {} new {}", portName, oldDpnId, newDpnId);
+                        if(InterfaceMetaUtils.isPortConfiguredOnBridge(portName, oldDpnId, dataBroker) ||
+                                !InterfaceMetaUtils.isPortConfiguredOnBridge(portName, newDpnId, dataBroker)) {
+                            // Remove old interface only it wasn't configured through us and new one is.
+                            return;
                         }
                     }
-                } else {
-                    portName = getDpnPrefixedPortName(nodeConnectorId, portName);
+                    LOG.debug("Triggering NodeConnector Remove Event for the interface: {}, {}, {}", portName, nodeConnectorId, nodeConnectorIdOld);
+                    remove(nodeConnectorId, nodeConnectorIdOld, fcNodeConnectorNew, portName, false);
+                    //Adding a delay of 10sec for VM migration, so applications can process remove and add events
+                    try {
+                        Thread.sleep(IfmConstants.DELAY_TIME_IN_MILLISECOND);
+                    } catch (InterruptedException e) {
+                        LOG.error("Error while waiting for the vm migration remove events to get processed");
+                    }
                 }
-                DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
-                InterfaceStateAddWorker ifStateAddWorker = new InterfaceStateAddWorker(idManager, nodeConnectorId,
-                        fcNodeConnectorNew, portName);
-                coordinator.enqueueJob(portName, ifStateAddWorker, IfmConstants.JOB_MAX_RETRIES);
+            } else {
+                portName = getDpnPrefixedPortName(nodeConnectorId, portName);
             }
+            DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+            InterfaceStateAddWorker ifStateAddWorker = new InterfaceStateAddWorker(idManager, nodeConnectorId,
+                    fcNodeConnectorNew, portName);
+            coordinator.enqueueJob(portName, ifStateAddWorker, IfmConstants.JOB_MAX_RETRIES);
         });
     }
 
@@ -154,7 +152,7 @@ public class InterfaceInventoryStateListener extends AsyncClusteredDataTreeChang
     }
 
     private String getDpnPrefixedPortName(NodeConnectorId nodeConnectorId, String portName) {
-        portName = (IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId)).toString() +
+        portName = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId).toString() +
                 IfmConstants.OF_URI_SEPARATOR +
                 portName;
         return portName;
@@ -200,10 +198,10 @@ public class InterfaceInventoryStateListener extends AsyncClusteredDataTreeChang
     }
 
     private class InterfaceStateUpdateWorker implements Callable {
-        private InstanceIdentifier<FlowCapableNodeConnector> key;
+        private final InstanceIdentifier<FlowCapableNodeConnector> key;
         private final FlowCapableNodeConnector fcNodeConnectorOld;
         private final FlowCapableNodeConnector fcNodeConnectorNew;
-        private String interfaceName;
+        private final String interfaceName;
 
 
         public InterfaceStateUpdateWorker(InstanceIdentifier<FlowCapableNodeConnector> key,