Bug 5174: Support for AutoAttach Table in OVSDB 61/33861/34
authorRashmi Pujar <rpujar@inocybe.com>
Mon, 1 Feb 2016 17:23:41 +0000 (12:23 -0500)
committerRashmi Pujar <rpujar@inocybe.com>
Thu, 10 Mar 2016 23:22:33 +0000 (23:22 +0000)
Change-Id: I325f58517caa66079de26c70d2818770968ef3bf
Signed-off-by: Rashmi Pujar <rpujar@inocybe.com>
16 files changed:
schemas/openvswitch/src/main/java/org/opendaylight/ovsdb/schema/openvswitch/AutoAttach.java [new file with mode: 0644]
schemas/openvswitch/src/main/java/org/opendaylight/ovsdb/schema/openvswitch/Bridge.java
southbound/southbound-api/src/main/yang/ovsdb.yang
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbSchemaContants.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundConstants.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachRemovedCommand.java [new file with mode: 0644]
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachUpdateCommand.java [new file with mode: 0644]
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactCommandAggregator.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbAutoAttachRemovedCommand.java [new file with mode: 0644]
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbAutoAttachUpdateCommand.java [new file with mode: 0644]
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbBridgeUpdateCommand.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbOperationalCommandAggregator.java
southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactCommandAggregatorTest.java
southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbAutoAttachRemovedCommandTest.java [new file with mode: 0644]
southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbAutoAttachUpdateCommandTest.java [new file with mode: 0644]
southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbOperationalCommandAggregatorTest.java

diff --git a/schemas/openvswitch/src/main/java/org/opendaylight/ovsdb/schema/openvswitch/AutoAttach.java b/schemas/openvswitch/src/main/java/org/opendaylight/ovsdb/schema/openvswitch/AutoAttach.java
new file mode 100644 (file)
index 0000000..28ad9ba
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.schema.openvswitch;
+
+import java.util.Map;
+
+import org.opendaylight.ovsdb.lib.notation.Column;
+import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
+import org.opendaylight.ovsdb.lib.schema.typed.MethodType;
+import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
+import org.opendaylight.ovsdb.lib.schema.typed.TypedColumn;
+import org.opendaylight.ovsdb.lib.schema.typed.TypedTable;
+
+/**
+ * This class is a typed interface to the AutoAttach Table
+ */
+@TypedTable(name="AutoAttach", database="Open_vSwitch", fromVersion="7.11.2")
+public interface AutoAttach extends TypedBaseTable<GenericTableSchema> {
+
+    @TypedColumn(name="system_name", method=MethodType.GETCOLUMN, fromVersion="7.11.2")
+    Column<GenericTableSchema, String> getSystemNameColumn();
+    @TypedColumn(name="system_name", method=MethodType.SETDATA, fromVersion="7.11.2")
+    void setSystemName(String systemName);
+
+    @TypedColumn(name="system_description", method=MethodType.GETCOLUMN, fromVersion="7.11.2")
+    Column<GenericTableSchema, String> getSystemDescriptionColumn();
+    @TypedColumn(name="system_description", method=MethodType.SETDATA, fromVersion="7.11.2")
+    void setSystemDescription(String systemDescription);
+
+    @TypedColumn(name="mappings", method=MethodType.GETCOLUMN, fromVersion="7.11.2")
+    Column<GenericTableSchema, Map<Long, Long>> getMappingsColumn();
+    @TypedColumn(name="mappings", method=MethodType.SETDATA, fromVersion="7.11.2")
+    void setMappings(Map<Long, Long> mappings);
+
+    // FIXME: To be uncommented when Open vSwitch supports external_ids column
+//    @TypedColumn (name="external_ids", method= MethodType.GETCOLUMN, fromVersion="7.11.2")
+//    Column<GenericTableSchema, Map<String, String>> getExternalIdsColumn();
+//    @TypedColumn (name="external_ids", method= MethodType.SETDATA, fromVersion="7.11.2")
+//    void setExternalIds(Map<String, String> externalIds);
+
+}
index 5fd912dadf626ad08f83241b233015c58762336e..d7f74f3d27c016450f7d0515b7cba47574ffeaf8 100644 (file)
@@ -129,4 +129,9 @@ public interface Bridge extends TypedBaseTable<GenericTableSchema> {
     @TypedColumn(name="flow_tables", method=MethodType.SETDATA, fromVersion="6.5.0")
     void setFlowTables(Map<Long, UUID> flowTables);
 
+    @TypedColumn(name="auto_attach", method=MethodType.GETCOLUMN, fromVersion="7.11.2")
+    Column<GenericTableSchema, Set<UUID>> getAutoAttachColumn();
+
+    @TypedColumn(name="auto_attach", method=MethodType.SETDATA, fromVersion="7.11.2")
+    void setAutoAttach(Set<UUID> autoAttach);
 }
index 0b1ee591f0e802b350f0a0ac2bd4e0b924fe28b1..cc4b4920ad366892b65bdb82def59ac9e0ac3950 100755 (executable)
@@ -629,6 +629,10 @@ module ovsdb {
                 description "An identifier used for AutoAttach table in the MD-SAL.";
                 type inet:uri;
             }
+            leaf bridge-id {
+                description "Node-id of the Bridge table from where Autoattach table can be referenced.";
+                type inet:uri;
+            }
             leaf autoattach-uuid {
                 description "The unique identifier of the autoattach table.";
                 type yang:uuid;
@@ -659,6 +663,23 @@ module ovsdb {
                     }
                 }
             }
+            list autoattach-external-ids {
+                description
+                   "Key-value pairs for use by external frameworks that integrate with
+                    Open vSwitch, rather than by Open vSwitch itself.";
+
+                key "autoattach-external-id-key";
+                leaf autoattach-external-id-key {
+                    description "external-id name/key";
+                    type string;
+                    mandatory true;
+                }
+                leaf autoattach-external-id-value {
+                    description "autoattach-external-id value";
+                    type string;
+                    mandatory true;
+                }
+            }
         }
      }
 
index 1e227c5e73a7d710178d5c2ea428b64b3bd0b1d5..a91b8c982914d2b4e9f5b227664eb830b9bb2d8d 100644 (file)
@@ -28,7 +28,8 @@ public class OvsdbSchemaContants {
         MIRROR("Mirror", "Bridge", "mirrors"),
         MANAGER("Manager", "Open_vSwitch", "manager_options"),
         CONTROLLER("Controller", "Bridge", "controller"),
-        FLOWSAMPLECOLLECTORSET("Flow_Sample_Collector_Set",null,null);
+        FLOWSAMPLECOLLECTORSET("Flow_Sample_Collector_Set",null,null),
+        AUTOATTACH("AutoAttach", "Bridge", "auto_attach");
 
         private final String tableName;
         private final String parentTableName;
index d577ed46b33d2444126e9e4dce02a3da71d89f7c..7bc8d7bb0afb6c16e6d3d0dde3b284c74c3886a5 100755 (executable)
@@ -53,6 +53,7 @@ public class SouthboundConstants {
     public static final String TP_URI_PREFIX = "terminationpoint";
     public static final String QOS_URI_PREFIX = "qos";
     public static final String QUEUE_URI_PREFIX = "queue";
+    public static final String AUTOATTACH_URI_PREFIX = "autoattach";
     public static final Integer DEFAULT_OVSDB_PORT = 6640;
     public static final String DEFAULT_OPENFLOW_PORT = "6653";
     public static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
@@ -109,6 +110,7 @@ public class SouthboundConstants {
     public static final String IID_EXTERNAL_ID_KEY = "opendaylight-iid";
     public static final String QOS_ID_EXTERNAL_ID_KEY = "opendaylight-qos-id";
     public static final String QUEUE_ID_EXTERNAL_ID_KEY = "opendaylight-queue-id";
+    public static final String AUTOATTACH_ID_EXTERNAL_ID_KEY = "opendaylight-autoattach-id";
 
     public enum VLANMODES {
         ACCESS("access"),
diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachRemovedCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachRemovedCommand.java
new file mode 100644 (file)
index 0000000..5684b13
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.southbound.ovsdb.transact;
+
+import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.lib.notation.Mutator;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.ovsdb.schema.openvswitch.AutoAttach;
+import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
+import org.opendaylight.ovsdb.southbound.SouthboundProvider;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+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.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Autoattach;
+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.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;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+
+public class AutoAttachRemovedCommand extends AbstractTransactCommand {
+    private static final Logger LOG = LoggerFactory.getLogger(AutoAttachRemovedCommand.class);
+
+    public AutoAttachRemovedCommand(BridgeOperationalState state,
+            AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+        super(state, changes);
+    }
+
+    @Override
+    public void execute(TransactionBuilder transaction) {
+
+        // FIXME: Remove if loop after ovs community supports external_ids column in AutoAttach Table
+        if (true) {
+            try {
+                throw new UnsupportedOperationException("CRUD operations not supported from ODL for auto_attach column for"
+                        + " this version of ovsdb schema due to missing external_ids column");
+            } catch (UnsupportedOperationException e) {
+                LOG.debug(e.getMessage());
+            }
+            return;
+        }
+
+        @SuppressWarnings("unused")
+        Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> original =
+        TransactUtils.extractOriginal(getChanges(), OvsdbNodeAugmentation.class);
+
+        Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> deleted =
+                TransactUtils.extractUpdated(getChanges(), OvsdbNodeAugmentation.class);
+
+        for (Map.Entry<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> originalEntry : original.entrySet()) {
+            InstanceIdentifier<OvsdbNodeAugmentation> ovsdbNodeIid = originalEntry.getKey();
+            OvsdbNodeAugmentation ovsdbNodeAugmentation = originalEntry.getValue();
+            OvsdbNodeAugmentation deletedOvsdbNodeAugmentation = deleted.get(ovsdbNodeIid);
+
+            if (ovsdbNodeAugmentation != null && deletedOvsdbNodeAugmentation != null) {
+                List<Autoattach> origAutoattachList = ovsdbNodeAugmentation.getAutoattach();
+                List<Autoattach> deletedAutoattachList = deletedOvsdbNodeAugmentation.getAutoattach();
+                if(origAutoattachList != null && !origAutoattachList.isEmpty() &&
+                        (deletedAutoattachList == null || deletedAutoattachList.isEmpty())) {
+
+                    OvsdbNodeAugmentation currentOvsdbNode =
+                            getOperationalState().getBridgeNode(ovsdbNodeIid).get().getAugmentation(OvsdbNodeAugmentation.class);
+                    List<Autoattach> currentAutoAttach = currentOvsdbNode.getAutoattach();
+                    for (Autoattach origAutoattach : origAutoattachList) {
+                        Uri autoAttachId = origAutoattach.getAutoattachId();
+                        deleteAutoAttach(transaction, ovsdbNodeIid, getAutoAttachUuid(currentAutoAttach, autoAttachId));
+                    }
+                }
+            }
+        }
+    }
+
+    private void deleteAutoAttach(TransactionBuilder transaction,
+            InstanceIdentifier<OvsdbNodeAugmentation> ovsdbNodeIid,
+            Uuid autoattachUuid) {
+
+        LOG.debug("Received request to delete Autoattach entry {}", autoattachUuid);
+        OvsdbBridgeAugmentation bridgeAugmentation = getBridge(ovsdbNodeIid, autoattachUuid);
+        if (autoattachUuid != null && bridgeAugmentation != null) {
+            UUID uuid = new UUID(autoattachUuid.getValue());
+            AutoAttach autoattach = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), AutoAttach.class, null);
+            transaction.add(op.delete(autoattach.getSchema())
+                    .where(autoattach.getUuidColumn().getSchema().opEqual(uuid))
+                    .build());
+            transaction.add(op.comment("AutoAttach: Deleting {} " + uuid
+                    + " attached to " + bridgeAugmentation.getBridgeName().getValue()));
+
+            Bridge bridge = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
+                    Bridge.class,null);
+
+            transaction.add(op.mutate(bridge.getSchema())
+                    .addMutation(bridge.getAutoAttachColumn().getSchema(),
+                            Mutator.DELETE, Sets.newHashSet(uuid))
+                    .where(bridge.getNameColumn().getSchema()
+                            .opEqual(bridgeAugmentation.getBridgeName().getValue())).build());
+
+            transaction.add(op.comment("Bridge: Mutating " + bridgeAugmentation.getBridgeName().getValue()
+                    + " to remove autoattach column " + uuid));
+        } else {
+            LOG.debug("Unable to delete AutoAttach {} for node {} because it was not found in the operational store, "
+                    + "and thus we cannot retrieve its UUID", autoattachUuid, ovsdbNodeIid);
+        }
+    }
+
+    private Uuid getAutoAttachUuid(List<Autoattach> currentAutoAttach, Uri autoAttachId) {
+        if (currentAutoAttach != null && !currentAutoAttach.isEmpty()) {
+            for (Autoattach autoAttach : currentAutoAttach) {
+                if (autoAttach.getAutoattachId().equals(autoAttachId)) {
+                    return autoAttach.getAutoattachUuid();
+                }
+            }
+        }
+        return null;
+    }
+
+    private OvsdbBridgeAugmentation getBridge(InstanceIdentifier<OvsdbNodeAugmentation> key, Uuid aaUuid) {
+        Preconditions.checkNotNull(aaUuid);
+        OvsdbBridgeAugmentation bridge = null;
+        InstanceIdentifier<Node> nodeIid = key.firstIdentifierOf(Node.class);
+        try (ReadOnlyTransaction transaction = SouthboundProvider.getDb().newReadOnlyTransaction()) {
+            Optional<Node> nodeOptional = transaction.read(LogicalDatastoreType.OPERATIONAL, nodeIid).get();
+            if (nodeOptional.isPresent()) {
+                List<ManagedNodeEntry> managedNodes = nodeOptional.get().getAugmentation(OvsdbNodeAugmentation.class).getManagedNodeEntry();
+                for (ManagedNodeEntry managedNode : managedNodes) {
+                    OvsdbBridgeRef ovsdbBridgeRef = managedNode.getBridgeRef();
+                    InstanceIdentifier<OvsdbBridgeAugmentation> brIid = ovsdbBridgeRef.getValue()
+                            .firstIdentifierOf(Node.class).augmentation(OvsdbBridgeAugmentation.class);
+                    Optional<OvsdbBridgeAugmentation> optionalBridge = transaction.read(LogicalDatastoreType.OPERATIONAL, brIid).get();
+                    bridge = optionalBridge.orNull();
+                    if(bridge != null && bridge.getAutoAttach() != null
+                            && bridge.getAutoAttach().equals(aaUuid)) {
+                        return bridge;
+                    }
+                }
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.warn("Error reading from datastore",e);
+        }
+        return null;
+    }
+}
diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachUpdateCommand.java
new file mode 100644 (file)
index 0000000..bcede11
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.southbound.ovsdb.transact;
+
+import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.ovsdb.lib.notation.Mutator;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.ovsdb.schema.openvswitch.AutoAttach;
+import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
+import org.opendaylight.ovsdb.southbound.SouthboundConstants;
+import org.opendaylight.ovsdb.southbound.SouthboundMapper;
+import org.opendaylight.ovsdb.southbound.SouthboundProvider;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+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.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Autoattach;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.AutoattachExternalIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.Mappings;
+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.NodeId;
+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.TopologyKey;
+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.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.collect.ImmutableMap;
+import com.google.common.collect.Sets;
+
+public class AutoAttachUpdateCommand extends AbstractTransactCommand {
+    private static final Logger LOG = LoggerFactory.getLogger(AutoAttachUpdateCommand.class);
+
+    public AutoAttachUpdateCommand(BridgeOperationalState state, AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+        super(state, changes);
+    }
+
+    @Override
+    public void execute(TransactionBuilder transaction) {
+
+        // FIXME: Fix if loop after ovs community supports external_ids column in AutoAttach Table
+        if (true) {
+            try {
+                throw new UnsupportedOperationException("CRUD operations not supported from ODL for auto_attach column for"
+                        + " this version of ovsdb schema due to missing external_ids column");
+            } catch (UnsupportedOperationException e) {
+                LOG.debug(e.getMessage());
+            }
+            return;
+        }
+
+        @SuppressWarnings("unused")
+        Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> createdOrUpdated =
+        TransactUtils.extractCreatedOrUpdated(getChanges(), OvsdbNodeAugmentation.class);
+        for (Entry<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> ovsdbNodeEntry
+                : createdOrUpdated.entrySet()) {
+            updateAutoAttach(transaction, ovsdbNodeEntry.getKey(), ovsdbNodeEntry.getValue());
+        }
+    }
+
+    private void updateAutoAttach(TransactionBuilder transaction,
+            InstanceIdentifier<OvsdbNodeAugmentation> iid,
+            OvsdbNodeAugmentation ovsdbNode) {
+
+        List<Autoattach> autoAttachList = ovsdbNode.getAutoattach();
+        if (!getOperationalState().getBridgeNode(iid).isPresent()) {
+            return;
+        }
+        OvsdbNodeAugmentation currentOvsdbNode = getOperationalState().getBridgeNode(iid).get().getAugmentation(OvsdbNodeAugmentation.class);
+        List<Autoattach> currentAutoAttach = currentOvsdbNode.getAutoattach();
+
+        if (autoAttachList != null) {
+            for (Autoattach autoAttach : autoAttachList) {
+                AutoAttach autoAttachWrapper = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), AutoAttach.class);
+                if (autoAttach.getSystemName() != null) {
+                    autoAttachWrapper.setSystemName(autoAttach.getSystemName());
+                }
+                if (autoAttach.getSystemDescription() != null) {
+                    autoAttachWrapper.setSystemDescription(autoAttach.getSystemDescription());
+                }
+
+                List<Mappings> mappingsList = autoAttach.getMappings();
+                if (mappingsList != null && !mappingsList.isEmpty()) {
+                    Map<Long, Long> newMappings = new HashMap<>();
+                    for (Mappings mappings : mappingsList) {
+                        Long mappingsValue = new Long(mappings.getMappingsValue().toString());
+                        newMappings.put(mappings.getMappingsKey(), mappingsValue);
+                    }
+                    autoAttachWrapper.setMappings(newMappings);
+                }
+
+                List<AutoattachExternalIds> externalIds = autoAttach.getAutoattachExternalIds();
+                Map<String, String> externalIdsMap = new HashMap<>();
+                if (externalIds != null) {
+                    for (AutoattachExternalIds externalId : externalIds) {
+                        externalIdsMap.put(externalId.getAutoattachExternalIdKey(), externalId.getAutoattachExternalIdValue());
+                    }
+                }
+                externalIdsMap.put(SouthboundConstants.AUTOATTACH_ID_EXTERNAL_ID_KEY, autoAttach.getAutoattachId().getValue());
+                // FIXME: To be uncommented when Open vSwitch supports external_ids column
+//                try {
+//                    autoAttachWrapper.setExternalIds(ImmutableMap.copyOf(externalIdsMap));
+//                } catch (NullPointerException e) {
+//                    LOG.warn("Incomplete AutoAttach external IDs");
+//                }
+
+                Uuid aaUuid = getAutoAttachUuid(currentAutoAttach, autoAttach.getAutoattachId());
+                if (aaUuid != null) {
+                    UUID uuid = new UUID(aaUuid.getValue());
+                    AutoAttach newAutoAttach = TyperUtils.getTypedRowWrapper(
+                            transaction.getDatabaseSchema(), AutoAttach.class, null);
+                    newAutoAttach.getUuidColumn().setData(uuid);
+                    LOG.trace("Updating autoattach table entries {}", uuid);
+                    transaction.add(op.update(autoAttachWrapper)
+                            .where(newAutoAttach.getUuidColumn().getSchema().opEqual(uuid)).build());
+                    transaction.add(op.comment("Updating AutoAttach table: " + uuid));
+                } else {
+                    Uri bridgeUri = autoAttach.getBridgeId();
+                    String namedUuid = SouthboundMapper.getRandomUUID();
+                    Bridge bridge = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), Bridge.class);
+                    transaction.add(op.insert(autoAttachWrapper).withId(namedUuid));
+                    OvsdbBridgeAugmentation ovsdbBridgeAugmentation = getBridge(iid, bridgeUri);
+                    if (ovsdbBridgeAugmentation != null) {
+                        bridge.setName(ovsdbBridgeAugmentation.getBridgeName().getValue());
+                        bridge.setAutoAttach(Sets.newHashSet(new UUID(namedUuid)));
+                        LOG.trace("Create Autoattach table {}, "
+                                + "and mutate the bridge {}", autoAttach.getAutoattachId(), getBridge(iid, bridgeUri).getBridgeName().getValue());
+                        transaction.add(op.mutate(bridge)
+                                .addMutation(bridge.getAutoAttachColumn().getSchema(),
+                                        Mutator.INSERT,bridge.getAutoAttachColumn().getData())
+                                .where(bridge.getNameColumn().getSchema()
+                                        .opEqual(bridge.getNameColumn().getData())).build());
+                        transaction.add(op.comment("Bridge: Mutating " + ovsdbBridgeAugmentation.getBridgeName().getValue()
+                                + " to add autoattach column " + namedUuid));
+                    }
+                }
+            }
+        }
+    }
+
+    private OvsdbBridgeAugmentation getBridge(InstanceIdentifier<OvsdbNodeAugmentation> key,
+            Uri bridgeUri) {
+        InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid = InstanceIdentifier
+                .create(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
+                .child(Node.class, new NodeKey(new NodeId(bridgeUri)))
+                .augmentation(OvsdbBridgeAugmentation.class);
+
+        OvsdbBridgeAugmentation bridge = null;
+        try (ReadOnlyTransaction transaction = SouthboundProvider.getDb().newReadOnlyTransaction()) {
+            Optional<OvsdbBridgeAugmentation> bridgeOptional = transaction.read(LogicalDatastoreType.OPERATIONAL, bridgeIid).get();
+            if (bridgeOptional.isPresent()) {
+                bridge = bridgeOptional.get();
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.warn("Error reading from datastore", e);
+        }
+        return bridge;
+    }
+
+    private Uuid getAutoAttachUuid(List<Autoattach> currentAutoAttach, Uri autoattachId) {
+        if (currentAutoAttach != null && !currentAutoAttach.isEmpty()) {
+            for (Autoattach autoAttach : currentAutoAttach) {
+                if (autoAttach.getAutoattachId().equals(autoattachId)) {
+                    return autoAttach.getAutoattachUuid();
+                }
+            }
+        }
+        return null;
+    }
+}
index 70e6f58693a1c22f168b69eec5847be7d647deec..1bd9790c894c3d49274e4f8bfdb1f1e83a3e90cd 100644 (file)
@@ -35,6 +35,8 @@ public class TransactCommandAggregator implements TransactCommand {
         commands.add(new TerminationPointCreateCommand(state,changes));
         commands.add(new TerminationPointDeleteCommand(state, changes));
         commands.add(new OvsdbNodeUpdateCommand(changes));
+        commands.add(new AutoAttachUpdateCommand(state, changes));
+        commands.add(new AutoAttachRemovedCommand(state, changes));
         commands.add(new QosUpdateCommand(state, changes));
         commands.add(new QosRemovedCommand(state, changes));
         commands.add(new QueueUpdateCommand(state, changes));
diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbAutoAttachRemovedCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbAutoAttachRemovedCommand.java
new file mode 100644 (file)
index 0000000..c872279
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.southbound.transactions.md;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.lib.message.TableUpdates;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.ovsdb.schema.openvswitch.AutoAttach;
+import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
+import org.opendaylight.ovsdb.southbound.SouthboundMapper;
+import org.opendaylight.ovsdb.southbound.SouthboundUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+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.ovsdb.node.attributes.Autoattach;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.AutoattachKey;
+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;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class OvsdbAutoAttachRemovedCommand extends AbstractTransactionCommand {
+    private static final Logger LOG = LoggerFactory.getLogger(OvsdbQueueUpdateCommand.class);
+
+    private Map<UUID, AutoAttach> removedAutoAttachRows;
+
+    public OvsdbAutoAttachRemovedCommand(OvsdbConnectionInstance key,
+            TableUpdates updates, DatabaseSchema dbSchema) {
+        super(key, updates, dbSchema);
+        removedAutoAttachRows = TyperUtils.extractRowsRemoved(AutoAttach.class, getUpdates(), getDbSchema());
+    }
+
+    @Override
+    public void execute(ReadWriteTransaction transaction) {
+        final InstanceIdentifier<Node> nodeIId = getOvsdbConnectionInstance().getInstanceIdentifier();
+        final Optional<Node> ovsdbNode = SouthboundUtil.readNode(transaction, nodeIId);
+        if (ovsdbNode.isPresent() && removedAutoAttachRows != null && !removedAutoAttachRows.isEmpty()) {
+            InstanceIdentifier<Node> ovsdbNodeIid =
+                    SouthboundMapper.createInstanceIdentifier(getOvsdbConnectionInstance().getNodeId());
+            // FIXME: Iterate on external_ids instead of uuid when Open vSwitch supports external_ids column
+            for (UUID autoAttachUuid : removedAutoAttachRows.keySet()) {
+                AutoattachKey autoAttachKey = getAutoAttachKeyToRemove(ovsdbNode.get(), autoAttachUuid);
+                if (autoAttachKey != null) {
+                    InstanceIdentifier<Autoattach> iid = ovsdbNodeIid
+                            .augmentation(OvsdbNodeAugmentation.class)
+                            .child(Autoattach.class, autoAttachKey);
+                    transaction.delete(LogicalDatastoreType.OPERATIONAL, iid);
+                    LOG.debug("AutoAttach table {} for Ovsdb Node {} is deleted", autoAttachUuid.toString(),
+                            ovsdbNode.get().getNodeId());
+                } else {
+                    LOG.warn("AutoAttach table {} not found for Ovsdb Node {} to delete", autoAttachUuid.toString(),
+                            ovsdbNode.get().getNodeId());
+                }
+            }
+        }
+    }
+
+    private AutoattachKey getAutoAttachKeyToRemove(Node node, UUID autoAttachUuid) {
+        List<Autoattach> autoAttachList = node.getAugmentation(OvsdbNodeAugmentation.class).getAutoattach();
+        if (autoAttachList == null || autoAttachList.isEmpty()) {
+            return null;
+        }
+        for (Autoattach autoAttach : autoAttachList) {
+            if (autoAttach.getAutoattachUuid()
+                    .equals(new Uuid(autoAttachUuid.toString()))) {
+                return autoAttach.getKey();
+            }
+        }
+        return null;
+    }
+}
diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbAutoAttachUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbAutoAttachUpdateCommand.java
new file mode 100644 (file)
index 0000000..e41c4be
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.southbound.transactions.md;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.lib.message.TableUpdates;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.ovsdb.schema.openvswitch.AutoAttach;
+import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
+import org.opendaylight.ovsdb.southbound.SouthboundConstants;
+import org.opendaylight.ovsdb.southbound.SouthboundUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+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.ovsdb.node.attributes.Autoattach;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.AutoattachBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.AutoattachKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.AutoattachExternalIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.AutoattachExternalIdsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.Mappings;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.MappingsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.MappingsKey;
+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;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class OvsdbAutoAttachUpdateCommand extends AbstractTransactionCommand {
+    private static final Logger LOG = LoggerFactory.getLogger(OvsdbAutoAttachUpdateCommand.class);
+
+    private Map<UUID, AutoAttach> updatedAutoAttachRows;
+    private Map<UUID, AutoAttach> oldAutoAttachRows;
+
+    public OvsdbAutoAttachUpdateCommand(OvsdbConnectionInstance key,
+            TableUpdates updates, DatabaseSchema dbSchema) {
+        super(key, updates, dbSchema);
+        updatedAutoAttachRows = TyperUtils.extractRowsUpdated(AutoAttach.class,getUpdates(), getDbSchema());
+        oldAutoAttachRows = TyperUtils.extractRowsOld(AutoAttach.class, getUpdates(), getDbSchema());
+    }
+
+    @Override
+    public void execute(ReadWriteTransaction transaction) {
+        if (updatedAutoAttachRows != null && !updatedAutoAttachRows.isEmpty()) {
+            updateAutoAttach(transaction, updatedAutoAttachRows);
+        }
+    }
+
+    private void updateAutoAttach(ReadWriteTransaction transaction,
+            Map<UUID, AutoAttach> updatedAutoAttachRows) {
+
+        final InstanceIdentifier<Node> nodeIId = getOvsdbConnectionInstance().getInstanceIdentifier();
+        final Optional<Node> ovsdbNode = SouthboundUtil.readNode(transaction, nodeIId);
+        if (ovsdbNode.isPresent()) {
+            for (Entry<UUID, AutoAttach> entry : updatedAutoAttachRows.entrySet()) {
+                AutoAttach autoAttach = entry.getValue();
+                AutoAttach oldAutoAttach = oldAutoAttachRows.get(entry.getKey());
+                Uri uri = new Uri(SouthboundConstants.AUTOATTACH_URI_PREFIX + "://" + autoAttach.getUuid().toString());
+
+                // FIXME: To be uncommented when Open vSwitch supports external_ids column
+//                Uri uri = new Uri(getAutoAttachId(autoAttach));
+
+                Autoattach currentAutoattach = null;
+                try {
+                    InstanceIdentifier<Autoattach> currentIid = nodeIId
+                            .augmentation(OvsdbNodeAugmentation.class)
+                            .child(Autoattach.class, new AutoattachKey(new Uri(oldAutoAttach
+                                    .getUuidColumn().getData().toString())));
+                    // FIXME: To be uncommented and replaced to currentIid when Open vSwitch supports external_ids column
+//                    InstanceIdentifier<Autoattach> currentIid = nodeIId
+//                            .augmentation(OvsdbNodeAugmentation.class)
+//                            .child(Autoattach.class, new AutoattachKey(new Uri(oldAutoAttach
+//                                    .getExternalIdsColumn().getData()
+//                                    .get(SouthboundConstants.AUTOATTACH_ID_EXTERNAL_ID_KEY))));
+                    Optional<Autoattach> optionalAutoattach =
+                            transaction.read(LogicalDatastoreType.OPERATIONAL, currentIid).checkedGet();
+                    if (optionalAutoattach.isPresent()) {
+                        currentAutoattach = optionalAutoattach.get();
+                    }
+                } catch (Exception e) {
+                    LOG.warn("AutoAttach table entries not found in operational datastore, need to create it.", e);
+                }
+
+                AutoattachBuilder autoAttachBuilder = (currentAutoattach != null) ? new AutoattachBuilder(currentAutoattach)
+                        : new AutoattachBuilder()
+                        .setAutoattachUuid(new Uuid(entry.getKey().toString()))
+                        .setAutoattachId(uri)
+                        .setKey(new AutoattachKey(uri));
+
+                if (autoAttach.getSystemNameColumn() != null
+                        && autoAttach.getSystemNameColumn().getData() != null
+                        && !autoAttach.getSystemNameColumn().getData().isEmpty()) {
+                    autoAttachBuilder.setSystemName(autoAttach.getSystemNameColumn().getData());
+                }
+                if (autoAttach.getSystemDescriptionColumn() != null
+                        && autoAttach.getSystemDescriptionColumn().getData() != null
+                        && !autoAttach.getSystemDescriptionColumn().getData().isEmpty()) {
+                    autoAttachBuilder.setSystemDescription(autoAttach.getSystemDescriptionColumn().getData());
+                }
+                if (autoAttach.getMappingsColumn() != null
+                        && autoAttach.getMappingsColumn().getData() != null
+                        && !autoAttach.getMappingsColumn().getData().isEmpty()) {
+                    setMappings(autoAttachBuilder, autoAttach);
+                }
+                // FIXME: To be uncommented when Open vSwitch supports external_ids column
+//                setExternalIds(autoAttachBuilder, autoAttach);
+
+                Autoattach autoAttachEntry = autoAttachBuilder.build();
+                LOG.trace("Update Ovsdb Node {} with AutoAttach table entries {}",
+                        ovsdbNode.get().getNodeId(), autoAttachEntry);
+                InstanceIdentifier<Autoattach> iid = nodeIId
+                        .augmentation(OvsdbNodeAugmentation.class)
+                        .child(Autoattach.class, autoAttachEntry.getKey());
+                transaction.put(LogicalDatastoreType.OPERATIONAL,
+                        iid, autoAttachEntry);
+            }
+        }
+    }
+
+    private void setMappings (AutoattachBuilder autoAttachBuilder,
+            AutoAttach autoAttach) {
+        Map<Long, Long> mappings = autoAttach.getMappingsColumn().getData();
+        Set<Long> mappingsKeys = mappings.keySet();
+        List<Mappings> mappingsList = new ArrayList<>();
+        for (Long mappingsKey : mappingsKeys) {
+            Integer mappingsValue = new Integer(mappings.get(mappingsKey).toString());
+            if (mappingsKey != null && mappingsValue != null) {
+                mappingsList.add(new MappingsBuilder()
+                        .setKey(new MappingsKey(mappingsKey))
+                        .setMappingsKey(mappingsKey)
+                        .setMappingsValue(mappingsValue)
+                        .build());
+            }
+            autoAttachBuilder.setMappings(mappingsList);
+        }
+    }
+
+    // FIXME: To be uncommented when Open vSwitch supports external_ids column
+//    private String getAutoAttachId(AutoAttach autoAttach) {
+//        if (autoAttach.getExternalIdsColumn() != null
+//                && autoAttach.getExternalIdsColumn().getData() != null
+//                && autoAttach.getExternalIdsColumn().getData().containsKey(SouthboundConstants.AUTOATTACH_ID_EXTERNAL_ID_KEY)) {
+//            return autoAttach.getExternalIdsColumn().getData().get(SouthboundConstants.AUTOATTACH_ID_EXTERNAL_ID_KEY);
+//        } else {
+//            return SouthboundConstants.AUTOATTACH_URI_PREFIX + "://" + autoAttach.getUuid().toString();
+//        }
+//    }
+//
+//    private void setExternalIds(AutoattachBuilder autoAttachBuilder,
+//            AutoAttach autoAttach) {
+//        List<AutoattachExternalIds> externalIdsList = new ArrayList<>();
+//        if (autoAttach.getExternalIdsColumn() != null
+//                && autoAttach.getExternalIdsColumn().getData() != null
+//                && !autoAttach.getExternalIdsColumn().getData().isEmpty()) {
+//            Map<String, String> externalIds = autoAttach.getExternalIdsColumn().getData();
+//            Set<String> externalIdsKeys = externalIds.keySet();
+//
+//            String extIdValue;
+//            for (String extIdKey : externalIdsKeys) {
+//                extIdValue = externalIds.get(extIdKey);
+//                if (extIdKey != null && extIdValue != null) {
+//                    externalIdsList.add(new AutoattachExternalIdsBuilder().setAutoattachExternalIdKey(extIdKey)
+//                            .setAutoattachExternalIdValue(extIdValue).build());
+//                }
+//            }
+//        } else {
+//            externalIdsList.add(new AutoattachExternalIdsBuilder().setAutoattachExternalIdKey(SouthboundConstants.AUTOATTACH_ID_EXTERNAL_ID_KEY)
+//                    .setAutoattachExternalIdValue(autoAttach.getUuid().toString()).build());
+//        }
+//        autoAttachBuilder.setAutoattachExternalIds(externalIdsList);
+//    }
+}
index 9ab33b7681d3f715d2ec2b2cdb40b3007b75db47..269da04abe1676057f070d5f8a6b5a7582405af8 100644 (file)
@@ -228,6 +228,7 @@ public class OvsdbBridgeUpdateCommand extends AbstractTransactionCommand {
         setFailMode(ovsdbBridgeAugmentationBuilder, bridge);
         setOpenFlowNodeRef(ovsdbBridgeAugmentationBuilder, bridge);
         setManagedBy(ovsdbBridgeAugmentationBuilder);
+        setAutoAttach(ovsdbBridgeAugmentationBuilder, bridge);
         bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
 
         LOG.debug("Built with the intent to store bridge data {}",
@@ -235,6 +236,22 @@ public class OvsdbBridgeUpdateCommand extends AbstractTransactionCommand {
         return bridgeNodeBuilder.build();
     }
 
+    private void setAutoAttach(OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
+            Bridge bridge) {
+        try {
+            if (bridge.getAutoAttachColumn() != null
+                    && bridge.getAutoAttachColumn().getData() != null
+                    && !bridge.getAutoAttachColumn().getData().isEmpty()) {
+                Set<UUID> uuids = bridge.getAutoAttachColumn().getData();
+                for (UUID uuid : uuids) {
+                    ovsdbBridgeAugmentationBuilder.setAutoAttach(new Uuid(uuid.toString()));
+                }
+            }
+        } catch (SchemaVersionMismatchException e) {
+            LOG.debug("auto_attach column for Bridge Table unsupported for this version of ovsdb schema. {}", e);
+        }
+    }
+
     private void setManagedBy(OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder) {
         InstanceIdentifier<Node> connectionNodePath = getOvsdbConnectionInstance().getInstanceIdentifier();
         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
index 09564bfb7113e60aad68dfbaa05b06457167b78e..b0fab07b20b4bb27ce617e9fa014c08cccd1c4b0 100644 (file)
@@ -36,6 +36,8 @@ public class OvsdbOperationalCommandAggregator implements TransactionCommand {
         commands.add(new OvsdbControllerRemovedCommand(key, updates,  dbSchema));
         commands.add(new OvsdbPortUpdateCommand(key, updates, dbSchema));
         commands.add(new OvsdbPortRemoveCommand(key, updates, dbSchema));
+        commands.add(new OvsdbAutoAttachUpdateCommand(key, updates, dbSchema));
+        commands.add(new OvsdbAutoAttachRemovedCommand(key, updates, dbSchema));
     }
 
     @Override
index 918b33c7ec1a74629c691d024a3735ee23639317..414c6bb1dbb8866cca6dce80dcdf45b7ea7bca17 100644 (file)
@@ -35,7 +35,7 @@ import org.powermock.reflect.Whitebox;
 @PrepareForTest({})
 @RunWith(PowerMockRunner.class)
 public class TransactCommandAggregatorTest {
-    private static final int NUMBER_OF_COMMANDS = 15;
+    private static final int NUMBER_OF_COMMANDS = 17;
     private List<TransactCommand> commands = new ArrayList<>();
     private TransactCommandAggregator transactCommandAggregator;
     @Mock private AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes;
@@ -56,6 +56,8 @@ public class TransactCommandAggregatorTest {
         commands.add(mock(TerminationPointCreateCommand.class));
         commands.add(mock(TerminationPointDeleteCommand.class));
         commands.add(mock(OvsdbNodeUpdateCommand.class));
+        commands.add(mock(AutoAttachUpdateCommand.class));
+        commands.add(mock(AutoAttachRemovedCommand.class));
         commands.add(mock(QosUpdateCommand.class));
         commands.add(mock(QosRemovedCommand.class));
         commands.add(mock(QueueUpdateCommand.class));
diff --git a/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbAutoAttachRemovedCommandTest.java b/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbAutoAttachRemovedCommandTest.java
new file mode 100644 (file)
index 0000000..021ca96
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.southbound.transactions.md;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.schema.openvswitch.AutoAttach;
+import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
+import org.opendaylight.ovsdb.southbound.SouthboundConstants;
+import org.opendaylight.ovsdb.southbound.SouthboundMapper;
+import org.opendaylight.ovsdb.southbound.SouthboundUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+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.ovsdb.node.attributes.Autoattach;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.AutoattachKey;
+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.NodeId;
+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.TopologyKey;
+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.yang.binding.InstanceIdentifier;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.api.support.membermodification.MemberModifier;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.google.common.base.Optional;
+
+@PrepareForTest({OvsdbAutoAttachRemovedCommand.class, SouthboundMapper.class, SouthboundUtil.class})
+@RunWith(PowerMockRunner.class)
+public class OvsdbAutoAttachRemovedCommandTest {
+
+    private Map<UUID, AutoAttach> removedAutoAttachRows = new HashMap<>();
+    private OvsdbAutoAttachRemovedCommand ovsdbAutoAttachRemovedCommand;
+    private ReadWriteTransaction transaction;
+    private InstanceIdentifier<Autoattach> aaIid;
+
+    private static final UUID AUTOATTACH_UUID = new UUID("798f35d8-f40a-449a-94d3-c860f5547f9a");
+    private static final String CONNECTED_NODE_ID = "10.0.0.1";
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public void setUp() throws Exception {
+        ovsdbAutoAttachRemovedCommand = mock(OvsdbAutoAttachRemovedCommand.class, Mockito.CALLS_REAL_METHODS);
+
+        AutoAttach autoAttach = mock(AutoAttach.class);
+        removedAutoAttachRows.put(AUTOATTACH_UUID, autoAttach);
+        MemberModifier.field(OvsdbAutoAttachRemovedCommand.class, "removedAutoAttachRows").set(ovsdbAutoAttachRemovedCommand, removedAutoAttachRows);
+
+        OvsdbConnectionInstance ovsdbConnectionInstance = mock(OvsdbConnectionInstance.class);
+        when(ovsdbAutoAttachRemovedCommand.getOvsdbConnectionInstance()).thenReturn(ovsdbConnectionInstance);
+        AutoattachKey aaKey = new AutoattachKey(new Uri(SouthboundConstants.AUTOATTACH_URI_PREFIX + "://" + AUTOATTACH_UUID.toString()));
+        aaIid = InstanceIdentifier.create(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
+                .child(Node.class, new NodeKey(new NodeId(CONNECTED_NODE_ID)))
+                .augmentation(OvsdbNodeAugmentation.class)
+                .child(Autoattach.class, aaKey);
+        InstanceIdentifier<Node> nodeIid = aaIid.firstIdentifierOf(Node.class);
+        when(ovsdbConnectionInstance.getInstanceIdentifier()).thenReturn(nodeIid);
+
+        PowerMockito.mockStatic(SouthboundUtil.class);
+        Optional<Node> ovsdbNode = mock(Optional.class);
+        transaction = mock(ReadWriteTransaction.class);
+        PowerMockito.when(SouthboundUtil.readNode(transaction, nodeIid)).thenReturn(ovsdbNode);
+        when(ovsdbNode.isPresent()).thenReturn(true);
+        Node node = mock(Node.class);
+        when(ovsdbNode.get()).thenReturn(node);
+        NodeId nodeId = mock(NodeId.class);
+        when(node.getNodeId()).thenReturn(nodeId);
+
+        PowerMockito.mockStatic(SouthboundMapper.class);
+        when(ovsdbConnectionInstance.getNodeId()).thenReturn(nodeId);
+        when(SouthboundMapper.createInstanceIdentifier(nodeId)).thenReturn(nodeIid);
+
+        OvsdbNodeAugmentation ovsdbNodeAugmentation = mock(OvsdbNodeAugmentation.class);
+        when(node.getAugmentation(OvsdbNodeAugmentation.class)).thenReturn(ovsdbNodeAugmentation);
+        List<Autoattach> autoAttachList = new ArrayList<>();
+        Autoattach aaEntry = mock(Autoattach.class);
+        autoAttachList.add(aaEntry);
+        when(aaEntry.getAutoattachUuid()).thenReturn(new Uuid(AUTOATTACH_UUID.toString()));
+        when(ovsdbNodeAugmentation.getAutoattach()).thenReturn(autoAttachList);
+        when(aaEntry.getKey()).thenReturn(aaKey);
+
+        doNothing().when(transaction).delete(any(LogicalDatastoreType.class), any(InstanceIdentifier.class));
+    }
+
+    @Test
+    public void testExecute() {
+        ovsdbAutoAttachRemovedCommand.execute(transaction);
+        verify(transaction).delete(eq(LogicalDatastoreType.OPERATIONAL), eq(aaIid));
+    }
+}
diff --git a/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbAutoAttachUpdateCommandTest.java b/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbAutoAttachUpdateCommandTest.java
new file mode 100644 (file)
index 0000000..da61b64
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.southbound.transactions.md;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.lib.notation.Column;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
+import org.opendaylight.ovsdb.schema.openvswitch.AutoAttach;
+import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
+import org.opendaylight.ovsdb.southbound.SouthboundConstants;
+import org.opendaylight.ovsdb.southbound.SouthboundUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+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.ovsdb.node.attributes.Autoattach;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.AutoattachKey;
+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.NodeId;
+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.TopologyKey;
+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.yang.binding.InstanceIdentifier;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.api.support.membermodification.MemberModifier;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+
+@PrepareForTest({OvsdbAutoAttachUpdateCommand.class, SouthboundUtil.class})
+@RunWith(PowerMockRunner.class)
+public class OvsdbAutoAttachUpdateCommandTest {
+
+    private static final String AUTOATTACH_SYSTEM_INFO = "AutoAttach Test";
+    private static final Map<Long, Long> AUTOATTACH_MAPPINGS = ImmutableMap.of(100L, 200L);
+    private static final UUID AUTOATTACH_UUID = new UUID("798f35d8-f40a-449a-94d3-c860f5547f9a");
+    private static final String CONNECTED_NODE_ID = "10.0.0.2";
+    private static final Map<String, String> AUTOATTACH_EXTERNAL_IDS =
+            ImmutableMap.of("opendaylight-autoattach-id", "autoattach://798f35d8-f40a-449a-94d3-c860f5547f9a");
+    private Map<UUID, AutoAttach> updatedAutoAttachRows = new HashMap<>();
+    private Map<UUID, AutoAttach> oldAutoAttachRows = new HashMap<>();
+    private OvsdbAutoAttachUpdateCommand ovsdbAutoAttachUpdateCommand;
+    private ReadWriteTransaction transaction;
+    private InstanceIdentifier<Autoattach> aaIid;
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public void setUp() throws Exception {
+        ovsdbAutoAttachUpdateCommand = mock(OvsdbAutoAttachUpdateCommand.class, Mockito.CALLS_REAL_METHODS);
+
+        AutoAttach autoAttach = mock(AutoAttach.class);
+        updatedAutoAttachRows.put(AUTOATTACH_UUID, autoAttach);
+        oldAutoAttachRows.put(AUTOATTACH_UUID, autoAttach);
+
+        Column<GenericTableSchema, String> aaColumn = mock(Column.class);
+        when(autoAttach.getSystemNameColumn()).thenReturn(aaColumn);
+        when(autoAttach.getSystemDescriptionColumn()).thenReturn(aaColumn);
+        when(aaColumn.getData()).thenReturn(AUTOATTACH_SYSTEM_INFO);
+        Column<GenericTableSchema, Map<Long, Long>> aaMappingColumn = mock(Column.class);
+        when(autoAttach.getMappingsColumn()).thenReturn(aaMappingColumn);
+        when(aaMappingColumn.getData()).thenReturn(AUTOATTACH_MAPPINGS);
+
+        // FIXME: To be uncommented when Open vSwitch supports external_ids column
+//        Column<GenericTableSchema, Map<String, String>> aaExternalIdsColumn = mock(Column.class);
+//        when(autoAttach.getExternalIdsColumn()).thenReturn(aaExternalIdsColumn);
+//        when(aaExternalIdsColumn.getData()).thenReturn(AUTOATTACH_EXTERNAL_IDS);
+        when(autoAttach.getUuid()).thenReturn(AUTOATTACH_UUID);
+
+        OvsdbConnectionInstance ovsdbConnectionInstance = mock(OvsdbConnectionInstance.class);
+        when(ovsdbAutoAttachUpdateCommand.getOvsdbConnectionInstance()).thenReturn(ovsdbConnectionInstance);
+        aaIid = InstanceIdentifier.create(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
+                .child(Node.class, new NodeKey(new NodeId(CONNECTED_NODE_ID)))
+                .augmentation(OvsdbNodeAugmentation.class)
+                .child(Autoattach.class, new AutoattachKey
+                        (new Uri(SouthboundConstants.AUTOATTACH_URI_PREFIX + "://" + AUTOATTACH_UUID.toString())));
+        InstanceIdentifier<Node> connectionIid = aaIid.firstIdentifierOf(Node.class);
+        when(ovsdbConnectionInstance.getInstanceIdentifier()).thenReturn(connectionIid);
+        transaction = mock(ReadWriteTransaction.class);
+        doNothing().when(transaction).merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(Autoattach.class));
+        doNothing().when(transaction).delete(any(LogicalDatastoreType.class), any(InstanceIdentifier.class));
+
+        PowerMockito.mockStatic(SouthboundUtil.class);
+        Optional<Node> ovsdbNode = mock(Optional.class);
+        PowerMockito.when(SouthboundUtil.readNode(transaction, connectionIid)).thenReturn(ovsdbNode);
+        when(ovsdbNode.isPresent()).thenReturn(true);
+        Node node = mock(Node.class);
+        when(ovsdbNode.get()).thenReturn(node);
+        NodeId nodeId = mock(NodeId.class);
+        when(node.getNodeId()).thenReturn(nodeId);
+
+        MemberModifier.field(OvsdbAutoAttachUpdateCommand.class, "updatedAutoAttachRows").set(ovsdbAutoAttachUpdateCommand, updatedAutoAttachRows);
+        MemberModifier.field(OvsdbAutoAttachUpdateCommand.class, "oldAutoAttachRows").set(ovsdbAutoAttachUpdateCommand, oldAutoAttachRows);
+    }
+
+    @Test
+    public void testExecute() {
+        ovsdbAutoAttachUpdateCommand.execute(transaction);
+        verify(transaction).put(eq(LogicalDatastoreType.OPERATIONAL), eq(aaIid), any(Autoattach.class));
+    }
+}
index c3d3fd0471d3e3e1af5a9f02e6b75fe6bcf2a637..95df974f478e0503b6f7d56e2db4c2c27a3c09f8 100644 (file)
@@ -31,7 +31,7 @@ import org.powermock.reflect.Whitebox;
 @PrepareForTest({})
 @RunWith(PowerMockRunner.class)
 public class OvsdbOperationalCommandAggregatorTest {
-    private static final int NUMBER_OF_COMMANDS = 13;
+    private static final int NUMBER_OF_COMMANDS = 15;
     private List<TransactionCommand> commands = new ArrayList<>();
     private OvsdbOperationalCommandAggregator ovsdbOperationalCommandAggregator;
 
@@ -43,6 +43,8 @@ public class OvsdbOperationalCommandAggregatorTest {
         commands.add(mock(OpenVSwitchUpdateCommand.class));
         commands.add(mock(OvsdbManagersUpdateCommand.class));
         commands.add(mock(OvsdbManagersRemovedCommand.class));
+        commands.add(mock(OvsdbAutoAttachUpdateCommand.class));
+        commands.add(mock(OvsdbAutoAttachRemovedCommand.class));
         commands.add(mock(OvsdbQosUpdateCommand.class));
         commands.add(mock(OvsdbQosRemovedCommand.class));
         commands.add(mock(OvsdbQueueUpdateCommand.class));