Fix so that operational store correctly removes protocol entries 54/18154/5
authorEd Warnicke <eaw@cisco.com>
Sat, 11 Apr 2015 23:04:19 +0000 (16:04 -0700)
committerEd Warnicke <eaw@cisco.com>
Mon, 13 Apr 2015 17:38:25 +0000 (17:38 +0000)
    Before, if a protocol entry was removed on ovsdb, we didn't
    remove it from the operational store.

    This is an artifact of using *merge* rather than *put*.
    Using merge is *still* a good idea for us, but what was happening
    was basically this.

    Say we got a report in the operational store of

    [protocol1, protocol1]

    which we dutifully merged.

    Then we got a report of
    [protocol2]

    when that is *merged*... the protocol1 entry is left dangling,
    because its a *merge*.  To compensate, we have to be *very*
    specific about wanting to remove protocol1.

Change-Id: I17f8b9b26cea4e894d74b534335dc55f0097d8c8
Signed-off-by: Ed Warnicke <eaw@cisco.com>
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbBridgeUpdateCommand.java

index 15897012b1d40a5ed26aa457e7981393f80d2ca1..1a8866cb3f5ce650d7b14ce64da7c1eae2465300 100644 (file)
@@ -22,6 +22,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.OvsdbBridgeAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
 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.OvsdbNodeAugmentationBuilder;
@@ -30,25 +31,31 @@ 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.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.ProtocolEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 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.NodeBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 
 public class OvsdbBridgeUpdateCommand extends AbstractTransactionCommand {
     private static final Logger LOG = LoggerFactory.getLogger(OvsdbBridgeUpdateCommand.class);
     private Map<UUID,Bridge> updatedBridgeRows;
+    private Map<UUID, Bridge> oldBridgeRows;
 
     public OvsdbBridgeUpdateCommand(OvsdbClientKey key, TableUpdates updates,
             DatabaseSchema dbSchema) {
         super(key,updates,dbSchema);
         updatedBridgeRows = TyperUtils.extractRowsUpdated(Bridge.class, getUpdates(), getDbSchema());
+        oldBridgeRows = TyperUtils.extractRowsOld(Bridge.class, getUpdates(), getDbSchema());
     }
 
     @Override
@@ -73,9 +80,43 @@ public class OvsdbBridgeUpdateCommand extends AbstractTransactionCommand {
             InstanceIdentifier<Node> bridgeIid = SouthboundMapper.createInstanceIdentifier(getKey(),bridge);
             Node bridgeNode = buildBridgeNode(bridge);
             transaction.merge(LogicalDatastoreType.OPERATIONAL, bridgeIid, bridgeNode);
+            deleteEntries(transaction, protocolEntriesToRemove(bridgeIid,bridge));
         }
     }
 
+    private <T extends DataObject> void deleteEntries(ReadWriteTransaction transaction,
+            List<InstanceIdentifier<T>> entryIids) {
+        for (InstanceIdentifier<T> entryIid: entryIids) {
+            transaction.delete(LogicalDatastoreType.OPERATIONAL, entryIid);
+        }
+    }
+
+
+    private List<InstanceIdentifier<ProtocolEntry>> protocolEntriesToRemove(
+            InstanceIdentifier<Node> bridgeIid, Bridge bridge) {
+        Preconditions.checkNotNull(bridgeIid);
+        Preconditions.checkNotNull(bridge);
+        List<InstanceIdentifier<ProtocolEntry>> result =
+                new ArrayList<InstanceIdentifier<ProtocolEntry>>();
+        Bridge oldBridge = oldBridgeRows.get(bridge.getUuid());
+
+        if (oldBridge != null && oldBridge.getProtocolsColumn() != null) {
+            for (String protocol: oldBridge.getProtocolsColumn().getData()) {
+                if (bridge.getProtocolsColumn() == null
+                        || !bridge.getProtocolsColumn().getData().contains(protocol)) {
+                    Class<? extends OvsdbBridgeProtocolBase> proto =
+                            SouthboundConstants.OVSDB_PROTOCOL_MAP.inverse().get(protocol);
+                    InstanceIdentifier<ProtocolEntry> iid = bridgeIid
+                            .augmentation(OvsdbBridgeAugmentation.class)
+                            .child(ProtocolEntry.class,
+                                    new ProtocolEntryKey(proto));
+                    result.add(iid);
+                }
+            }
+        }
+        return result;
+    }
+
     private Optional<Node> readNode(ReadWriteTransaction transaction,
             final InstanceIdentifier<Node> connectionIid) {
         Optional<Node> node = Optional.absent();