delete reconciliation support on termination points 07/82707/12
authorChetan Arakere Gowdru <chetan.arakere@altencalsoftlabs.com>
Tue, 25 Jun 2019 08:55:28 +0000 (14:25 +0530)
committerChetan Arakere Gowdru <chetan.arakere@altencalsoftlabs.com>
Mon, 11 Nov 2019 05:33:32 +0000 (05:33 +0000)
Descripion:
There exists chances of stale tunnel-ports left over under following
scenario.

1) DPN connected and Tunnel configuration pushed in by ODL.
2) DPN disconnected and Tunnel Configuation delete by ODL from
network-topology config DS.
3) On DPN connecting back, there exists stale tunnelport port on this
DPN.

Following Changes are done to handle delete reconciliation support.

1) Configure "created_by:odl" on tunnel port in OVS(Port, Interface)
which will be pushed by ovsdb plugin.
2) During reconcilation, compare the termination points available in
config and oper DS and trigger delete of those stale termination points
of Oper DS which are set with "created_by:odl"

JIRA: OVSDB-459

Change-Id: I9356d5ef0af44334c97b6cf3632d4ce9fd2070aa
Signed-off-by: Chetan Arakere Gowdru <chetan.arakere@altencalsoftlabs.com>
Signed-off-by: xcheara <chetan.arakere@altencalsoftlabs.com>
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundConstants.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundUtil.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointCreateCommand.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointDeleteCommand.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointUpdateCommand.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/reconciliation/ReconciliationManager.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/reconciliation/configuration/BridgeConfigReconciliationTask.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/reconciliation/configuration/TerminationPointConfigReconciliationTask.java
utils/southbound-utils/src/main/java/org/opendaylight/ovsdb/utils/southbound/utils/SouthboundUtils.java

index 48e77ce02101dfb02c8ea4bfc04cc23fa281243c..824cb23809fcd074477797c3475ebcc2e0919b7f 100755 (executable)
@@ -85,6 +85,9 @@ public interface SouthboundConstants {
     String QOS_LINUX_FQ_CODEL = "linux-fq_codel";
     String QOS_EGRESS_POLICER = "egress-policer";
     String URI_SEPERATOR = "/";
+    String CREATED_BY = "created_by";
+    String ODL = "odl";
+
     ImmutableBiMap<Class<? extends QosTypeBase>,String> QOS_TYPE_MAP
         = new ImmutableBiMap.Builder<Class<? extends QosTypeBase>,String>()
             .put(QosTypeLinuxHtb.class,QOS_LINUX_HTB)
index 5411a0fd76b8de53e03b0acddd2cbef7e48fb164..2a73c006aea2a190e8044a4ef785ad2a52db0f2c 100644 (file)
@@ -27,6 +27,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIdsBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -150,4 +154,16 @@ public final class SouthboundUtil {
     public static void schemaMismatchLog(String column, String table, SchemaVersionMismatchException ex) {
         LOG.debug(SCHEMA_VERSION_MISMATCH, column, table, SouthboundConstants.OPEN_V_SWITCH, ex.getMessage());
     }
+
+    public static PortExternalIds createExternalIdsForPort(String key, String value) {
+        return new PortExternalIdsBuilder()
+            .setExternalIdKey(key)
+            .setExternalIdValue(value).build();
+    }
+
+    public static InterfaceExternalIds createExternalIdsForInterface(String key, String value) {
+        return new InterfaceExternalIdsBuilder()
+            .setExternalIdKey(key)
+            .setExternalIdValue(value).build();
+    }
 }
index be357416ec4d3e3a0164d66f84eb2ff75f62606f..48a141efd586653afc1a91d7410d1b26ebde4137 100644 (file)
@@ -12,6 +12,8 @@ import static org.opendaylight.ovsdb.southbound.SouthboundUtil.schemaMismatchLog
 
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -38,6 +40,7 @@ import org.opendaylight.ovsdb.southbound.InstanceIdentifierCodec;
 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
 import org.opendaylight.ovsdb.southbound.SouthboundProvider;
+import org.opendaylight.ovsdb.southbound.SouthboundUtil;
 import org.opendaylight.ovsdb.utils.yang.YangUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
@@ -103,7 +106,8 @@ public class TerminationPointCreateCommand implements TransactCommand {
                 // Configure port with the above interface details
                 String portUuid = "Port_" + SouthboundMapper.getRandomUuid();
                 Port port = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), Port.class);
-                createPort(terminationPoint, port, interfaceUuid);
+                final String opendaylightIid = instanceIdentifierCodec.serialize(terminationPointIid);
+                createPort(terminationPoint, port, interfaceUuid, opendaylightIid);
                 transaction.add(op.insert(port).withId(portUuid));
                 LOG.info("Created Termination Point : {} with Uuid : {}",
                         terminationPoint.getName(),portUuid);
@@ -150,7 +154,7 @@ public class TerminationPointCreateCommand implements TransactCommand {
 
     private void createPort(
             final OvsdbTerminationPointAugmentation terminationPoint,
-            final Port port, final String interfaceUuid) {
+            final Port port, final String interfaceUuid, final String opendaylightIid) {
 
         port.setName(terminationPoint.getName());
         port.setInterfaces(Collections.singleton(new UUID(interfaceUuid)));
@@ -158,7 +162,7 @@ public class TerminationPointCreateCommand implements TransactCommand {
         createPortVlanTag(terminationPoint, port);
         createPortVlanTrunk(terminationPoint, port);
         createPortVlanMode(terminationPoint, port);
-        createPortExternalIds(terminationPoint, port);
+        createPortExternalIds(terminationPoint, port, opendaylightIid);
     }
 
     private void createOfPort(
@@ -203,12 +207,17 @@ public class TerminationPointCreateCommand implements TransactCommand {
         List<InterfaceExternalIds> interfaceExternalIds =
                 terminationPoint.getInterfaceExternalIds();
         if (interfaceExternalIds != null && !interfaceExternalIds.isEmpty()) {
-            try {
-                ovsInterface.setExternalIds(YangUtils.convertYangKeyValueListToMap(interfaceExternalIds,
-                        InterfaceExternalIds::getExternalIdKey, InterfaceExternalIds::getExternalIdValue));
-            } catch (NullPointerException e) {
-                LOG.warn("Incomplete OVSDB interface external_ids", e);
-            }
+            interfaceExternalIds.add(SouthboundUtil.createExternalIdsForInterface(
+                SouthboundConstants.CREATED_BY, SouthboundConstants.ODL));
+        } else {
+            interfaceExternalIds = Arrays.asList(SouthboundUtil.createExternalIdsForInterface(
+                SouthboundConstants.CREATED_BY, SouthboundConstants.ODL));
+        }
+        try {
+            ovsInterface.setExternalIds(YangUtils.convertYangKeyValueListToMap(interfaceExternalIds,
+                    InterfaceExternalIds::getExternalIdKey, InterfaceExternalIds::getExternalIdValue));
+        } catch (NullPointerException e) {
+            LOG.warn("Incomplete OVSDB interface external_ids", e);
         }
     }
 
@@ -272,16 +281,29 @@ public class TerminationPointCreateCommand implements TransactCommand {
 
     private void createPortExternalIds(
             final OvsdbTerminationPointAugmentation terminationPoint,
-            final Port port) {
+            final Port port, final String opendaylightIid) {
 
+        // Set the iid external_id
         List<PortExternalIds> portExternalIds = terminationPoint.getPortExternalIds();
         if (portExternalIds != null && !portExternalIds.isEmpty()) {
-            try {
-                port.setExternalIds(YangUtils.convertYangKeyValueListToMap(portExternalIds,
-                        PortExternalIds::getExternalIdKey, PortExternalIds::getExternalIdValue));
-            } catch (NullPointerException e) {
-                LOG.warn("Incomplete OVSDB port external_ids", e);
-            }
+            portExternalIds.add(SouthboundUtil.createExternalIdsForPort(
+                SouthboundConstants.CREATED_BY, SouthboundConstants.ODL));
+            portExternalIds.add(SouthboundUtil.createExternalIdsForPort(
+                SouthboundConstants.IID_EXTERNAL_ID_KEY, opendaylightIid));
+        } else {
+            portExternalIds = new ArrayList<PortExternalIds>();
+            portExternalIds.add(SouthboundUtil.createExternalIdsForPort(
+                SouthboundConstants.CREATED_BY, SouthboundConstants.ODL));
+            portExternalIds.add(SouthboundUtil.createExternalIdsForPort(
+                SouthboundConstants.IID_EXTERNAL_ID_KEY, opendaylightIid));
+        }
+        try {
+            port.setExternalIds(YangUtils.convertYangKeyValueListToMap(portExternalIds,
+                PortExternalIds::getExternalIdKey, PortExternalIds::getExternalIdValue));
+            //YangUtils.copyYangKeyValueListToMap(externalIdMap, terminationPoint.getPortExternalIds(),
+             //       PortExternalIds::getExternalIdKey, PortExternalIds::getExternalIdValue);
+        } catch (NullPointerException e) {
+            LOG.warn("Incomplete OVSDB port external_ids", e);
         }
     }
 
@@ -374,5 +396,4 @@ public class TerminationPointCreateCommand implements TransactCommand {
                 .where(port.getNameColumn().getSchema().opEqual(interfaceName))
                 .build());
     }
-
-}
+}
\ No newline at end of file
index 658920174999911f5e32d813c3ed7677a20c7270..53dc870a60ae5256848a5555d0c19955640bd4df 100644 (file)
@@ -62,9 +62,9 @@ public class TerminationPointDeleteCommand implements TransactCommand {
                          Set<InstanceIdentifier<OvsdbTerminationPointAugmentation>> removedTps) {
         for (InstanceIdentifier<OvsdbTerminationPointAugmentation> removedTpIid: removedTps) {
             LOG.debug("Received request to delete termination point {}", removedTpIid);
-
             OvsdbTerminationPointAugmentation original = originals.get(removedTpIid);
             Node originalNode = originalNodes.get(removedTpIid.firstIdentifierOf(Node.class));
+            LOG.trace("Termination point's associated original node {}", originalNode);
             OvsdbBridgeAugmentation originalOvsdbBridgeAugmentation =
                     originalNode.augmentation(OvsdbBridgeAugmentation.class);
             String bridgeName = null;
@@ -78,11 +78,9 @@ public class TerminationPointDeleteCommand implements TransactCommand {
                     LOG.error("Bridge does not exist for termination point {}", removedTpIid);
                 }
             }
-
             Port port = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), Port.class,null);
             Optional<OvsdbTerminationPointAugmentation> tpAugmentation =
                     state.getOvsdbTerminationPointAugmentation(removedTpIid);
-
             if (tpAugmentation.isPresent()) {
                 OvsdbTerminationPointAugmentation tp = tpAugmentation.get();
                 if (tp.getPortUuid() != null) {
index 76f2544d7e82ae52873797321a70516bcab4f7da..303822fcb4ab0f5aed0bbc9f0876fcb5eba38f02 100644 (file)
@@ -13,6 +13,7 @@ import static org.opendaylight.ovsdb.southbound.SouthboundUtil.schemaMismatchLog
 
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -35,6 +36,7 @@ import org.opendaylight.ovsdb.schema.openvswitch.Port;
 import org.opendaylight.ovsdb.southbound.InstanceIdentifierCodec;
 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
 import org.opendaylight.ovsdb.southbound.SouthboundProvider;
+import org.opendaylight.ovsdb.southbound.SouthboundUtil;
 import org.opendaylight.ovsdb.utils.yang.YangUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
@@ -111,7 +113,7 @@ public class TerminationPointUpdateCommand implements TransactCommand {
             TerminationPointCreateCommand.stampInstanceIdentifier(transaction,
                     iid.firstIdentifierOf(OvsdbTerminationPointAugmentation.class), terminationPoint.getName(),
                     instanceIdentifierCodec);
-
+            final String opendaylightIid = instanceIdentifierCodec.serialize(iid);
             // Update port
             // Bug#6136
             Optional<OvsdbBridgeAugmentation> ovsdbBridgeOptional = state.getOvsdbBridgeAugmentation(iid);
@@ -120,7 +122,7 @@ public class TerminationPointUpdateCommand implements TransactCommand {
                 if (operBridge != null) {
                     Port port = TyperUtils.getTypedRowWrapper(
                         transaction.getDatabaseSchema(), Port.class);
-                    updatePort(terminationPoint, port, operBridge);
+                    updatePort(terminationPoint, port, operBridge, opendaylightIid);
                     Port extraPort = TyperUtils.getTypedRowWrapper(
                         transaction.getDatabaseSchema(), Port.class);
                     extraPort.setName("");
@@ -152,13 +154,14 @@ public class TerminationPointUpdateCommand implements TransactCommand {
     private void updatePort(
             final OvsdbTerminationPointAugmentation terminationPoint,
             final Port port,
-            final OvsdbBridgeAugmentation operBridge) {
+            final OvsdbBridgeAugmentation operBridge,
+            final String opendaylightIid) {
 
         updatePortOtherConfig(terminationPoint, port);
         updatePortVlanTag(terminationPoint, port);
         updatePortVlanTrunk(terminationPoint, port);
         updatePortVlanMode(terminationPoint, port);
-        updatePortExternalIds(terminationPoint, port);
+        updatePortExternalIds(terminationPoint, port, opendaylightIid);
         updatePortQos(terminationPoint, port, operBridge);
     }
 
@@ -250,12 +253,17 @@ public class TerminationPointUpdateCommand implements TransactCommand {
         List<InterfaceExternalIds> interfaceExternalIds =
                 terminationPoint.getInterfaceExternalIds();
         if (interfaceExternalIds != null && !interfaceExternalIds.isEmpty()) {
-            try {
-                ovsInterface.setExternalIds(YangUtils.convertYangKeyValueListToMap(interfaceExternalIds,
-                        InterfaceExternalIds::getExternalIdKey, InterfaceExternalIds::getExternalIdValue));
-            } catch (NullPointerException e) {
-                LOG.warn("Incomplete OVSDB interface external_ids", e);
-            }
+            interfaceExternalIds.add(SouthboundUtil.createExternalIdsForInterface(
+                SouthboundConstants.CREATED_BY, SouthboundConstants.ODL));
+        } else {
+            interfaceExternalIds = Arrays.asList(SouthboundUtil.createExternalIdsForInterface(
+                SouthboundConstants.CREATED_BY, SouthboundConstants.ODL));
+        }
+        try {
+            ovsInterface.setExternalIds(YangUtils.convertYangKeyValueListToMap(interfaceExternalIds,
+                    InterfaceExternalIds::getExternalIdKey, InterfaceExternalIds::getExternalIdValue));
+        } catch (NullPointerException e) {
+            LOG.warn("Incomplete OVSDB interface external_ids", e);
         }
     }
 
@@ -335,17 +343,19 @@ public class TerminationPointUpdateCommand implements TransactCommand {
 
     private void updatePortExternalIds(
             final OvsdbTerminationPointAugmentation terminationPoint,
-            final Port port) {
+            final Port port,
+            final String opendaylightIid) {
 
-        List<PortExternalIds> portExternalIds = terminationPoint.getPortExternalIds();
-        if (portExternalIds != null && !portExternalIds.isEmpty()) {
-            try {
-                port.setExternalIds(YangUtils.convertYangKeyValueListToMap(portExternalIds,
-                        PortExternalIds::getExternalIdKey, PortExternalIds::getExternalIdValue));
-            } catch (NullPointerException e) {
-                LOG.warn("Incomplete OVSDB port external_ids", e);
-            }
+        Map<String, String> externalIdMap = new HashMap<>();
+        externalIdMap.put(SouthboundConstants.IID_EXTERNAL_ID_KEY, opendaylightIid);
+        externalIdMap.put(SouthboundConstants.CREATED_BY, SouthboundConstants.ODL);
+        try {
+            YangUtils.copyYangKeyValueListToMap(externalIdMap, terminationPoint.getPortExternalIds(),
+                    PortExternalIds::getExternalIdKey, PortExternalIds::getExternalIdValue);
+        } catch (NullPointerException e) {
+            LOG.warn("Incomplete OVSDB port external_ids", e);
         }
+        port.setExternalIds(externalIdMap);
     }
 
     private void updatePortVlanTag(
@@ -400,5 +410,4 @@ public class TerminationPointUpdateCommand implements TransactCommand {
             }
         }
     }
-
 }
index e4f8e74475c2574d1849d96616da726c9c7ac691..e40ff617eb02e3ab0c77e4cb5299a8ac546c7264 100644 (file)
@@ -13,7 +13,9 @@ import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import com.google.common.util.concurrent.UncheckedExecutionException;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
@@ -36,6 +38,7 @@ import org.opendaylight.ovsdb.southbound.SouthboundMapper;
 import org.opendaylight.ovsdb.southbound.ovsdb.transact.TransactUtils;
 import org.opendaylight.ovsdb.southbound.reconciliation.configuration.TerminationPointConfigReconciliationTask;
 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.OvsdbTerminationPointAugmentation;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
@@ -168,6 +171,7 @@ public class ReconciliationManager implements AutoCloseable {
                         nodeConnectionMetadata.getNode(),
                         nodeConnectionMetadata.getNodeIid(),
                         nodeConnectionMetadata.getConnectionInstance(),
+                        nodeConnectionMetadata.getOperTerminationPoints(),
                         instanceIdentifierCodec
                 ));
             }
@@ -215,6 +219,9 @@ public class ReconciliationManager implements AutoCloseable {
             if (!bridgeNodeCache.asMap().isEmpty()) {
                 Map<InstanceIdentifier<OvsdbBridgeAugmentation>, OvsdbBridgeAugmentation> nodes =
                         TransactUtils.extractCreated(changes, OvsdbBridgeAugmentation.class);
+                Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation>
+                            terminationPointsAug =
+                        TransactUtils.extractCreated(changes, OvsdbTerminationPointAugmentation.class);
                 for (Map.Entry<InstanceIdentifier<OvsdbBridgeAugmentation>, OvsdbBridgeAugmentation> entry :
                         nodes.entrySet()) {
                     InstanceIdentifier<?> bridgeIid = entry.getKey();
@@ -222,12 +229,15 @@ public class ReconciliationManager implements AutoCloseable {
                     try {
                         NodeConnectionMetadata bridgeNodeMetaData = bridgeNodeCache.get(nodeKey);
                         bridgeNodeMetaData.setNodeIid(bridgeIid);
+                        bridgeNodeMetaData.setOperTerminationPoints(
+                                filterTerminationPointsForBridge(nodeKey, terminationPointsAug));
                         TerminationPointConfigReconciliationTask tpReconciliationTask =
                                 new TerminationPointConfigReconciliationTask(ReconciliationManager.this,
                                         bridgeNodeMetaData.getConnectionManager(),
                                         bridgeNodeMetaData.getNode(),
                                         bridgeIid,
                                         bridgeNodeMetaData.getConnectionInstance(),
+                                        bridgeNodeMetaData.getOperTerminationPoints(),
                                         instanceIdentifierCodec);
                         enqueue(tpReconciliationTask);
                         bridgeNodeCache.invalidate(nodeKey);
@@ -253,6 +263,30 @@ public class ReconciliationManager implements AutoCloseable {
         }
     }
 
+    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+            justification = "https://github.com/spotbugs/spotbugs/issues/811")
+    private Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation>
+        filterTerminationPointsForBridge(NodeKey nodeKey,
+            Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation>
+            terminationPoints) {
+
+        Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation>
+                filteredTerminationPoints = new HashMap<>();
+        for (Map.Entry<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation> entry :
+                terminationPoints.entrySet()) {
+            InstanceIdentifier<?> bridgeIid = entry.getKey();
+            NodeKey terminationPointNodeKey = bridgeIid.firstKeyOf(Node.class);
+            if (terminationPointNodeKey.getNodeId().equals(nodeKey.getNodeId())) {
+                LOG.trace("TP Match found: {} {} ", terminationPointNodeKey.getNodeId(), nodeKey.getNodeId());
+                filteredTerminationPoints.put(entry.getKey(), entry.getValue());
+            } else {
+                LOG.trace("TP No Match found : {} {} ", terminationPointNodeKey.getNodeId(), nodeKey.getNodeId());
+            }
+        }
+        return filteredTerminationPoints;
+
+    }
+
     private void cleanupBridgeCreatedDataTreeChangeRegistration() {
         if (bridgeCreatedDataTreeChangeRegistration != null) {
             bridgeCreatedDataTreeChangeRegistration.close();
@@ -265,6 +299,19 @@ public class ReconciliationManager implements AutoCloseable {
         private InstanceIdentifier<?> nodeIid;
         private final OvsdbConnectionManager connectionManager;
         private final OvsdbConnectionInstance connectionInstance;
+        private Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation>
+            operTerminationPoints;
+
+        public Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation>
+            getOperTerminationPoints() {
+            return operTerminationPoints;
+        }
+
+        public void setOperTerminationPoints(
+            Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation>
+                operTerminationPoints) {
+            this.operTerminationPoints = operTerminationPoints;
+        }
 
         NodeConnectionMetadata(Node node,
                                OvsdbConnectionManager connectionManager,
index 6c14db8f71de467d347a304d0f24f5a880682dc9..2a65351530d5ec872c223f8dd11b0325adc35740 100644 (file)
@@ -194,11 +194,14 @@ public class BridgeConfigReconciliationTask extends ReconciliationTask {
                 brChanges.putAll(extractBridgeConfigurationChanges(node, bridge));
                 tpChanges.add(node);
             } else if (node.key().getNodeId().getValue().startsWith(
-                nodeIid.firstKeyOf(Node.class).getNodeId().getValue())
-                && node.getTerminationPoint() != null && !node.getTerminationPoint().isEmpty()) {
+                nodeIid.firstKeyOf(Node.class).getNodeId().getValue())) {
+                //&& node.getTerminationPoint() != null && !node.getTerminationPoint().isEmpty()) {
+                // Above check removed to handle delete reconciliation with ManagedBy
+                // param not set in config DS
                 tpChanges.add(node);
             } else {
                 LOG.trace("Ignoring Reconcilation of Bridge: {}", node.key().getNodeId().getValue());
+
             }
         }
 
index 2d13d1a3a0bb446d41f6c4748bc6c992540b510b..597e11dcd2ce24c543ff8ecfeb74644147f90a42 100644 (file)
@@ -7,19 +7,27 @@
  */
 package org.opendaylight.ovsdb.southbound.reconciliation.configuration;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
+
 import org.opendaylight.ovsdb.southbound.InstanceIdentifierCodec;
 import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
 import org.opendaylight.ovsdb.southbound.OvsdbConnectionManager;
+import org.opendaylight.ovsdb.southbound.SouthboundConstants;
 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
 import org.opendaylight.ovsdb.southbound.ovsdb.transact.BridgeOperationalState;
 import org.opendaylight.ovsdb.southbound.ovsdb.transact.DataChangeEvent;
 import org.opendaylight.ovsdb.southbound.ovsdb.transact.TerminationPointCreateCommand;
+import org.opendaylight.ovsdb.southbound.ovsdb.transact.TerminationPointDeleteCommand;
 import org.opendaylight.ovsdb.southbound.reconciliation.ReconciliationManager;
 import org.opendaylight.ovsdb.southbound.reconciliation.ReconciliationTask;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIds;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -39,22 +47,27 @@ public class TerminationPointConfigReconciliationTask extends ReconciliationTask
     private static final Logger LOG = LoggerFactory.getLogger(TerminationPointConfigReconciliationTask.class);
     private final OvsdbConnectionInstance connectionInstance;
     private final InstanceIdentifierCodec instanceIdentifierCodec;
+    private final Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation>
+        operTerminationPoints;
 
     public TerminationPointConfigReconciliationTask(final ReconciliationManager reconciliationManager,
             final OvsdbConnectionManager connectionManager, final Node bridgeNode,
             final InstanceIdentifier<?> bridgeIid, final OvsdbConnectionInstance connectionInstance,
+            final Map<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation>
+                operTerminationPoints,
             final InstanceIdentifierCodec instanceIdentifierCodec) {
         super(reconciliationManager, connectionManager, bridgeIid, bridgeNode);
         this.connectionInstance = connectionInstance;
         this.instanceIdentifierCodec = instanceIdentifierCodec;
+        this.operTerminationPoints = operTerminationPoints;
     }
 
     @Override
     public boolean reconcileConfiguration(final OvsdbConnectionManager connectionManager) {
-        LOG.debug("Reconcile Termination Point Configuration for node {}", ((Node) configData).getNodeId());
         final Map<InstanceIdentifier<?>, DataObject> changes = new HashMap<>();
-        changes.putAll(SouthboundMapper.extractTerminationPointConfigurationChanges((Node) configData));
-
+        final Node configNodeData = ((Node) configData);
+        LOG.debug("Reconcile Termination Point Configuration for node {}", configNodeData.getNodeId());
+        changes.putAll(SouthboundMapper.extractTerminationPointConfigurationChanges(configNodeData));
         DataChangeEvent changeEvents = new DataChangeEvent() {
             @Override
             public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
@@ -81,6 +94,74 @@ public class TerminationPointConfigReconciliationTask extends ReconciliationTask
                         new BridgeOperationalState(reconciliationManager.getDb(), changeEvents),
                         changeEvents, instanceIdentifierCodec);
 
+        List<String> configTerminationPoints = new ArrayList<>();
+        if (configNodeData.getTerminationPoint() != null) {
+            configNodeData.getTerminationPoint().forEach(entry -> {
+                configTerminationPoints.add(entry.getTpId().getValue());
+            });
+        }
+
+        Set<InstanceIdentifier<?>> removeTerminationPoints = new HashSet<>();
+        final Map<InstanceIdentifier<?>, DataObject> original = new HashMap<>();
+        final InstanceIdentifier<Node> bridgeNodeIid =
+                SouthboundMapper.createInstanceIdentifier(configNodeData.getNodeId());
+        original.put(bridgeNodeIid, configNodeData);
+        LOG.trace("Config Topology Termination Points during Reconciliation {} for bridge {}",
+            configTerminationPoints, bridgeNodeIid);
+        LOG.trace("Oper Topology Termination Points during Reconciliation {} for bridge {}",
+            operTerminationPoints, bridgeNodeIid);
+        for (Map.Entry<InstanceIdentifier<OvsdbTerminationPointAugmentation>, OvsdbTerminationPointAugmentation> entry :
+                operTerminationPoints.entrySet()) {
+            OvsdbTerminationPointAugmentation terminationPoint = entry.getValue();
+            if (configTerminationPoints.contains(terminationPoint.getName())) {
+                LOG.trace("Termination Point {} from Oper Topology also present in config topology During Reconcile",
+                    terminationPoint.getName());
+            } else {
+                LOG.trace("Termination Point {} from Oper Topology NOT present in config topology During Reconcile,"
+                        + "checking if this created by ODL and perform delete reconciliation",
+                    terminationPoint.getName());
+                List<PortExternalIds> externalIds = terminationPoint.getPortExternalIds();
+                if (externalIds != null) {
+                    for (PortExternalIds portExternalIds : externalIds) {
+                        if (portExternalIds.getExternalIdKey().equals(SouthboundConstants.CREATED_BY)
+                            && portExternalIds.getExternalIdValue().equals(SouthboundConstants.ODL)) {
+                            LOG.trace("Termination Point {} created by ODL. Marking for deletion during reconcile",
+                                entry.getKey());
+                            removeTerminationPoints.add(entry.getKey());
+                            original.put(entry.getKey(), entry.getValue());
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        DataChangeEvent deleteChangeEvents = new DataChangeEvent() {
+            @Override
+            public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
+                return Collections.emptyMap();
+            }
+
+            @Override
+            public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
+                return original;
+            }
+
+            @Override
+            public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
+                return original;
+            }
+
+            @Override
+            public Set<InstanceIdentifier<?>> getRemovedPaths() {
+                return removeTerminationPoints;
+            }
+        };
+
+        connectionInstance.transact(new TerminationPointDeleteCommand(),
+                new BridgeOperationalState(reconciliationManager.getDb(), deleteChangeEvents),
+                deleteChangeEvents, instanceIdentifierCodec);
+
         return true;
     }
 
index b8088fa19cac43b98f3226ae3462057e99f3febb..e766b9d593b2cc703c1f252603ed512d994382b5 100644 (file)
@@ -75,6 +75,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIdsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
@@ -201,7 +202,8 @@ public class SouthboundUtils {
     private static final String PATCH_PORT_TYPE = "patch";
     // External ID key used for mapping between an OVSDB port and an interface name
     private static final String EXTERNAL_INTERFACE_ID_KEY = "iface-id";
-
+    private static final String CREATED_BY = "created_by";
+    private static final String ODL = "odl";
     private static final String FORMAT = "(\\d+)\\.(\\d+)\\.(\\d+)";
     private static final Pattern PATTERN = Pattern.compile(FORMAT);
 
@@ -739,6 +741,7 @@ public class SouthboundUtils {
             bridgeOtherConfigsBuilder.setBridgeOtherConfigValue("true");
             otherConfigs.add(bridgeOtherConfigsBuilder.build());
             ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
+            ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(setBridgeExternalIds());
             setManagedByForBridge(ovsdbBridgeAugmentationBuilder, ovsdbNode.key());
             if (dpType != null) {
                 ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
@@ -1389,4 +1392,13 @@ public class SouthboundUtils {
         }
         return false;
     }
+
+    private List<BridgeExternalIds> setBridgeExternalIds() {
+        List<BridgeExternalIds> externalIdsList = new ArrayList<>();
+        externalIdsList.add(new BridgeExternalIdsBuilder()
+                .setBridgeExternalIdKey(CREATED_BY)
+                .setBridgeExternalIdValue(ODL)
+                .build());
+        return externalIdsList;
+    }
 }