bug 6643 hwvtep configuration reconcilation 91/44091/17
authorK.V Suneelu Verma <k.v.suneelu.verma@ericsson.com>
Tue, 16 Aug 2016 17:32:52 +0000 (23:02 +0530)
committerAnil Vishnoi <vishnoianil@gmail.com>
Thu, 20 Oct 2016 07:31:47 +0000 (07:31 +0000)
Added operational node listener to trigger reconcillation
listens for physical switch node added event and schedules the reconcillation.
trigger transactions for changes in macs and logical switches and vlan bindings
trigger transactions for removal of local ucast and mcast macs aswell
so that to be deleted logical switches will not have any references
cancel the queued reconcilation task if any upon receiving node disconnect event

fixed some npes in mac remove commands
run the logical switch remove command post mac entries remove command as
those logical switches removed logical swithes have to be visible in the
other remove commands

validated the following test cases
1) disconnect the device and push the config (logical switch and remote
macs and vlan bindings ) and connect the device again
2) disconnect the device and delete some confing and connect the device
again

Change-Id: I12d0692e4c8b040f261a9c2cc5cffc05bef96f0d
Signed-off-by: K.V Suneelu Verma <k.v.suneelu.verma@ericsson.com>
21 files changed:
hwvtepsouthbound/hwvtepsouthbound-features/src/main/features/features.xml
hwvtepsouthbound/hwvtepsouthbound-impl/pom.xml
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepConnectionManager.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepSouthboundMapper.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepSouthboundProvider.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepSouthboundUtil.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/DataObjectModificationImpl.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/DataTreeModificationImpl.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/GlobalConfigOperationalChangeGetter.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/HwvtepReconciliationManager.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/HwvtepReconciliationTask.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/SwitchConfigOperationalChangeGetter.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/HwvtepOperationalState.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/LogicalSwitchRemoveCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/McastMacsLocalRemoveCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/McastMacsRemoteRemoveCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/TransactUtils.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/UcastMacsLocalRemoveCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/UcastMacsRemoteRemoveCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/UcastMacsRemoteUpdateCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transactions/md/HwvtepOperationalCommandAggregator.java

index d3ce84ca7d8401ac5c9c329368d36838ec3680be..8314b9fad3cf19957ccd11e2ba903e2e612dd98e 100644 (file)
@@ -23,6 +23,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   <feature name='odl-ovsdb-hwvtepsouthbound' version='${project.version}' description='OpenDaylight :: hwvtepsouthbound'>
     <feature version='${controller.mdsal.version}'>odl-mdsal-broker</feature>
     <feature version='${project.version}'>odl-ovsdb-hwvtepsouthbound-api</feature>
+    <bundle>mvn:org.opendaylight.ovsdb/utils.mdsal-utils/{{VERSION}}</bundle>
     <bundle>mvn:org.opendaylight.ovsdb/hwvtepsouthbound-impl/{{VERSION}}</bundle>
     <bundle>mvn:org.opendaylight.ovsdb/library/{{VERSION}}</bundle>
     <bundle>mvn:com.fasterxml.jackson.core/jackson-annotations/{{VERSION}}</bundle>
index 1c65559540608e1b204cc37d0e7f7343cb9b79c0..122e4e00b2616a1b35de100db4884084b92a1bd0 100644 (file)
@@ -37,6 +37,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <artifactId>schema.hardwarevtep</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>utils.mdsal-utils</artifactId>
+      <version>${project.version}</version>
+    </dependency>
     <!-- Testing Dependencies -->
     <dependency>
       <groupId>junit</groupId>
index 471a67f9d00da6875f173f34a5d613ff7daf5ac0..79b84a4ac5fafcc220c544de98d7cc7b3dc17a6b 100644 (file)
@@ -39,6 +39,7 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.ovsdb.hwvtepsouthbound.reconciliation.ReconciliationManager;
 import org.opendaylight.ovsdb.hwvtepsouthbound.reconciliation.ReconciliationTask;
+import org.opendaylight.ovsdb.hwvtepsouthbound.reconciliation.configuration.HwvtepReconciliationTask;
 import org.opendaylight.ovsdb.hwvtepsouthbound.reconciliation.connection.ConnectionReconciliationTask;
 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.HwvtepGlobalRemoveCommand;
 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionCommand;
@@ -53,6 +54,7 @@ import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
 import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
 import org.opendaylight.ovsdb.schema.hardwarevtep.Global;
+import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
 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.HwvtepPhysicalSwitchAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
@@ -250,7 +252,7 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
         }
     }
 
-    private HwvtepConnectionInstance getConnectionInstance(HwvtepPhysicalSwitchAttributes pNode) {
+    public HwvtepConnectionInstance getConnectionInstance(HwvtepPhysicalSwitchAttributes pNode) {
         Optional<HwvtepGlobalAugmentation> optional = HwvtepSouthboundUtil.getManagingNode(db, pNode);
         if(optional.isPresent()) {
             return getConnectionInstance(optional.get().getConnectionInfo());
@@ -259,6 +261,21 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
         }
     }
 
+    public void stopConfigurationReconciliation(final InstanceIdentifier<Node> nodeIid) {
+        final ReconciliationTask task = new HwvtepReconciliationTask(
+                reconciliationManager, HwvtepConnectionManager.this, nodeIid, null, null, db);
+
+        reconciliationManager.dequeue(task);
+    }
+
+    public void reconcileConfigurations(final HwvtepConnectionInstance client, Node psNode) {
+        final InstanceIdentifier<Node> nodeIid = client.getInstanceIdentifier();
+        final ReconciliationTask task = new HwvtepReconciliationTask(
+                reconciliationManager, HwvtepConnectionManager.this, nodeIid, psNode, client, db);
+
+        reconciliationManager.enqueue(task);
+    }
+
     private void removeConnectionInstance(ConnectionInfo key) {
         ConnectionInfo connectionInfo = HwvtepSouthboundMapper.suppressLocalIpPort(key);
         clients.remove(connectionInfo);
@@ -476,7 +493,7 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
             return;
         }
         //Connection detail need to be cached, irrespective of ownership result.
-        putConnectionInstance(hwvtepConnectionInstance.getMDConnectionInfo(),hwvtepConnectionInstance);
+        putConnectionInstance(hwvtepConnectionInstance.getMDConnectionInfo(), hwvtepConnectionInstance);
 
         if (ownershipChange.isOwner() == hwvtepConnectionInstance.getHasDeviceOwnership()) {
             LOG.debug("handleOwnershipChanged: no change in ownership for {}. Ownership status is : {}",
index c49f6e02b6ebc7cfbacc6bc067034ecb46ba5afb..2aaa5253078505a3b30781c2d26a793607ae2e52 100644 (file)
@@ -227,4 +227,12 @@ public class HwvtepSouthboundMapper {
                         new VlanBindingsKey(vBindings.getKey()));
 
     }
+
+    public static InstanceIdentifier<Node> createInstanceIdentifier() {
+        InstanceIdentifier<Node> path = InstanceIdentifier
+                .create(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID))
+                .child(Node.class);
+        return path;
+    }
 }
index 60c12a104960fa50c35d6661c0327a40fc4b70c5..d1a9d53b0f2f3c6aa619d704f234210bf82e485b 100644 (file)
@@ -19,13 +19,13 @@ import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipS
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipState;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.ovsdb.hwvtepsouthbound.reconciliation.configuration.HwvtepReconciliationManager;
 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionInvoker;
 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionInvokerImpl;
 import org.opendaylight.ovsdb.lib.OvsdbConnection;
+import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
 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.NetworkTopologyBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
@@ -56,6 +56,7 @@ public class HwvtepSouthboundProvider implements AutoCloseable {
     private EntityOwnershipCandidateRegistration registration;
     private HwvtepsbPluginInstanceEntityOwnershipListener providerOwnershipChangeListener;
     private HwvtepDataChangeListener hwvtepDTListener;
+    private HwvtepReconciliationManager hwvtepReconciliationManager;
 
     public HwvtepSouthboundProvider(final DataBroker dataBroker,
             final EntityOwnershipService entityOwnershipServiceDependency,
@@ -66,7 +67,6 @@ public class HwvtepSouthboundProvider implements AutoCloseable {
         this.entityOwnershipService = entityOwnershipServiceDependency;
         registration = null;
         this.ovsdbConnection = ovsdbConnection;
-
         HwvtepSouthboundUtil.setInstanceIdentifierCodec(new InstanceIdentifierCodec(schemaService,
                 bindingNormalizedNodeSerializer));
         LOG.info("HwvtepSouthboundProvider ovsdbConnectionService: {}", ovsdbConnection);
@@ -80,7 +80,7 @@ public class HwvtepSouthboundProvider implements AutoCloseable {
         txInvoker = new TransactionInvokerImpl(db);
         cm = new HwvtepConnectionManager(db, txInvoker, entityOwnershipService);
         hwvtepDTListener = new HwvtepDataChangeListener(db, cm);
-
+        hwvtepReconciliationManager = new HwvtepReconciliationManager(db, cm);
         //Register listener for entityOnwership changes
         providerOwnershipChangeListener =
                 new HwvtepsbPluginInstanceEntityOwnershipListener(this,this.entityOwnershipService);
index 7da5b5590b0e07b23a3c1f161b2e025686a3ce3f..033bf73efe360fd918a0ecf31d8681e388e38ed1 100644 (file)
@@ -28,6 +28,8 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.CheckedFuture;
 
+import java.util.concurrent.ExecutionException;
+
 public class HwvtepSouthboundUtil {
 
     private static final Logger LOG = LoggerFactory.getLogger(HwvtepSouthboundUtil.class);
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/DataObjectModificationImpl.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/DataObjectModificationImpl.java
new file mode 100644 (file)
index 0000000..c967b19
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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.reconciliation.configuration;
+
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class DataObjectModificationImpl<T extends DataObject> implements DataObjectModification<T> {
+
+    private Collection<DataObjectModification<? extends DataObject>> childNodesCache = new ArrayList<>();
+    InstanceIdentifier<T> nodeId;
+    T newNode;
+    T oldNode;
+
+    public DataObjectModificationImpl(InstanceIdentifier<T> nodeId, T newData, T oldData) {
+        this.nodeId = nodeId;
+        this.newNode = newData;
+        this.oldNode = oldData;
+    }
+
+
+    @Override
+    public T getDataBefore() {
+        return oldNode;
+    }
+
+    @Override
+    public T getDataAfter() {
+        return newNode;
+    }
+
+    @Override
+    public Class<T> getDataType() {
+        return (Class<T>) newNode.getClass();
+    }
+
+    @Override
+    public InstanceIdentifier.PathArgument getIdentifier() {
+        return nodeId.getPathArguments().iterator().next();
+    }
+
+    @Override
+    public ModificationType getModificationType() {
+        return ModificationType.WRITE;
+
+    }
+
+    @Override
+    public Collection<DataObjectModification<? extends DataObject>> getModifiedChildren() {
+        return childNodesCache;
+    }
+
+    @Override
+    public DataObjectModification<? extends DataObject> getModifiedChild(final InstanceIdentifier.PathArgument arg) {
+        return null;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <C extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<C>> DataObjectModification<C>
+        getModifiedChildListItem(final Class<C> listItem, final K listKey) {
+        return (DataObjectModification<C>) getModifiedChild(
+                new InstanceIdentifier.IdentifiableItem<>(listItem, listKey));
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <C extends ChildOf<? super T>> DataObjectModification<C> getModifiedChildContainer(final Class<C> arg) {
+        return (DataObjectModification<C>) getModifiedChild(new InstanceIdentifier.Item<>(arg));
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <C extends Augmentation<T> & DataObject> DataObjectModification<C> getModifiedAugmentation(
+            final Class<C> augmentation) {
+        return (DataObjectModification<C>) getModifiedChild(new InstanceIdentifier.Item<>(augmentation));
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "{identifier = " + nodeId +"}";
+    }
+}
\ No newline at end of file
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/DataTreeModificationImpl.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/DataTreeModificationImpl.java
new file mode 100644 (file)
index 0000000..895375c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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.reconciliation.configuration;
+
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+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.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class DataTreeModificationImpl<T extends DataObject> implements DataTreeModification {
+
+    InstanceIdentifier<T> nodeId;
+    T newNode;
+    T oldNode;
+
+    public DataTreeModificationImpl(InstanceIdentifier<T> nodeId, T newNode, T oldNode) {
+        this.nodeId = nodeId;
+        this.newNode = newNode;
+        this.oldNode = oldNode;
+    }
+
+    @Override
+    public DataTreeIdentifier<T> getRootPath() {
+        return new DataTreeIdentifier<T>(LogicalDatastoreType.CONFIGURATION, nodeId);
+    }
+
+    @Override
+    public DataObjectModification<T> getRootNode() {
+        return new DataObjectModificationImpl<T>(nodeId, newNode, oldNode);
+    }
+}
\ No newline at end of file
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/GlobalConfigOperationalChangeGetter.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/GlobalConfigOperationalChangeGetter.java
new file mode 100644 (file)
index 0000000..599a6bf
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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.reconciliation.configuration;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+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.HwvtepGlobalAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalMcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class GlobalConfigOperationalChangeGetter {
+
+    public static DataTreeModification<Node> getModification(InstanceIdentifier<Node> nodeId, Node configNode,
+                                                             Node opNode) {
+
+        NodeBuilder newNodeBuilder = getNodeBuilderFromNode(configNode);
+        NodeBuilder oldNodeBuilder = getNodeBuilderFromNode(opNode);
+
+        HwvtepGlobalAugmentationBuilder newAugmentation = getAugmentationFromNode(configNode);
+        HwvtepGlobalAugmentationBuilder oldAugmentation = getAugmentationFromNode(opNode);
+
+        //fire removal of local ucast macs so that logical switches will be deleted
+        fillLocalMcacsToBeRemoved(oldAugmentation, configNode, opNode);
+
+        newNodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, newAugmentation.build());
+        oldNodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, oldAugmentation.build());
+
+        return new DataTreeModificationImpl<Node>(nodeId, newNodeBuilder.build(), oldNodeBuilder.build());
+    }
+
+    static void fillLocalMcacsToBeRemoved(HwvtepGlobalAugmentationBuilder oldAugmentation, Node configNode,
+                                          Node opNode) {
+        Set<String> logicalSwitchNamesToBeRemoved = getLogicalSwitchesToBeRemoved(configNode, opNode);
+        List<LocalUcastMacs> localUcastMacsToBeRemoved = getLocalUcastMacsToBeRemoved(opNode,
+                logicalSwitchNamesToBeRemoved);
+        List<LocalMcastMacs> localMcastMacsToBeRemoved = getLocalMcastMacsToBeRemoved(opNode,
+                logicalSwitchNamesToBeRemoved);
+
+        oldAugmentation.setLocalUcastMacs(localUcastMacsToBeRemoved);
+        oldAugmentation.setLocalMcastMacs(localMcastMacsToBeRemoved);
+    }
+
+    static List<LocalUcastMacs> getLocalUcastMacsToBeRemoved(Node opNode, final Set<String> removedSwitchNames) {
+        if (opNode == null || opNode.getAugmentation(HwvtepGlobalAugmentation.class) == null) {
+            return null;
+        }
+        List<LocalUcastMacs> localUcastMacs = opNode.getAugmentation(HwvtepGlobalAugmentation.class).
+                getLocalUcastMacs();
+        if (localUcastMacs == null) {
+            return null;
+        }
+        Iterable<LocalUcastMacs> removedLocalUcastMacs = Iterables.filter(localUcastMacs,
+                new Predicate<LocalUcastMacs>() {
+                    @Override
+                    public boolean apply(LocalUcastMacs mac) {
+                        String ls = mac.getLogicalSwitchRef().getValue().firstKeyOf(LogicalSwitches.class).
+                                getHwvtepNodeName().getValue();
+                        if (removedSwitchNames.contains(ls)) {
+                            return true;
+                        }
+                        return false;
+                    }
+                });
+        return Lists.newArrayList(removedLocalUcastMacs);
+    }
+
+    static List<LocalMcastMacs> getLocalMcastMacsToBeRemoved(Node opNode, final Set<String> removedSwitchNames) {
+        if (opNode == null || opNode.getAugmentation(HwvtepGlobalAugmentation.class) == null) {
+            return null;
+        }
+        List<LocalMcastMacs> localMcastMacs = opNode.getAugmentation(HwvtepGlobalAugmentation.class).
+                getLocalMcastMacs();
+        if (localMcastMacs == null) {
+            return null;
+        }
+        Iterable<LocalMcastMacs> removedLocalMcastMacs = Iterables.filter(localMcastMacs,
+                new Predicate<LocalMcastMacs>() {
+                    @Override
+                    public boolean apply(LocalMcastMacs mac) {
+                        String ls = mac.getLogicalSwitchRef().getValue().firstKeyOf(LogicalSwitches.class).
+                                getHwvtepNodeName().getValue();
+                        if (removedSwitchNames.contains(ls)) {
+                            return true;
+                        }
+                        return false;
+                    }
+                });
+        return Lists.newArrayList(removedLocalMcastMacs);
+    }
+
+    static  Set<String> getLogicalSwitchesToBeRemoved(Node configNode, Node opNode) {
+        Set<String> opSwitchNames = new HashSet<>();
+        Set<String> cfgSwitchNames = new HashSet<>();
+        List<LogicalSwitches> cfgLogicalSwitches = Lists.newArrayList();
+
+        List<LogicalSwitches> opLogicalSwitches = opNode.getAugmentation(HwvtepGlobalAugmentation.class).getLogicalSwitches();
+        if (configNode != null) {
+            cfgLogicalSwitches = configNode.getAugmentation(HwvtepGlobalAugmentation.class).getLogicalSwitches();
+        }
+        if (opLogicalSwitches != null) {
+            for (LogicalSwitches ls : opLogicalSwitches) {
+                opSwitchNames.add(ls.getHwvtepNodeName().getValue());
+            }
+        }
+        if (cfgLogicalSwitches != null) {
+            for (LogicalSwitches ls : cfgLogicalSwitches) {
+                cfgSwitchNames.add(ls.getHwvtepNodeName().getValue());
+            }
+        }
+        final Set<String> removedSwitchNames = Sets.difference(opSwitchNames, cfgSwitchNames);
+        return removedSwitchNames;
+    }
+
+    static HwvtepGlobalAugmentationBuilder getAugmentationFromNode(Node node ) {
+        if (node == null) {
+            return new HwvtepGlobalAugmentationBuilder();
+        }
+        HwvtepGlobalAugmentation src = node.getAugmentation(HwvtepGlobalAugmentation.class);
+        HwvtepGlobalAugmentationBuilder builder = new HwvtepGlobalAugmentationBuilder();
+        if (src != null) {
+            builder.setLogicalSwitches(src.getLogicalSwitches());
+            builder.setRemoteMcastMacs(src.getRemoteMcastMacs());
+            builder.setRemoteUcastMacs(src.getRemoteUcastMacs());
+        }
+        return builder;
+    }
+
+    static NodeBuilder getNodeBuilderFromNode(Node node) {
+        NodeBuilder newNodeBuilder;
+        if (node != null) {
+            newNodeBuilder = new NodeBuilder(node);
+            newNodeBuilder.removeAugmentation(HwvtepGlobalAugmentation.class);
+        } else {
+            newNodeBuilder = new NodeBuilder();
+        }
+        newNodeBuilder.setTerminationPoint(new ArrayList<>());
+        return newNodeBuilder;
+    }
+}
\ No newline at end of file
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/HwvtepReconciliationManager.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/HwvtepReconciliationManager.java
new file mode 100644 (file)
index 0000000..65986d5
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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.reconciliation.configuration;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+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.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepConnectionInstance;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepConnectionManager;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundConstants;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundMapper;
+import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
+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.HwvtepPhysicalSwitchAttributes;
+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.NetworkTopology;
+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.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+
+public class HwvtepReconciliationManager implements ClusteredDataTreeChangeListener<Node>, AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(HwvtepReconciliationManager.class);
+    private ListenerRegistration<HwvtepReconciliationManager> registration;
+    private HwvtepConnectionManager hcm;
+    private DataBroker db;
+
+    public HwvtepReconciliationManager(DataBroker db, HwvtepConnectionManager hcm) {
+        this.db = db;
+        this.hcm = hcm;
+        registerListener(db);
+    }
+
+    private void registerListener(final DataBroker db) {
+        InstanceIdentifier<Node> iid = HwvtepSouthboundMapper.createInstanceIdentifier();
+        DataTreeIdentifier<Node> treeId =
+                        new DataTreeIdentifier<Node>(LogicalDatastoreType.OPERATIONAL, iid);
+        LOG.trace("Registering listener for path {}", treeId);
+        registration = db.registerDataTreeChangeListener(treeId, HwvtepReconciliationManager.this);
+    }
+
+    @Override
+    public void close() throws Exception {
+        if(registration != null) {
+            registration.close();
+        }
+    }
+
+    @Override
+    public void onDataTreeChanged(Collection<DataTreeModification<Node>> changes) {
+        processConnectedNodes(changes);
+        processDisconnectedNodes(changes);
+    }
+
+    private void processDisconnectedNodes(Collection<DataTreeModification<Node>> changes) {
+        for (DataTreeModification<Node> change : changes) {
+            final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+            final DataObjectModification<Node> mod = change.getRootNode();
+            Node deleted = getRemoved(mod);
+            if (deleted != null) {
+                if (deleted.getAugmentation(HwvtepGlobalAugmentation.class) != null) {
+                    LOG.trace("Cancel config reconciliation for node {}", deleted.getKey());
+                    hcm.stopConfigurationReconciliation(key);
+                }
+            }
+        }
+    }
+
+    private void processConnectedNodes(Collection<DataTreeModification<Node>> changes) {
+        for (DataTreeModification<Node> change : changes) {
+            InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+            DataObjectModification<Node> mod = change.getRootNode();
+            Node node = getCreated(mod);
+            if (node != null) {
+                PhysicalSwitchAugmentation physicalSwitch = node.getAugmentation(PhysicalSwitchAugmentation.class);
+                if (physicalSwitch != null) {
+                    HwvtepConnectionInstance connection =
+                            hcm.getConnectionInstance((HwvtepPhysicalSwitchAttributes)physicalSwitch);
+                    if (connection != null) {
+                        LOG.trace("Reconcile config for node {}, IP : {}", node.getKey(),
+                                connection.getConnectionInfo().getRemoteAddress());
+                        hcm.reconcileConfigurations(connection, node);
+                    }
+                }
+            }
+        }
+    }
+
+    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;
+    }
+}
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/HwvtepReconciliationTask.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/HwvtepReconciliationTask.java
new file mode 100644 (file)
index 0000000..cd9a817
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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.reconciliation.configuration;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepConnectionInstance;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepConnectionManager;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundMapper;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundUtil;
+import org.opendaylight.ovsdb.hwvtepsouthbound.reconciliation.ReconciliationManager;
+import org.opendaylight.ovsdb.hwvtepsouthbound.reconciliation.ReconciliationTask;
+import org.opendaylight.ovsdb.hwvtepsouthbound.transact.HwvtepOperationalState;
+import org.opendaylight.ovsdb.hwvtepsouthbound.transact.TransactCommandAggregator;
+import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
+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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.ExecutionException;
+
+import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
+import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
+
+public class HwvtepReconciliationTask extends ReconciliationTask {
+
+    private static final Logger LOG = LoggerFactory.getLogger(HwvtepReconciliationTask.class);
+    private HwvtepConnectionInstance connectionInstance;
+    private DataBroker db;
+    private Node psNode;
+    private MdsalUtils mdsalUtils;
+
+    public HwvtepReconciliationTask(ReconciliationManager reconciliationManager,
+                                    HwvtepConnectionManager connectionManager,
+                                    InstanceIdentifier<?> nodeId,
+                                    Node psNode,
+                                    HwvtepConnectionInstance connectionInstance,
+                                    DataBroker db) {
+        super(reconciliationManager, connectionManager, nodeId, null);
+        this.db = db;
+        this.psNode = psNode;
+        this.connectionInstance = connectionInstance;
+        this.mdsalUtils = new MdsalUtils(db);
+    }
+
+    private void transactChangesToDevice(Collection<DataTreeModification<Node>> changes) {
+        HwvtepOperationalState hwvtepOperationalState = new HwvtepOperationalState(db, changes);
+        connectionInstance.transact(new TransactCommandAggregator(hwvtepOperationalState,changes));
+    }
+
+    @Override
+    public boolean reconcileConfiguration(HwvtepConnectionManager connectionManagerOfDevice) {
+        InstanceIdentifier<Node> psNodeIid = HwvtepSouthboundMapper.createInstanceIdentifier(psNode.getNodeId());
+        InstanceIdentifier<Node> nodeId = (InstanceIdentifier<Node>)nodeIid;
+        ReadOnlyTransaction tx = reconciliationManager.getDb().newReadOnlyTransaction();
+
+        Node globalConfigNode = mdsalUtils.read(CONFIGURATION, nodeId);
+        Node globalOpNode = mdsalUtils.read(OPERATIONAL, nodeId);
+        Node psConfigNode = mdsalUtils.read(CONFIGURATION, psNodeIid);
+
+        DataTreeModification<Node> change = null;
+        Collection<DataTreeModification<Node>> changes = new ArrayList<>();
+        change = GlobalConfigOperationalChangeGetter.getModification(nodeId, globalConfigNode, globalOpNode);
+        changes.add(change);
+
+        change = SwitchConfigOperationalChangeGetter.getModification(psNodeIid, psConfigNode, psNode);
+        changes.add(change);
+
+        transactChangesToDevice(changes);
+        return true;
+    }
+
+    @Override
+    public void doRetry(boolean wasPreviousAttemptSuccessful) {
+    }
+
+    @Override
+    public void checkReadinessAndProcess() {
+    }
+
+    @Override
+    public long retryDelayInMills() {
+        return 0;
+    }
+
+}
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/SwitchConfigOperationalChangeGetter.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/SwitchConfigOperationalChangeGetter.java
new file mode 100644 (file)
index 0000000..a1d0572
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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.reconciliation.configuration;
+
+import com.google.common.collect.Lists;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+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.HwvtepPhysicalPortAugmentationBuilder;
+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.NodeBuilder;
+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.TerminationPointBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SwitchConfigOperationalChangeGetter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SwitchConfigOperationalChangeGetter.class);
+
+    public static DataTreeModification<Node> getModification(InstanceIdentifier<Node> psNodeId,
+                                                             Node configNode, Node operationalNode) {
+
+        NodeBuilder newNodeBuilder = getNodeBuilderFromNode(configNode);
+        NodeBuilder oldNodeBuilder = getNodeBuilderFromNode(operationalNode);
+
+        List<TerminationPoint> tpList = getPorts(configNode);
+        if (tpList.size() > 0) {
+            newNodeBuilder.setTerminationPoint(tpList);
+        }
+
+        tpList = getPorts(operationalNode);
+        if (tpList.size() > 0) {
+            oldNodeBuilder.setTerminationPoint(tpList);
+        }
+
+        return new DataTreeModificationImpl<Node>(psNodeId, newNodeBuilder.build(), oldNodeBuilder.build());
+
+    }
+
+
+    static NodeBuilder getNodeBuilderFromNode(Node node) {
+        NodeBuilder newNodeBuilder;
+        if (node != null) {
+            newNodeBuilder = new NodeBuilder(node);
+            newNodeBuilder.removeAugmentation(PhysicalSwitchAugmentation.class);
+        } else {
+            newNodeBuilder = new NodeBuilder();
+        }
+        List<TerminationPoint> emptyList = Lists.newArrayList();
+        newNodeBuilder.setTerminationPoint(emptyList);
+
+        return newNodeBuilder;
+    }
+
+
+    static List<TerminationPoint> getPorts(Node node) {
+        ArrayList<TerminationPoint> tpList = Lists.newArrayList();
+        if (node == null || node.getTerminationPoint() == null) {
+            return tpList;
+        }
+        for (TerminationPoint tp: node.getTerminationPoint()) {
+            TerminationPointBuilder terminationPointBuilder = new TerminationPointBuilder(tp);
+            terminationPointBuilder.removeAugmentation(HwvtepPhysicalPortAugmentation.class);
+
+            HwvtepPhysicalPortAugmentation augmentation = tp.getAugmentation(HwvtepPhysicalPortAugmentation.class);
+            HwvtepPhysicalPortAugmentationBuilder builder = new HwvtepPhysicalPortAugmentationBuilder();
+            if (augmentation != null) {
+                builder = new HwvtepPhysicalPortAugmentationBuilder(augmentation);
+            }
+            if (augmentation != null && augmentation.getVlanBindings() != null && !augmentation.getVlanBindings().isEmpty() ) {
+                builder.setVlanBindings(augmentation.getVlanBindings());
+                terminationPointBuilder.addAugmentation(HwvtepPhysicalPortAugmentation.class, builder.build());
+                tpList.add(terminationPointBuilder.build());
+            }
+        }
+        return tpList;
+    }
+}
\ No newline at end of file
index dd5496e70a9ec97d8e809cfa630b2218012b6bfe..3153cab15bd4aae0c032d9b739867841314fe5fc 100644 (file)
@@ -14,10 +14,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import com.google.common.collect.Maps;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundUtil;
+import org.opendaylight.ovsdb.lib.notation.UUID;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
@@ -51,7 +53,8 @@ import com.google.common.base.Preconditions;
 public class HwvtepOperationalState {
     private static final Logger LOG = LoggerFactory.getLogger(HwvtepOperationalState.class);
     private Map<InstanceIdentifier<Node>, Node> operationalNodes = new HashMap<>();
-    ReadWriteTransaction transaction;
+    private ReadWriteTransaction transaction;
+    HashMap<InstanceIdentifier<TerminationPoint>, UUID> inflightLocators = Maps.newHashMap();
 
     public HwvtepOperationalState(DataBroker db, Collection<DataTreeModification<Node>> changes) {
         Map<InstanceIdentifier<Node>, Node> nodeCreateOrUpdate =
@@ -296,4 +299,13 @@ public class HwvtepOperationalState {
     public ReadWriteTransaction getReadWriteTransaction() {
         return transaction;
     }
+
+    public void setPhysicalLocatorInFlight(InstanceIdentifier<TerminationPoint> iid,
+                                           UUID uuid) {
+        inflightLocators.put(iid, uuid);
+    }
+
+    public UUID getPhysicalLocatorInFlight(InstanceIdentifier<TerminationPoint> iid) {
+        return inflightLocators.get(iid);
+    }
 }
index 755d550d4146854841975776cae21cc976287dcd..8790a8380b15bd959e0c3ca31f919bad99aaee59 100644 (file)
@@ -112,16 +112,20 @@ public class LogicalSwitchRemoveCommand extends AbstractTransactCommand {
                             lswitchListBefore.removeAll(lswitchListUpdated);
                         }
                         //then exclude updated ones
-                        for (LogicalSwitches lswitchBefore: lswitchListBefore) {
-                            int i = 0;
-                            for(; i < lswitchListUpdated.size(); i++) {
-                                if (lswitchBefore.getHwvtepNodeName().equals(lswitchListUpdated.get(i).getHwvtepNodeName())) {
-                                    break;
+                        if (lswitchListUpdated != null) {
+                            for (LogicalSwitches lswitchBefore : lswitchListBefore) {
+                                int i = 0;
+                                for (; i < lswitchListUpdated.size(); i++) {
+                                    if (lswitchBefore.getHwvtepNodeName().equals(lswitchListUpdated.get(i).getHwvtepNodeName())) {
+                                        break;
+                                    }
+                                }
+                                if (i == lswitchListUpdated.size()) {
+                                    lswitchListRemoved.add(lswitchBefore);
                                 }
                             }
-                            if (i == lswitchListUpdated.size()) {
-                                lswitchListRemoved.add(lswitchBefore);
-                            }
+                        } else {
+                            lswitchListRemoved.addAll(lswitchListBefore);
                         }
                         if (!lswitchListRemoved.isEmpty()) {
                             result.put(key, lswitchListRemoved);
index 9490371119fe312b7c9ecd17334722eb6b239178..e67b9d38fed89478b5575ff3f76ce3f59df1845b 100644 (file)
@@ -116,16 +116,20 @@ public class McastMacsLocalRemoveCommand extends AbstractTransactCommand {
                             macListBefore.removeAll(macListUpdated);
                         }
                         //then exclude updated localMcastMacs
-                        for (LocalMcastMacs macBefore: macListBefore) {
-                            int i = 0;
-                            for(; i < macListUpdated.size(); i++) {
-                                if (macBefore.getKey().equals(macListUpdated.get(i).getKey())) {
-                                    break;
+                        if (macListUpdated != null) {
+                            for (LocalMcastMacs macBefore : macListBefore) {
+                                int i = 0;
+                                for (; i < macListUpdated.size(); i++) {
+                                    if (macBefore.getKey().equals(macListUpdated.get(i).getKey())) {
+                                        break;
+                                    }
+                                }
+                                if (i == macListUpdated.size()) {
+                                    macListRemoved.add(macBefore);
                                 }
                             }
-                            if (i == macListUpdated.size()) {
-                                macListRemoved.add(macBefore);
-                            }
+                        } else {
+                            macListRemoved.addAll(macListBefore);
                         }
                         if (!macListRemoved.isEmpty()) {
                             result.put(key, macListRemoved);
index a02eae68f7fead7ddfb2a85df32cfef307eadd44..4745f5e5f5a3e9c57b656165217c427471bfb8a3 100644 (file)
@@ -116,16 +116,20 @@ public class McastMacsRemoteRemoveCommand extends AbstractTransactCommand {
                             macListBefore.removeAll(macListUpdated);
                         }
                         //then exclude updated remoteMcastMacs
-                        for (RemoteMcastMacs macBefore: macListBefore) {
-                            int i = 0;
-                            for(; i < macListUpdated.size(); i++) {
-                                if (macBefore.getKey().equals(macListUpdated.get(i).getKey())) {
-                                    break;
+                        if (macListUpdated != null) {
+                            for (RemoteMcastMacs macBefore : macListBefore) {
+                                int i = 0;
+                                for (; i < macListUpdated.size(); i++) {
+                                    if (macBefore.getKey().equals(macListUpdated.get(i).getKey())) {
+                                        break;
+                                    }
+                                }
+                                if (i == macListUpdated.size()) {
+                                    macListRemoved.add(macBefore);
                                 }
                             }
-                            if (i == macListUpdated.size()) {
-                                macListRemoved.add(macBefore);
-                            }
+                        } else {
+                            macListRemoved.addAll(macListBefore);
                         }
                         if (!macListRemoved.isEmpty()) {
                             result.put(key, macListRemoved);
index 271b28c0bf42e3cfc705b2171f8021c10a1999b0..711a365ef539ea28a96bdbae3ffe0a98a5b65bed 100644 (file)
@@ -29,6 +29,7 @@ import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocator;
 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocatorSet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
 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.hwvtep.physical.locator.set.attributes.LocatorSet;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
@@ -146,16 +147,20 @@ public class TransactUtils {
                 HwvtepPhysicalLocatorAugmentation locatorAugmentation = operationalLocatorOptional.get();
                 locatorUuid = new UUID(locatorAugmentation.getPhysicalLocatorUuid().getValue());
             } else {
-                //if no, get it from config DS and create id
-                Optional<TerminationPoint> configLocatorOptional =
-                        readNodeFromConfig(hwvtepOperationalState.getReadWriteTransaction(), iid);
-                if (configLocatorOptional.isPresent()) {
-                    HwvtepPhysicalLocatorAugmentation locatorAugmentation =
-                            configLocatorOptional.get().getAugmentation(HwvtepPhysicalLocatorAugmentation.class);
-                    locatorUuid = TransactUtils.createPhysicalLocator(transaction, locatorAugmentation);
-                } else {
-                    LOG.warn("Create or update localMcastMac: No physical locator found in operational datastore!"
-                            + "Its indentifier is {}", locator.getLocatorRef().getValue());
+                locatorUuid = hwvtepOperationalState.getPhysicalLocatorInFlight(iid);
+                if (locatorUuid == null) {
+                    //if no, get it from config DS and create id
+                    Optional<TerminationPoint> configLocatorOptional =
+                            readNodeFromConfig(hwvtepOperationalState.getReadWriteTransaction(), iid);
+                    if (configLocatorOptional.isPresent()) {
+                        HwvtepPhysicalLocatorAugmentation locatorAugmentation =
+                                configLocatorOptional.get().getAugmentation(HwvtepPhysicalLocatorAugmentation.class);
+                        locatorUuid = TransactUtils.createPhysicalLocator(transaction, locatorAugmentation);
+                        hwvtepOperationalState.setPhysicalLocatorInFlight(iid, locatorUuid);
+                    } else {
+                        LOG.warn("Create or update localMcastMac: No physical locator found in operational datastore!"
+                                + "Its indentifier is {}", locator.getLocatorRef().getValue());
+                    }
                 }
             }
             if (locatorUuid != null) {
@@ -192,11 +197,17 @@ public class TransactUtils {
         }
     }
 
+    static String sanitizeUUID(HwvtepNodeName hwvtepNodeName) {
+        //ovs is not accepting '-' in the named uuids
+        return hwvtepNodeName.getValue().replaceAll("-", "_");
+    }
+
     public static String getLogicalSwitchId(LogicalSwitches lswitch){
-        return HwvtepSouthboundConstants.LOGICALSWITCH_UUID_PREFIX+lswitch.getHwvtepNodeName().getValue();
+        return HwvtepSouthboundConstants.LOGICALSWITCH_UUID_PREFIX + sanitizeUUID(lswitch.getHwvtepNodeName());
     }
 
     public static UUID getLogicalSwitchUUID(InstanceIdentifier<LogicalSwitches> lswitchIid){
-        return new UUID(HwvtepSouthboundConstants.LOGICALSWITCH_UUID_PREFIX+lswitchIid.firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue());
+        return new UUID(HwvtepSouthboundConstants.LOGICALSWITCH_UUID_PREFIX +
+                sanitizeUUID(lswitchIid.firstKeyOf(LogicalSwitches.class).getHwvtepNodeName()));
     }
 }
index c563c675ab2d35057329d90241f19086fc538d0d..9b1556169a3ad89804effde6e30ad397e2bc95f4 100644 (file)
@@ -115,16 +115,20 @@ public class UcastMacsLocalRemoveCommand extends AbstractTransactCommand {
                             macListBefore.removeAll(macListUpdated);
                         }
                         //then exclude updated remoteUcastMacs
-                        for (LocalUcastMacs macBefore: macListBefore) {
-                            int i = 0;
-                            for(; i < macListUpdated.size(); i++) {
-                                if (macBefore.getKey().equals(macListUpdated.get(i).getKey())) {
-                                    break;
+                        if (macListUpdated != null) {
+                            for (LocalUcastMacs macBefore : macListBefore) {
+                                int i = 0;
+                                for (; i < macListUpdated.size(); i++) {
+                                    if (macBefore.getKey().equals(macListUpdated.get(i).getKey())) {
+                                        break;
+                                    }
+                                }
+                                if (i == macListUpdated.size()) {
+                                    macListRemoved.add(macBefore);
                                 }
                             }
-                            if (i == macListUpdated.size()) {
-                                macListRemoved.add(macBefore);
-                            }
+                        } else {
+                            macListRemoved.addAll(macListBefore);
                         }
                         if (!macListRemoved.isEmpty()) {
                             result.put(key, macListRemoved);
index 3126431b9696ce459e3570a9a74c50a8cfa39d31..fb478e6835680118de5f643d56f5e264a6d70a85 100644 (file)
@@ -115,16 +115,20 @@ public class UcastMacsRemoteRemoveCommand extends AbstractTransactCommand {
                             macListBefore.removeAll(macListUpdated);
                         }
                         //then exclude updated remoteUcastMacs
-                        for (RemoteUcastMacs macBefore: macListBefore) {
-                            int i = 0;
-                            for(; i < macListUpdated.size(); i++) {
-                                if (macBefore.getKey().equals(macListUpdated.get(i).getKey())) {
-                                    break;
+                        if (macListUpdated != null) {
+                            for (RemoteUcastMacs macBefore : macListBefore) {
+                                int i = 0;
+                                for (; i < macListUpdated.size(); i++) {
+                                    if (macBefore.getKey().equals(macListUpdated.get(i).getKey())) {
+                                        break;
+                                    }
+                                }
+                                if (i == macListUpdated.size()) {
+                                    macListRemoved.add(macBefore);
                                 }
                             }
-                            if (i == macListUpdated.size()) {
-                                macListRemoved.add(macBefore);
-                            }
+                        } else {
+                            macListRemoved.addAll(macListBefore);
                         }
                         if (!macListRemoved.isEmpty()) {
                             result.put(key, macListRemoved);
index 509354e78491ef26dc23d73afbc37bca12bf2bca..3a2758d22c8b43b199fbd28cb47d624c33cf8823 100644 (file)
@@ -127,15 +127,19 @@ public class UcastMacsRemoteUpdateCommand extends AbstractTransactCommand {
             } else {
                 //TODO: need to optimize by eliminating reading Configuration datastore
                 //if no, get it from config DS and create id
-                Optional<TerminationPoint> configLocatorOptional =
-                        TransactUtils.readNodeFromConfig(getOperationalState().getReadWriteTransaction(), iid);
-                if (configLocatorOptional.isPresent()) {
-                    HwvtepPhysicalLocatorAugmentation locatorAugmentation =
-                            configLocatorOptional.get().getAugmentation(HwvtepPhysicalLocatorAugmentation.class);
-                    locatorUuid = TransactUtils.createPhysicalLocator(transaction, locatorAugmentation);
-                } else {
-                    LOG.warn("Create or update remoteUcastMac: No physical locator found in operational datastore!"
-                            + "Its indentifier is {}", inputMac.getLocatorRef().getValue());
+                locatorUuid = getOperationalState().getPhysicalLocatorInFlight(iid);
+                if (locatorUuid == null) {
+                    Optional<TerminationPoint> configLocatorOptional =
+                            TransactUtils.readNodeFromConfig(getOperationalState().getReadWriteTransaction(), iid);
+                    if (configLocatorOptional.isPresent()) {
+                        HwvtepPhysicalLocatorAugmentation locatorAugmentation =
+                                configLocatorOptional.get().getAugmentation(HwvtepPhysicalLocatorAugmentation.class);
+                        locatorUuid = TransactUtils.createPhysicalLocator(transaction, locatorAugmentation);
+                        getOperationalState().setPhysicalLocatorInFlight(iid, locatorUuid);
+                    } else {
+                        LOG.warn("Create or update remoteUcastMac: No physical locator found in operational datastore!"
+                                + "Its indentifier is {}", inputMac.getLocatorRef().getValue());
+                    }
                 }
             }
             if (locatorUuid != null) {
index f8eabbcd5d36221bcad651bd3c064a71ca54d63e..2089a1af4ddca54ab4326d24dcf8837f64e6f472 100644 (file)
@@ -28,7 +28,6 @@ public class HwvtepOperationalCommandAggregator implements TransactionCommand {
         commands.add(new HwvtepManagerUpdateCommand(key, updates, dbSchema));
         commands.add(new HwvtepManagerRemoveCommand(key, updates, dbSchema));
         commands.add(new HwvtepLogicalSwitchUpdateCommand(key, updates, dbSchema));
-        commands.add(new HwvtepLogicalSwitchRemoveCommand(key, updates, dbSchema));
         commands.add(new HwvtepPhysicalPortUpdateCommand(key, updates, dbSchema));
         commands.add(new HwvtepPhysicalPortRemoveCommand(key, updates, dbSchema));
         commands.add(new HwvtepPhysicalLocatorUpdateCommand(key, updates, dbSchema));
@@ -40,6 +39,7 @@ public class HwvtepOperationalCommandAggregator implements TransactionCommand {
         commands.add(new HwvtepMcastMacsLocalUpdateCommand(key, updates, dbSchema));
         commands.add(new HwvtepMcastMacsRemoteUpdateCommand(key, updates, dbSchema));
         commands.add(new HwvtepMacEntriesRemoveCommand(key, updates, dbSchema));
+        commands.add(new HwvtepLogicalSwitchRemoveCommand(key, updates, dbSchema));
     }
 
     @Override