Merge "update IT for new SFC model changes for DPLs"
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / HwvtepDataChangeListener.java
index f20789572c3430796dc544a4903690fbd03802d0..4d3daf5d1954c4eb8dec6062e468adbf8757fa32 100644 (file)
@@ -9,7 +9,12 @@
 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 org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
@@ -17,7 +22,10 @@ import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.Mod
 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.binding.api.ReadWriteTransaction;
 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.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.ConnectionInfo;
@@ -30,6 +38,8 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Optional;
+
 public class HwvtepDataChangeListener implements DataTreeChangeListener<Node>, AutoCloseable {
 
     private ListenerRegistration<HwvtepDataChangeListener> registration;
@@ -114,21 +124,23 @@ 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);
+                // We can only connect if user configured connection info
+                if (hwvtepGlobal != null && hwvtepGlobal.getConnectionInfo() != 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) {
@@ -140,18 +152,20 @@ 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);
+                // Check if user has updated connection information
+                if (hgUpdated != null && hgOriginal != null && hgUpdated.getConnectionInfo() != 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) {
@@ -160,7 +174,12 @@ public class HwvtepDataChangeListener implements DataTreeChangeListener<Node>, A
          * Update data for each connection
          * Requires Command patterns. TBD.
          */
-        
+        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) {
@@ -170,17 +189,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();
         }
@@ -238,4 +259,39 @@ public class HwvtepDataChangeListener implements DataTreeChangeListener<Node>, A
                         .child(Node.class);
         return path;
     }
+
+    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 DataObjectModification<Node> mod = change.getRootNode();
+            //From original node to get connection instance
+            Node node = mod.getDataBefore()!=null ? mod.getDataBefore() : mod.getDataAfter();
+            HwvtepConnectionInstance connection = hcm.getConnectionInstance(node);
+            if(connection == null) {
+                //Let us try getting it from Operational DS
+                final ReadWriteTransaction transaction = db.newReadWriteTransaction();
+                InstanceIdentifier<Node> connectionIid = HwvtepSouthboundMapper.createInstanceIdentifier(node.getNodeId());
+                Optional<Node> optionalNode = HwvtepSouthboundUtil.readNode(transaction, connectionIid);
+                LOG.trace("Node in Operational DataStore for user node {} is {}", node, optionalNode);
+                if(optionalNode.isPresent()) {
+                    connection = hcm.getConnectionInstance(optionalNode.get());
+                }
+            }
+            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 Change Map: {}", result);
+        return result;
+    }
 }