Listen config DS then push configuration to switch 75/29575/3
authorPeng Zhang <pzhang@ctbri.com.cn>
Thu, 12 Nov 2015 03:01:04 +0000 (11:01 +0800)
committerPeng Zhang <pzhang@ctbri.com.cn>
Sun, 15 Nov 2015 13:56:19 +0000 (21:56 +0800)
Patch Set 1:
1. Add skeletal code for command pattern to push configuration to switch, function TBD.
2. Implement LogicalSwitchUpdateCommand.

Patch Set 2:
1. Fix whiteapce issues.
2. Add 'logical-switch-managed-by' for logical-switch-attribute in hwvtep.yang.
3. Use hcm.getConnetionInstance(node) added in https://git.opendaylight.org/gerrit/#/c/29599.

Patch Set 3:
1. Fix LOG severities and delete some TODOes.
2. Use HwvtepSchemaConstats.databaseName for Hwvtep database name.

Change-Id: I0fe5dafdf9ecfa91ee8c757c4b694a50e6cbed35
Signed-off-by: Peng Zhang <pzhang@ctbri.com.cn>
15 files changed:
hwvtepsouthbound/hwvtepsouthbound-api/src/main/yang/hwvtep.yang
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepConnectionInstance.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepConnectionManager.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepDataChangeListener.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepSouthboundUtil.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/AbstractTransactCommand.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/HwvtepOperationalState.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/LogicalSwitchRemoveCommand.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/LogicalSwitchUpdateCommand.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/PhysicalLocatorRemoveCommand.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/PhysicalLocatorUpdateCommand.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/PhysicalPortRemoveCommand.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/PhysicalPortUpdateCommand.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/TransactCommandAggregator.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/TransactUtils.java [new file with mode: 0644]

index 8b5bdbee1cd6cca06ac9faab6dd8e669a5d2f8c7..6244999fa1165ac50e770d3aa4c74fcf385891cc 100644 (file)
@@ -256,6 +256,10 @@ module hwvtep {
             description "Per Logical Switch tunnel key";
             type string;
         }
+        leaf logical-switch-managed-by {
+            description "The hwvtep global node to which this logical switch belongs to";
+            type hwvtep-global-ref;
+        }
     }
 
     grouping hwvtep-physical-port-attributes {
index 11b3052290425730aef2d7f7359224f982826482..7eec7e18a55ae15b2d880116f0917a54ac7d2cf9 100644 (file)
@@ -108,12 +108,9 @@ public class HwvtepConnectionInstance implements OvsdbClient{
         if (transactInvokers == null) {
             try {
                 transactInvokers = new HashMap<>();
-                List<String> databases = getDatabases().get();
-                for (String database : databases) {
-                    DatabaseSchema dbSchema = getSchema(database).get();
-                    if (dbSchema != null) {
-                        transactInvokers.put(dbSchema, new TransactInvokerImpl(this,dbSchema));
-                    }
+                DatabaseSchema dbSchema = getSchema(HwvtepSchemaConstants.databaseName).get();
+                if(dbSchema != null) {
+                    transactInvokers.put(dbSchema, new TransactInvokerImpl(this,dbSchema));
                 }
             } catch (InterruptedException | ExecutionException e) {
                 LOG.warn("Exception attempting to createTransactionInvokers {}: {}",connectionInfo,e);
index 2d4f49b7d0b5115d331cbbcd19967f1cdf827874..694542463f683326b47adf230793a1268edb2119 100644 (file)
@@ -450,5 +450,4 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
             hcm.handleOwnershipChanged(ownershipChange);
         }
     }
-
 }
index b60ad1c188d5976bca313c50762907086a966dec..bdf84e614c9fb739057221ded2e2228611133881 100644 (file)
@@ -9,9 +9,15 @@
 package org.opendaylight.ovsdb.hwvtepsouthbound;
 
 import java.net.UnknownHostException;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
@@ -19,10 +25,17 @@ import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.hwvtepsouthbound.transact.HwvtepOperationalState;
+import org.opendaylight.ovsdb.hwvtepsouthbound.transact.TransactCommandAggregator;
 import org.opendaylight.ovsdb.lib.OvsdbClient;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.ConnectionInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.ConnectionInfoBuilder;
 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;
@@ -115,21 +128,22 @@ public class HwvtepDataChangeListener implements DataTreeChangeListener<Node>, A
             Node node = getCreated(mod);
             if (node != null) {
                 HwvtepGlobalAugmentation hwvtepGlobal = node.getAugmentation(HwvtepGlobalAugmentation.class);
-                ConnectionInfo connection = hwvtepGlobal.getConnectionInfo();
-                InstanceIdentifier<Node> iid = hcm.getInstanceIdentifier(connection);
-                if (iid != null) {
-                    LOG.warn("Connection to device {} already exists. Plugin does not allow multiple connections "
-                                    + "to same device, hence dropping the request {}", connection, hwvtepGlobal);
-                } else {
-                    try {
-                        hcm.connect(HwvtepSouthboundMapper.createInstanceIdentifier(node.getNodeId()), hwvtepGlobal);
-                    } catch (UnknownHostException e) {
-                        LOG.warn("Failed to connect to OVSDB node", e);
+                if (hwvtepGlobal != null) {
+                    ConnectionInfo connection = hwvtepGlobal.getConnectionInfo();
+                    InstanceIdentifier<Node> iid = hcm.getInstanceIdentifier(connection);
+                    if (iid != null) {
+                        LOG.warn("Connection to device {} already exists. Plugin does not allow multiple connections "
+                                        + "to same device, hence dropping the request {}", connection, hwvtepGlobal);
+                    } else {
+                        try {
+                            hcm.connect(HwvtepSouthboundMapper.createInstanceIdentifier(node.getNodeId()), hwvtepGlobal);
+                        } catch (UnknownHostException e) {
+                            LOG.warn("Failed to connect to OVSDB node", e);
+                        }
                     }
                 }
             }
         }
-
     }
 
     private void updateConnections(Collection<DataTreeModification<Node>> changes) {
@@ -141,18 +155,19 @@ public class HwvtepDataChangeListener implements DataTreeChangeListener<Node>, A
                 Node original = getOriginal(mod);
                 HwvtepGlobalAugmentation hgUpdated = updated.getAugmentation(HwvtepGlobalAugmentation.class);
                 HwvtepGlobalAugmentation hgOriginal = original.getAugmentation(HwvtepGlobalAugmentation.class);
-                OvsdbClient client = hcm.getClient(hgUpdated.getConnectionInfo());
-                if (client == null) {
-                    try {
-                        hcm.disconnect(hgOriginal);
-                        hcm.connect(HwvtepSouthboundMapper.createInstanceIdentifier(original.getNodeId()), hgUpdated);
-                    } catch (UnknownHostException e) {
-                        LOG.warn("Failed to update connection on OVSDB Node", e);
+                if (hgUpdated != null && hgOriginal != null) {
+                    OvsdbClient client = hcm.getClient(hgUpdated.getConnectionInfo());
+                    if (client == null) {
+                        try {
+                            hcm.disconnect(hgOriginal);
+                            hcm.connect(HwvtepSouthboundMapper.createInstanceIdentifier(original.getNodeId()), hgUpdated);
+                        } catch (UnknownHostException e) {
+                            LOG.warn("Failed to update connection on OVSDB Node", e);
+                        }
                     }
                 }
             }
         }
-
     }
 
     private void updateData(Collection<DataTreeModification<Node>> changes) {
@@ -161,11 +176,12 @@ public class HwvtepDataChangeListener implements DataTreeChangeListener<Node>, A
          * Update data for each connection
          * Requires Command patterns. TBD.
          */
-        connectionInstancesFromChanges(changes);
-        /*for (Entry<InstanceIdentifier<Node>, HwvtepConnectionInstance> connectionInstanceEntry :
-            connectionInstancesFromChanges(changes).entrySet()) {
-            
-        }*/
+        for (Entry<HwvtepConnectionInstance, Collection<DataTreeModification<Node>>> changesEntry :
+                changesByConnectionInstance(changes).entrySet()) {
+            HwvtepConnectionInstance connectionInstance = changesEntry.getKey();
+            connectionInstance.transact(new TransactCommandAggregator(
+                new HwvtepOperationalState(db, changesEntry.getValue()),changesEntry.getValue()));
+        }
     }
 
     private void disconnect(Collection<DataTreeModification<Node>> changes) {
@@ -175,17 +191,19 @@ public class HwvtepDataChangeListener implements DataTreeChangeListener<Node>, A
             Node deleted = getRemoved(mod);
             if (deleted != null) {
                 HwvtepGlobalAugmentation hgDeleted = deleted.getAugmentation(HwvtepGlobalAugmentation.class);
-                try {
-                    hcm.disconnect(hgDeleted);
-                } catch (UnknownHostException e) {
-                    LOG.warn("Failed to disconnect OVSDB Node", e);
+                if (hgDeleted != null) {
+                    try {
+                        hcm.disconnect(hgDeleted);
+                    } catch (UnknownHostException e) {
+                        LOG.warn("Failed to disconnect OVSDB Node", e);
+                    }
                 }
             }
         }
     }
 
     private Node getCreated(DataObjectModification<Node> mod) {
-        if((mod.getModificationType() == ModificationType.WRITE) 
+        if((mod.getModificationType() == ModificationType.WRITE)
                         && (mod.getDataBefore() == null)){
             return mod.getDataAfter();
         }
@@ -244,35 +262,28 @@ public class HwvtepDataChangeListener implements DataTreeChangeListener<Node>, A
         return path;
     }
 
-    public Map<InstanceIdentifier<Node>, HwvtepConnectionInstance> connectionInstancesFromChanges(
-                    Collection<DataTreeModification<Node>> changes) {
-        Map<InstanceIdentifier<Node>, HwvtepConnectionInstance> result =
-                        new HashMap<InstanceIdentifier<Node>, HwvtepConnectionInstance>();
+    private Map<HwvtepConnectionInstance, Collection<DataTreeModification<Node>>> changesByConnectionInstance(
+            Collection<DataTreeModification<Node>> changes) {
+        Map<HwvtepConnectionInstance, Collection<DataTreeModification<Node>>> result =
+                new HashMap<HwvtepConnectionInstance, Collection<DataTreeModification<Node>>>();
         for (DataTreeModification<Node> change : changes) {
-            final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
             final DataObjectModification<Node> mod = change.getRootNode();
-            Node created = getCreated(mod);
-            Node updated = getUpdated(mod);
-            Node original = getOriginal(mod);
-            Node deleted = getRemoved(mod);
-
-            if((original != null) && (deleted == null)) {
-                result.put(key, getConnectionInstance(original));
-            }
-            if(created != null) {
-                result.put(key, getConnectionInstance(created));
-            } else if(updated != null) {
-                result.put(key, getConnectionInstance(updated));
+            //From original node to get connection instance
+            Node node = mod.getDataBefore()!=null ? mod.getDataBefore() : mod.getDataAfter();
+            HwvtepConnectionInstance connection = hcm.getConnectionInstance(node);
+            if (connection != null) {
+                if (!result.containsKey(connection)) {
+                    List<DataTreeModification<Node>> tempChanges= new ArrayList<DataTreeModification<Node>>();
+                    tempChanges.add(change);
+                    result.put(connection, tempChanges);
+                } else {
+                    result.get(connection).add(change);
+                }
+            } else {
+                LOG.warn("Failed to get the connection of changed node: {}", node);
             }
         }
-        LOG.trace("Connection Instance Map: {}", result);
+        LOG.trace("Connection Change Map: {}", result);
         return result;
     }
-
-    private HwvtepConnectionInstance getConnectionInstance(Node node) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-
-}
+}
\ No newline at end of file
index 8592e4286d1c76e01789d4318a7026aae5387f8b..483cf1567d7a1ac52ccb6aa49e950c12c8879c7b 100644 (file)
@@ -106,18 +106,18 @@ public class HwvtepSouthboundUtil {
                     HwvtepLogicalSwitchAttributes lNode) {
         Preconditions.checkNotNull(lNode);
         Optional<HwvtepGlobalAugmentation> result = null;
-        // TODO: Add managed-by to hwvtep-logical-switch-attributes in
-        // hwvtep.yang
-        /*
-         * HwvtepGlobalRef ref = lNode.getManagedBy(); if (ref != null &&
-         * ref.getValue() != null) { result = getManagingNode(db, ref); } else {
-         * LOG.warn(
-         * "Cannot find client for LogicalSwitch without a specified ManagedBy {}"
-         * , pNode); return Optional.absent(); } if(!result.isPresent()) {
-         * LOG.warn("Failed to find managing node for PhysicalSwitch {}",
-         * pNode); } return result;
-         */
-        return Optional.absent(); // TODO: Delete this once yang is updated
+
+        HwvtepGlobalRef ref = lNode.getLogicalSwitchManagedBy();
+        if (ref != null && ref.getValue() != null) {
+            result = getManagingNode(db, ref);
+        } else {
+            LOG.warn("Cannot find client for LogicalSwitch without a specified ManagedBy {}", lNode);
+            return Optional.absent();
+        }
+        if(!result.isPresent()) {
+            LOG.warn("Failed to find managing node for PhysicalSwitch {}",lNode);
+        }
+        return result;
     }
 
     private static Optional<HwvtepGlobalAugmentation> getManagingNode(DataBroker db, HwvtepGlobalRef ref) {
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/AbstractTransactCommand.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/AbstractTransactCommand.java
new file mode 100644 (file)
index 0000000..d766f19
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 China Telecom Beijing Research Institute 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.hwvtepsouthbound.transact;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+
+public abstract class AbstractTransactCommand implements TransactCommand {
+
+    private HwvtepOperationalState operationalState;
+    private Collection<DataTreeModification<Node>> changes;
+
+    protected AbstractTransactCommand() {
+        // NO OP
+    }
+
+    public AbstractTransactCommand(HwvtepOperationalState state, Collection<DataTreeModification<Node>> changes) {
+        this.operationalState = state;
+        this.changes = changes;
+    }
+
+    public HwvtepOperationalState getOperationalState() {
+        return operationalState;
+    }
+
+    public Collection<DataTreeModification<Node>> getChanges() {
+        return changes;
+    }
+}
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/HwvtepOperationalState.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/HwvtepOperationalState.java
new file mode 100644 (file)
index 0000000..26c515d
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2015 China Telecom Beijing Research Institute 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.hwvtepsouthbound.transact;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorSetAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalPortAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
+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.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
+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.util.concurrent.CheckedFuture;
+
+public class HwvtepOperationalState {
+    private static final Logger LOG = LoggerFactory.getLogger(HwvtepOperationalState.class);
+    private Map<InstanceIdentifier<Node>, Node> operationalNodes = new HashMap<>();
+
+    public HwvtepOperationalState(DataBroker db, Collection<DataTreeModification<Node>> changes) {
+        ReadOnlyTransaction transaction = db.newReadOnlyTransaction();
+        Map<InstanceIdentifier<Node>, Node> nodeCreateOrUpdate =
+            extractCreatedOrUpdatedOrRemoved(changes, Node.class);
+            //TransactUtils.extractCreatedOrUpdatedOrRemoved(changes, Node.class);
+        if (nodeCreateOrUpdate != null) {
+            for (Entry<InstanceIdentifier<Node>, Node> entry: nodeCreateOrUpdate.entrySet()) {
+                CheckedFuture<Optional<Node>, ReadFailedException> nodeFuture =
+                        transaction.read(LogicalDatastoreType.OPERATIONAL, entry.getKey());
+                try {
+                    Optional<Node> nodeOptional = nodeFuture.get();
+                    if (nodeOptional.isPresent()) {
+                        operationalNodes.put(entry.getKey(), nodeOptional.get());
+                    }
+                } catch (InterruptedException | ExecutionException e) {
+                    LOG.warn("Error reading from datastore",e);
+                }
+            }
+        }
+        transaction.close();
+    }
+
+    private Node getCreated(DataObjectModification<Node> mod) {
+        if((mod.getModificationType() == ModificationType.WRITE)
+                        && (mod.getDataBefore() == null)){
+            return mod.getDataAfter();
+        }
+        return null;
+    }
+
+    private Node getRemoved(DataObjectModification<Node> mod) {
+        if(mod.getModificationType() == ModificationType.DELETE){
+            return mod.getDataBefore();
+        }
+        return null;
+    }
+
+    private Node getUpdated(DataObjectModification<Node> mod) {
+        Node node = null;
+        switch(mod.getModificationType()) {
+            case SUBTREE_MODIFIED:
+                node = mod.getDataAfter();
+                break;
+            case WRITE:
+                if(mod.getDataBefore() !=  null) {
+                    node = mod.getDataAfter();
+                }
+                break;
+            default:
+                break;
+        }
+        return node;
+    }
+
+    private Node getOriginal(DataObjectModification<Node> mod) {
+        Node node = null;
+        switch(mod.getModificationType()) {
+            case SUBTREE_MODIFIED:
+                node = mod.getDataBefore();
+                break;
+            case WRITE:
+                if(mod.getDataBefore() !=  null) {
+                    node = mod.getDataBefore();
+                }
+                break;
+            case DELETE:
+                node = mod.getDataBefore();
+                break;
+            default:
+                break;
+        }
+        return node;
+    }
+
+    private Map<InstanceIdentifier<Node>, Node> extractCreatedOrUpdatedOrRemoved(
+            Collection<DataTreeModification<Node>> changes, Class<Node> class1) {
+        // TODO Auto-generated method stub
+        Map<InstanceIdentifier<Node>, Node> result = new HashMap<InstanceIdentifier<Node>, Node>();
+        for (DataTreeModification<Node> change : changes) {
+            final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+            final DataObjectModification<Node> mod = change.getRootNode();
+            Node created = getCreated(mod);
+            result.put(key, created);
+            Node updated = getUpdated(mod);
+            result.put(key, updated);
+            Node deleted = getRemoved(mod);
+            result.put(key, deleted);
+        }
+        return result;
+    }
+
+    public Optional<Node> getGlobalNode(InstanceIdentifier<?> iid) {
+        InstanceIdentifier<Node> nodeIid = iid.firstIdentifierOf(Node.class);
+        return Optional.fromNullable(operationalNodes.get(nodeIid));
+    }
+
+    public Optional<HwvtepLogicalSwitchAugmentation> getLogicalSwitchAugmentation(InstanceIdentifier<?> iid) {
+        Optional<Node> nodeOptional = getGlobalNode(iid);
+        if (nodeOptional.isPresent()) {
+            return Optional.fromNullable(nodeOptional.get().getAugmentation(HwvtepLogicalSwitchAugmentation.class));
+        }
+        return Optional.absent();
+    }
+
+    public Optional<PhysicalSwitchAugmentation> getPhysicalSwitchAugmentation(InstanceIdentifier<?> iid) {
+        Optional<Node> nodeOptional = getGlobalNode(iid);
+        if (nodeOptional.isPresent()) {
+            return Optional.fromNullable(nodeOptional.get().getAugmentation(PhysicalSwitchAugmentation.class));
+        }
+        return Optional.absent();
+    }
+
+    public Optional<HwvtepPhysicalLocatorSetAugmentation> getPhysicalLocatorSetAugmentation(InstanceIdentifier<?> iid) {
+        Optional<Node> nodeOptional = getGlobalNode(iid);
+        if (nodeOptional.isPresent()) {
+            return Optional.fromNullable(nodeOptional.get().getAugmentation(HwvtepPhysicalLocatorSetAugmentation.class));
+        }
+        return Optional.absent();
+    }
+
+    public Optional<TerminationPoint> getHwvtepTerminationPoint(InstanceIdentifier<?> iid) {
+        if (iid != null) {
+            Optional<Node> nodeOptional = getGlobalNode(iid);
+            if (nodeOptional.isPresent() && nodeOptional.get().getTerminationPoint() != null) {
+                TerminationPointKey key = iid.firstKeyOf(TerminationPoint.class, TerminationPointKey.class);
+                if (key != null) {
+                    for (TerminationPoint tp:nodeOptional.get().getTerminationPoint()) {
+                        if (tp.getKey().equals(key)) {
+                            return Optional.of(tp);
+                        }
+                    }
+                }
+            }
+        }
+        return Optional.absent();
+    }
+
+    public Optional<HwvtepPhysicalLocatorAugmentation> getPhysicalLocatorAugmentation(InstanceIdentifier<?> iid) {
+        Optional<TerminationPoint> nodeOptional = getHwvtepTerminationPoint(iid);
+        if (nodeOptional.isPresent()) {
+            return Optional.fromNullable(nodeOptional.get().getAugmentation(HwvtepPhysicalLocatorAugmentation.class));
+        }
+        return Optional.absent();
+    }
+
+    public Optional<HwvtepPhysicalPortAugmentation> getPhysycalPortAugmentation(InstanceIdentifier<?> iid) {
+        Optional<TerminationPoint> tpOptional = getHwvtepTerminationPoint(iid);
+        if (tpOptional.isPresent()) {
+            return Optional.fromNullable(tpOptional.get().getAugmentation(HwvtepPhysicalPortAugmentation.class));
+        }
+        return Optional.absent();
+    }
+}
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/LogicalSwitchRemoveCommand.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/LogicalSwitchRemoveCommand.java
new file mode 100644 (file)
index 0000000..6be3c44
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015 China Telecom Beijing Research Institute 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.hwvtepsouthbound.transact;
+
+import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+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.hardwarevtep.Global;
+import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchAugmentation;
+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 LogicalSwitchRemoveCommand extends AbstractTransactCommand {
+    private static final Logger LOG = LoggerFactory.getLogger(LogicalSwitchRemoveCommand.class);
+
+    public LogicalSwitchRemoveCommand(HwvtepOperationalState state,
+            Collection<DataTreeModification<Node>> changes) {
+        super(state, changes);
+    }
+
+    @Override
+    public void execute(TransactionBuilder transaction) {
+        //TODO
+        /*Set<InstanceIdentifier<HwvtepLogicalSwitchAugmentation>> removeds =
+                TransactUtils.extractRemoved(getChanges(),HwvtepLogicalSwitchAugmentation.class);
+        Map<InstanceIdentifier<HwvtepLogicalSwitchAugmentation>, HwvtepLogicalSwitchAugmentation> originals
+            = TransactUtils.extractOriginal(getChanges(),HwvtepLogicalSwitchAugmentation.class);
+        for (InstanceIdentifier<HwvtepLogicalSwitchAugmentation> removed: removeds) {
+            LOG.info("Received request to delete ovsdb node {}",removed);
+            HwvtepLogicalSwitchAugmentation original = originals.get(removed);
+            LogicalSwitch bridge = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), LogicalSwitch.class, null);
+            Optional<HwvtepLogicalSwitchAugmentation> lsAugmentationOptional = getOperationalState()
+                    .getLogicalSwitchAugmentation(removed);
+            if (lsAugmentationOptional.isPresent() && lsAugmentationOptional.get().getHwvtepLogicalSwitchExternalId() != null) {
+                UUID lsUuid = new UUID(lsAugmentationOptional.get().getHwvtepLogicalSwitchExternalId().getValue());
+                Global ovs = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
+                        Global.class,null);
+                transaction.add(op.delete(bridge.getSchema())
+                        .where(bridge.getUuidColumn().getSchema().opEqual(lsUuid)).build());
+                transaction.add(op.comment("Logical Switch: Deleting " + original.getHwvtepNodeName()));
+            } else {
+                LOG.warn("Unable to delete logical switch {} because it was not found in the operational store, "
+                        + "and thus we cannot retrieve its UUID", removed);
+            }
+
+        }*/
+    }
+}
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/LogicalSwitchUpdateCommand.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/LogicalSwitchUpdateCommand.java
new file mode 100644 (file)
index 0000000..730c936
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015 China Telecom Beijing Research Institute 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.hwvtepsouthbound.transact;
+
+import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchAugmentation;
+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 LogicalSwitchUpdateCommand extends AbstractTransactCommand {
+    private static final Logger LOG = LoggerFactory.getLogger(LogicalSwitchUpdateCommand.class);
+
+    public LogicalSwitchUpdateCommand(HwvtepOperationalState state,
+            Collection<DataTreeModification<Node>> changes) {
+        super(state, changes);
+    }
+
+    @Override
+    public void execute(TransactionBuilder transaction) {
+        Map<InstanceIdentifier<HwvtepLogicalSwitchAugmentation>, HwvtepLogicalSwitchAugmentation> created =
+                extractCreated(getChanges(),HwvtepLogicalSwitchAugmentation.class);
+        if(created != null) {
+            for(Entry<InstanceIdentifier<HwvtepLogicalSwitchAugmentation>, HwvtepLogicalSwitchAugmentation> logicalSwitchEntry:
+                created.entrySet()) {
+                updateLogicalSwitch(transaction,  logicalSwitchEntry.getKey(), logicalSwitchEntry.getValue());
+            }
+        }
+    }
+
+
+    private void updateLogicalSwitch(TransactionBuilder transaction,
+            InstanceIdentifier<HwvtepLogicalSwitchAugmentation> iid, HwvtepLogicalSwitchAugmentation logicalSwitchAugmentation) {
+        LOG.debug("Creating a logical switch named: {}", logicalSwitchAugmentation.getHwvtepNodeName());
+        Optional<HwvtepLogicalSwitchAugmentation> operationalLogicalSwitchOptional =
+                getOperationalState().getLogicalSwitchAugmentation(iid);
+        DatabaseSchema dbSchema = transaction.getDatabaseSchema();
+        LogicalSwitch logicalSwitch = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), LogicalSwitch.class);
+        if(!operationalLogicalSwitchOptional.isPresent()) {
+            setName(logicalSwitch, logicalSwitchAugmentation, operationalLogicalSwitchOptional);
+            setTunnelKey(logicalSwitch, logicalSwitchAugmentation, operationalLogicalSwitchOptional);
+            transaction.add(op.insert(logicalSwitch));
+        } else {
+            String existingLogicalSwitchName = operationalLogicalSwitchOptional.get().getHwvtepNodeName().getValue();
+            // Name is immutable, and so we *can't* update it.  So we use extraBridge for the schema stuff
+            LogicalSwitch extraLogicalSwitch = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), LogicalSwitch.class);
+            extraLogicalSwitch.setName("");
+            transaction.add(op.update(logicalSwitch)
+                    .where(extraLogicalSwitch.getNameColumn().getSchema().opEqual(existingLogicalSwitchName))
+                    .build());
+            //stampInstanceIdentifier(transaction, iid.firstIdentifierOf(Node.class),existingBridgeName);
+        }
+    }
+
+    private void setName(LogicalSwitch logicalSwitch, HwvtepLogicalSwitchAugmentation logicalSwitchAugmentation,
+            Optional<HwvtepLogicalSwitchAugmentation> operationalLogicalSwitchOptional) {
+        if(logicalSwitchAugmentation.getHwvtepNodeName() != null) {
+            logicalSwitch.setName(logicalSwitchAugmentation.getHwvtepNodeName().getValue());
+        } else if(operationalLogicalSwitchOptional.isPresent() && operationalLogicalSwitchOptional.get().getHwvtepNodeName() != null) {
+            logicalSwitch.setName(operationalLogicalSwitchOptional.get().getHwvtepNodeName().getValue());
+        }
+    }
+
+    private void setTunnelKey(LogicalSwitch logicalSwitch, HwvtepLogicalSwitchAugmentation logicalSwitchAugmentation,
+            Optional<HwvtepLogicalSwitchAugmentation> operationalLogicalSwitchOptional) {
+        if(logicalSwitchAugmentation.getTunnelKey() != null) {
+            Set<Long> tunnel = new HashSet<Long>();
+            tunnel.add(Long.valueOf(logicalSwitchAugmentation.getTunnelKey()));
+            logicalSwitch.setTunnelKey(tunnel);
+        } else if(operationalLogicalSwitchOptional.isPresent() && operationalLogicalSwitchOptional.get().getTunnelKey() != null) {
+            Set<Long> tunnel = new HashSet<Long>();
+            tunnel.add(Long.valueOf(operationalLogicalSwitchOptional.get().getTunnelKey()));
+            logicalSwitch.setTunnelKey(tunnel);
+        }
+    }
+
+    private Node getCreated(DataObjectModification<Node> mod) {
+        if((mod.getModificationType() == ModificationType.WRITE)
+                        && (mod.getDataBefore() == null)){
+            return mod.getDataAfter();
+        }
+        return null;
+    }
+
+    private Map<InstanceIdentifier<HwvtepLogicalSwitchAugmentation>, HwvtepLogicalSwitchAugmentation> extractCreated(
+            Collection<DataTreeModification<Node>> changes, Class<HwvtepLogicalSwitchAugmentation> class1) {
+        Map<InstanceIdentifier<HwvtepLogicalSwitchAugmentation>, HwvtepLogicalSwitchAugmentation> result
+            = new HashMap<InstanceIdentifier<HwvtepLogicalSwitchAugmentation>, HwvtepLogicalSwitchAugmentation>();
+        if(changes != null && !changes.isEmpty()) {
+            for(DataTreeModification<Node> change : changes) {
+                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+                final DataObjectModification<Node> mod = change.getRootNode();
+                Node created = getCreated(mod);
+                if(created != null) {
+                    HwvtepLogicalSwitchAugmentation logicalSwitch = created.getAugmentation(HwvtepLogicalSwitchAugmentation.class);
+                    InstanceIdentifier<HwvtepLogicalSwitchAugmentation> iid = change.getRootPath().getRootIdentifier().augmentation(HwvtepLogicalSwitchAugmentation.class);
+                    if(logicalSwitch != null) {
+                        result.put(iid, logicalSwitch);
+                    }
+                }
+            }
+        }
+        return result;
+    }
+}
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/PhysicalLocatorRemoveCommand.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/PhysicalLocatorRemoveCommand.java
new file mode 100644 (file)
index 0000000..8206b4c
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 China Telecom Beijing Research Institute 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.hwvtepsouthbound.transact;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PhysicalLocatorRemoveCommand extends AbstractTransactCommand {
+    private static final Logger LOG = LoggerFactory.getLogger(PhysicalLocatorRemoveCommand.class);
+
+    public PhysicalLocatorRemoveCommand(HwvtepOperationalState state,
+            Collection<DataTreeModification<Node>> changes) {
+        super(state, changes);
+    }
+
+    @Override
+    public void execute(TransactionBuilder transaction) {
+        //TODO
+    }
+}
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/PhysicalLocatorUpdateCommand.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/PhysicalLocatorUpdateCommand.java
new file mode 100644 (file)
index 0000000..113d78b
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 China Telecom Beijing Research Institute 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.hwvtepsouthbound.transact;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PhysicalLocatorUpdateCommand extends AbstractTransactCommand {
+    private static final Logger LOG = LoggerFactory.getLogger(PhysicalLocatorUpdateCommand.class);
+
+    public PhysicalLocatorUpdateCommand(HwvtepOperationalState state,
+            Collection<DataTreeModification<Node>> changes) {
+        super(state, changes);
+    }
+
+    @Override
+    public void execute(TransactionBuilder transaction) {
+        //TODO
+    }
+
+}
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/PhysicalPortRemoveCommand.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/PhysicalPortRemoveCommand.java
new file mode 100644 (file)
index 0000000..aafc847
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 China Telecom Beijing Research Institute 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.hwvtepsouthbound.transact;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PhysicalPortRemoveCommand extends AbstractTransactCommand {
+    private static final Logger LOG = LoggerFactory.getLogger(PhysicalPortRemoveCommand.class);
+
+    public PhysicalPortRemoveCommand(HwvtepOperationalState state,
+            Collection<DataTreeModification<Node>> changes) {
+        super(state, changes);
+    }
+
+    @Override
+    public void execute(TransactionBuilder transaction) {
+        //TODO
+    }
+
+}
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/PhysicalPortUpdateCommand.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/PhysicalPortUpdateCommand.java
new file mode 100644 (file)
index 0000000..caef6cb
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 China Telecom Beijing Research Institute 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.hwvtepsouthbound.transact;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PhysicalPortUpdateCommand extends AbstractTransactCommand {
+    private static final Logger LOG = LoggerFactory.getLogger(PhysicalPortUpdateCommand.class);
+
+    public PhysicalPortUpdateCommand(HwvtepOperationalState state,
+            Collection<DataTreeModification<Node>> changes) {
+        super(state, changes);
+    }
+
+    @Override
+    public void execute(TransactionBuilder transaction) {
+        //TODO
+    }
+
+}
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/TransactCommandAggregator.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/TransactCommandAggregator.java
new file mode 100644 (file)
index 0000000..3d15f38
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015 China Telecom Beijing Research Institute 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.hwvtepsouthbound.transact;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+
+public class TransactCommandAggregator implements TransactCommand {
+
+    private List<TransactCommand> commands = new ArrayList<TransactCommand>();
+
+    public TransactCommandAggregator(HwvtepOperationalState state, Collection<DataTreeModification<Node>> changes) {
+        commands.add(new LogicalSwitchUpdateCommand(state,changes));
+        commands.add(new LogicalSwitchRemoveCommand(state,changes));
+        commands.add(new PhysicalLocatorUpdateCommand(state,changes));
+        commands.add(new PhysicalLocatorRemoveCommand(state,changes));
+        commands.add(new PhysicalPortUpdateCommand(state,changes));
+        commands.add(new PhysicalPortRemoveCommand(state,changes));
+    }
+
+    @Override
+    public void execute(TransactionBuilder transaction) {
+        for (TransactCommand command:commands) {
+            command.execute(transaction);
+        }
+    }
+}
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/TransactUtils.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/TransactUtils.java
new file mode 100644 (file)
index 0000000..e8a01e6
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2015 China Telecom Beijing Research Institute 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.hwvtepsouthbound.transact;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchAugmentation;
+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.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TransactUtils {
+    private static final Logger LOG = LoggerFactory.getLogger(TransactUtils.class);
+
+    public static Node getCreated(DataObjectModification<Node> mod) {
+        if((mod.getModificationType() == ModificationType.WRITE)
+                        && (mod.getDataBefore() == null)){
+            return mod.getDataAfter();
+        }
+        return null;
+    }
+
+    public static Node getRemoved(DataObjectModification<Node> mod) {
+        if(mod.getModificationType() == ModificationType.DELETE){
+            return mod.getDataBefore();
+        }
+        return null;
+    }
+
+    public static Node getUpdated(DataObjectModification<Node> mod) {
+        Node node = null;
+        switch(mod.getModificationType()) {
+            case SUBTREE_MODIFIED:
+                node = mod.getDataAfter();
+                break;
+            case WRITE:
+                if(mod.getDataBefore() !=  null) {
+                    node = mod.getDataAfter();
+                }
+                break;
+            default:
+                break;
+        }
+        return node;
+    }
+
+    public static Node getOriginal(DataObjectModification<Node> mod) {
+        Node node = null;
+        switch(mod.getModificationType()) {
+            case SUBTREE_MODIFIED:
+                node = mod.getDataBefore();
+                break;
+            case WRITE:
+                if(mod.getDataBefore() !=  null) {
+                    node = mod.getDataBefore();
+                }
+                break;
+            case DELETE:
+                node = mod.getDataBefore();
+                break;
+            default:
+                break;
+        }
+        return node;
+    }
+
+    public static Map<InstanceIdentifier<Node>, Node> extractCreatedOrUpdatedOrRemoved(
+            Collection<DataTreeModification<Node>> changes, Class<Node> class1) {
+        // TODO Auto-generated method stub
+        Map<InstanceIdentifier<Node>, Node> result = new HashMap<InstanceIdentifier<Node>, Node>();
+        for(DataTreeModification<Node> change : changes) {
+            final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+            final DataObjectModification<Node> mod = change.getRootNode();
+            Node created = getCreated(mod);
+            result.put(key, created);
+            Node updated = getUpdated(mod);
+            result.put(key, updated);
+            Node deleted = getRemoved(mod);
+            result.put(key, deleted);
+        }
+        return null;
+    }
+
+    /*
+    public static <T extends Augmentation<Node>> Map<InstanceIdentifier<? extends DataObject>, T> extractCreated(
+            Collection<DataTreeModification<Node>> changes, Class<T> class1) {
+        // TODO Auto-generated method stub
+        Map<InstanceIdentifier<?>, T> result =
+            new HashMap<InstanceIdentifier<?>, T>();
+        if(changes != null && !changes.isEmpty()) {
+            for(DataTreeModification<Node> change : changes) {
+                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+                final DataObjectModification<Node> mod = change.getRootNode();
+                Node created = getCreated(mod);
+                if(created != null) {
+                    T logicalSwitch = created.getAugmentation(class1);
+                    created.getKey().getNodeId().get
+                    logicalSwitch.
+                    InstanceIdentifier<?> iid = change.getRootPath().getRootIdentifier()..augmentation(class1);
+                    if(logicalSwitch != null) {
+                        result.put(iid, logicalSwitch);
+                    }
+                }
+            }
+        }
+        return result;
+    }
+    */
+
+}