Merge "Infra for running ovs dockers"
authorAnil Vishnoi <vishnoianil@gmail.com>
Mon, 23 May 2016 22:16:20 +0000 (22:16 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 23 May 2016 22:16:20 +0000 (22:16 +0000)
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepConnectionManager.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionManager.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundMapper.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachRemovedCommand.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachUpdateCommand.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/reconciliation/configuration/BridgeConfigReconciliationTask.java [new file with mode: 0644]
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbAutoAttachRemovedCommand.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/transactions/md/OvsdbAutoAttachUpdateCommand.java
southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionManagerTest.java
southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/reconciliation/configuration/BridgeConfigReconciliationTaskTest.java [new file with mode: 0644]

index 79fb3a7aa021388ab601b9aa119c4a78bb1b3dd3..6ccb3f5990a68b584794ddc70942d83f70edf825 100644 (file)
@@ -217,10 +217,11 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
             if(hwvtepGlobal.getConnectionInfo() != null) {
                 return getConnectionInstance(hwvtepGlobal.getConnectionInfo());
             } else {
-                // TODO: Case of user configured connection
-                return null; //for now
+                //TODO: Case of user configured connection for now
+                //TODO: We could get it from Managers also.
+                return null;
             }
-        } //TODO: We could get it from Managers also.
+        }
         else if(pSwitchNode != null){
             return getConnectionInstance(pSwitchNode);
         } else {
index 4b783c0fa38f53018289fbf313355c7839af4232..5115a4e033a373475334c447d1b8d923ed44b6aa 100644 (file)
@@ -47,6 +47,7 @@ import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
 import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
 import org.opendaylight.ovsdb.southbound.reconciliation.ReconciliationManager;
 import org.opendaylight.ovsdb.southbound.reconciliation.ReconciliationTask;
+import org.opendaylight.ovsdb.southbound.reconciliation.configuration.BridgeConfigReconciliationTask;
 import org.opendaylight.ovsdb.southbound.reconciliation.connection.ConnectionReconciliationTask;
 import org.opendaylight.ovsdb.southbound.transactions.md.OvsdbNodeRemoveCommand;
 import org.opendaylight.ovsdb.southbound.transactions.md.TransactionCommand;
@@ -138,6 +139,8 @@ public class OvsdbConnectionManager implements OvsdbConnectionListener, AutoClos
             ovsdbConnectionInstance.disconnect();
 
             removeConnectionInstance(key);
+
+            stopBridgeConfigReconciliationIfActive(ovsdbConnectionInstance.getInstanceIdentifier());
         }
 
         ovsdbConnectionInstance = new OvsdbConnectionInstance(key, externalClient, txInvoker,
@@ -170,6 +173,7 @@ public class OvsdbConnectionManager implements OvsdbConnectionListener, AutoClos
             //Controller initiated connection can be terminated from switch side.
             //So cleanup the instance identifier cache.
             removeInstanceIdentifier(key);
+            stopBridgeConfigReconciliationIfActive(ovsdbConnectionInstance.getInstanceIdentifier());
             retryConnection(ovsdbConnectionInstance.getInstanceIdentifier(),
                     ovsdbConnectionInstance.getOvsdbNodeAugmentation(),
                     ConnectionReconciliationTriggers.ON_DISCONNECT);
@@ -215,6 +219,8 @@ public class OvsdbConnectionManager implements OvsdbConnectionListener, AutoClos
             client.disconnect();
 
             removeInstanceIdentifier(ovsdbNode.getConnectionInfo());
+
+            stopBridgeConfigReconciliationIfActive(client.getInstanceIdentifier());
         } else {
             LOG.debug("disconnect : connection instance not found for {}",ovsdbNode.getConnectionInfo());
         }
@@ -351,6 +357,16 @@ public class OvsdbConnectionManager implements OvsdbConnectionListener, AutoClos
                 ovsdbNode);
         reconciliationManager.dequeue(task);
     }
+
+    public void stopBridgeConfigReconciliationIfActive(InstanceIdentifier<?> iid) {
+        final ReconciliationTask task = new BridgeConfigReconciliationTask(
+                reconciliationManager,
+                this,
+                iid,
+                null);
+        reconciliationManager.dequeue(task);
+    }
+
     private void handleOwnershipChanged(EntityOwnershipChange ownershipChange) {
         OvsdbConnectionInstance ovsdbConnectionInstance = getConnectionInstanceFromEntity(ownershipChange.getEntity());
         LOG.debug("handleOwnershipChanged: {} event received for device {}",
@@ -399,6 +415,7 @@ public class OvsdbConnectionManager implements OvsdbConnectionListener, AutoClos
             //so register for monitor callbacks
             ovsdbConnectionInstance.registerCallbacks();
 
+            reconcileBridgeConfigurations(ovsdbConnectionInstance);
         } else {
             //You were owner of the device, but now you are not. With the current ownership
             //grant mechanism, this scenario should not occur. Because this scenario will occur
@@ -589,6 +606,14 @@ public class OvsdbConnectionManager implements OvsdbConnectionListener, AutoClos
         }
     }
 
+    private void reconcileBridgeConfigurations(final OvsdbConnectionInstance client) {
+        final InstanceIdentifier<Node> nodeIid = client.getInstanceIdentifier();
+        final ReconciliationTask task = new BridgeConfigReconciliationTask(
+                reconciliationManager, OvsdbConnectionManager.this, nodeIid, client);
+
+        reconciliationManager.enqueue(task);
+    }
+
     private class OvsdbDeviceEntityOwnershipListener implements EntityOwnershipListener {
         private OvsdbConnectionManager cm;
         private EntityOwnershipListenerRegistration listenerRegistration;
index a21f1e4c51e821d3ad041cef6e058ce721d0baf5..78512a81623b758e7ae6a7421a6eb7e4a514a7b9 100644 (file)
@@ -89,13 +89,22 @@ public class SouthboundMapper {
         return new IpAddress(ipv6);
     }
 
-    public static InstanceIdentifier<Node> createInstanceIdentifier(NodeId nodeId) {
+    public static InstanceIdentifier<Topology> createTopologyInstanceIdentifier() {
         return InstanceIdentifier
                 .create(NetworkTopology.class)
-                .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
+                .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
+    }
+
+    public static InstanceIdentifier<Node> createInstanceIdentifier(NodeId nodeId) {
+        return createTopologyInstanceIdentifier()
                 .child(Node.class,new NodeKey(nodeId));
     }
 
+    public static InstanceIdentifier<OvsdbBridgeAugmentation> createBridgeInstanceIdentifier(OvsdbConnectionInstance client, String bridgeName) {
+        return createInstanceIdentifier(client, bridgeName)
+                .augmentation(OvsdbBridgeAugmentation.class);
+    }
+
     public static InstanceIdentifier<Node> createInstanceIdentifier(OvsdbConnectionInstance client,Bridge bridge) {
         InstanceIdentifier<Node> iid;
         if (bridge.getExternalIdsColumn() != null
@@ -104,14 +113,7 @@ public class SouthboundMapper {
             String iidString = bridge.getExternalIdsColumn().getData().get(SouthboundConstants.IID_EXTERNAL_ID_KEY);
             iid = (InstanceIdentifier<Node>) SouthboundUtil.deserializeInstanceIdentifier(iidString);
         } else {
-            String nodeString = client.getNodeKey().getNodeId().getValue()
-                    + "/bridge/" + bridge.getName();
-            NodeId nodeId = new NodeId(new Uri(nodeString));
-            NodeKey nodeKey = new NodeKey(nodeId);
-            iid = InstanceIdentifier.builder(NetworkTopology.class)
-                    .child(Topology.class,new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
-                    .child(Node.class,nodeKey)
-                    .build();
+            iid = createInstanceIdentifier(client, bridge.getName());
         }
         return iid;
     }
@@ -125,19 +127,20 @@ public class SouthboundMapper {
             String iidString = controller.getExternalIdsColumn().getData().get(SouthboundConstants.IID_EXTERNAL_ID_KEY);
             iid = (InstanceIdentifier<Node>) SouthboundUtil.deserializeInstanceIdentifier(iidString);
         } else {
-            // TODO retrieve bridge name
-            String nodeString = client.getNodeKey().getNodeId().getValue()
-                    + "/bridge/" + bridgeName;
-            NodeId nodeId = new NodeId(new Uri(nodeString));
-            NodeKey nodeKey = new NodeKey(nodeId);
-            iid = InstanceIdentifier.builder(NetworkTopology.class)
-                    .child(Topology.class,new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
-                    .child(Node.class,nodeKey)
-                    .build();
+            iid = createInstanceIdentifier(client, bridgeName);
         }
         return iid;
     }
 
+    public static InstanceIdentifier<Node> createInstanceIdentifier(
+            OvsdbConnectionInstance client, String bridgeName) {
+        String nodeString = client.getNodeKey().getNodeId().getValue()
+                + "/bridge/" + bridgeName;
+        NodeId nodeId = new NodeId(new Uri(nodeString));
+        return createInstanceIdentifier(nodeId);
+
+    }
+
     public static NodeId createManagedNodeId(InstanceIdentifier<Node> iid) {
         NodeKey nodeKey = iid.firstKeyOf(Node.class, NodeKey.class);
         return nodeKey.getNodeId();
index feb537f6183d9042a4928efcf3e49fc2459154c0..a4c175c7223f2b9ccdcc188d5a593abf5dd94ab1 100644 (file)
@@ -63,33 +63,28 @@ public class AutoAttachRemovedCommand implements TransactCommand {
                          Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> original,
                          Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> updated) {
 
-        // FIXME: Remove if loop after ovs community supports external_ids column in AutoAttach Table
-        if (true) {
-            try {
-                throw new UnsupportedOperationException("CRUD operations not supported from ODL for auto_attach column for"
-                        + " this version of ovsdb schema due to missing external_ids column");
-            } catch (UnsupportedOperationException e) {
-                LOG.debug(e.getMessage());
-            }
-            return;
-        }
-
-        for (Map.Entry<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> originalEntry : original.entrySet()) {
-            InstanceIdentifier<OvsdbNodeAugmentation> ovsdbNodeIid = originalEntry.getKey();
-            OvsdbNodeAugmentation ovsdbNodeAugmentation = originalEntry.getValue();
-            OvsdbNodeAugmentation deletedOvsdbNodeAugmentation = updated.get(ovsdbNodeIid);
+        for (final Map.Entry<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> originalEntry : original.entrySet()) {
+            final InstanceIdentifier<OvsdbNodeAugmentation> ovsdbNodeIid = originalEntry.getKey();
+            final OvsdbNodeAugmentation ovsdbNodeAugmentation = originalEntry.getValue();
+            final OvsdbNodeAugmentation deletedOvsdbNodeAugmentation = updated.get(ovsdbNodeIid);
 
             if (ovsdbNodeAugmentation != null && deletedOvsdbNodeAugmentation != null) {
-                List<Autoattach> origAutoattachList = ovsdbNodeAugmentation.getAutoattach();
-                List<Autoattach> deletedAutoattachList = deletedOvsdbNodeAugmentation.getAutoattach();
+                final List<Autoattach> origAutoattachList = ovsdbNodeAugmentation.getAutoattach();
+                final List<Autoattach> deletedAutoattachList = deletedOvsdbNodeAugmentation.getAutoattach();
                 if(origAutoattachList != null && !origAutoattachList.isEmpty() &&
                         (deletedAutoattachList == null || deletedAutoattachList.isEmpty())) {
 
-                    OvsdbNodeAugmentation currentOvsdbNode =
+                    if (true) {
+                        // FIXME: Remove if loop after ovs community supports external_ids column in AutoAttach Table
+                        LOG.info("UNSUPPORTED FUNCTIONALITY: Auto Attach related CRUD operations are not supported for"
+                                + " this version of OVSDB schema due to missing external_ids column.");
+                        return;
+                    }
+                    final OvsdbNodeAugmentation currentOvsdbNode =
                             state.getBridgeNode(ovsdbNodeIid).get().getAugmentation(OvsdbNodeAugmentation.class);
-                    List<Autoattach> currentAutoAttach = currentOvsdbNode.getAutoattach();
-                    for (Autoattach origAutoattach : origAutoattachList) {
-                        Uri autoAttachId = origAutoattach.getAutoattachId();
+                    final List<Autoattach> currentAutoAttach = currentOvsdbNode.getAutoattach();
+                    for (final Autoattach origAutoattach : origAutoattachList) {
+                        final Uri autoAttachId = origAutoattach.getAutoattachId();
                         deleteAutoAttach(transaction, ovsdbNodeIid, getAutoAttachUuid(currentAutoAttach, autoAttachId));
                     }
                 }
@@ -102,17 +97,17 @@ public class AutoAttachRemovedCommand implements TransactCommand {
             Uuid autoattachUuid) {
 
         LOG.debug("Received request to delete Autoattach entry {}", autoattachUuid);
-        OvsdbBridgeAugmentation bridgeAugmentation = getBridge(ovsdbNodeIid, autoattachUuid);
+        final OvsdbBridgeAugmentation bridgeAugmentation = getBridge(ovsdbNodeIid, autoattachUuid);
         if (autoattachUuid != null && bridgeAugmentation != null) {
-            UUID uuid = new UUID(autoattachUuid.getValue());
-            AutoAttach autoattach = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), AutoAttach.class, null);
+            final UUID uuid = new UUID(autoattachUuid.getValue());
+            final AutoAttach autoattach = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), AutoAttach.class, null);
             transaction.add(op.delete(autoattach.getSchema())
                     .where(autoattach.getUuidColumn().getSchema().opEqual(uuid))
                     .build());
             transaction.add(op.comment("AutoAttach: Deleting {} " + uuid
                     + " attached to " + bridgeAugmentation.getBridgeName().getValue()));
 
-            Bridge bridge = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
+            final Bridge bridge = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
                     Bridge.class,null);
 
             transaction.add(op.mutate(bridge.getSchema())
@@ -131,7 +126,7 @@ public class AutoAttachRemovedCommand implements TransactCommand {
 
     private Uuid getAutoAttachUuid(List<Autoattach> currentAutoAttach, Uri autoAttachId) {
         if (currentAutoAttach != null && !currentAutoAttach.isEmpty()) {
-            for (Autoattach autoAttach : currentAutoAttach) {
+            for (final Autoattach autoAttach : currentAutoAttach) {
                 if (autoAttach.getAutoattachId().equals(autoAttachId)) {
                     return autoAttach.getAutoattachUuid();
                 }
@@ -145,16 +140,16 @@ public class AutoAttachRemovedCommand implements TransactCommand {
             return null;
         }
         OvsdbBridgeAugmentation bridge = null;
-        InstanceIdentifier<Node> nodeIid = key.firstIdentifierOf(Node.class);
+        final InstanceIdentifier<Node> nodeIid = key.firstIdentifierOf(Node.class);
         try (ReadOnlyTransaction transaction = SouthboundProvider.getDb().newReadOnlyTransaction()) {
-            Optional<Node> nodeOptional = transaction.read(LogicalDatastoreType.OPERATIONAL, nodeIid).get();
+            final Optional<Node> nodeOptional = transaction.read(LogicalDatastoreType.OPERATIONAL, nodeIid).get();
             if (nodeOptional.isPresent()) {
-                List<ManagedNodeEntry> managedNodes = nodeOptional.get().getAugmentation(OvsdbNodeAugmentation.class).getManagedNodeEntry();
-                for (ManagedNodeEntry managedNode : managedNodes) {
-                    OvsdbBridgeRef ovsdbBridgeRef = managedNode.getBridgeRef();
-                    InstanceIdentifier<OvsdbBridgeAugmentation> brIid = ovsdbBridgeRef.getValue()
+                final List<ManagedNodeEntry> managedNodes = nodeOptional.get().getAugmentation(OvsdbNodeAugmentation.class).getManagedNodeEntry();
+                for (final ManagedNodeEntry managedNode : managedNodes) {
+                    final OvsdbBridgeRef ovsdbBridgeRef = managedNode.getBridgeRef();
+                    final InstanceIdentifier<OvsdbBridgeAugmentation> brIid = ovsdbBridgeRef.getValue()
                             .firstIdentifierOf(Node.class).augmentation(OvsdbBridgeAugmentation.class);
-                    Optional<OvsdbBridgeAugmentation> optionalBridge = transaction.read(LogicalDatastoreType.OPERATIONAL, brIid).get();
+                    final Optional<OvsdbBridgeAugmentation> optionalBridge = transaction.read(LogicalDatastoreType.OPERATIONAL, brIid).get();
                     bridge = optionalBridge.orNull();
                     if(bridge != null && bridge.getAutoAttach() != null
                             && bridge.getAutoAttach().equals(aaUuid)) {
index 4c320094d49ba36d477c1dc21e355f4d0e44a783..ec684a190fdb1a68addfb396f04fc7d25cdb6528 100644 (file)
@@ -69,18 +69,7 @@ public class AutoAttachUpdateCommand implements TransactCommand {
     private void execute(TransactionBuilder transaction, BridgeOperationalState state,
                          Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> createdOrUpdated) {
 
-        // FIXME: Fix if loop after ovs community supports external_ids column in AutoAttach Table
-        if (true) {
-            try {
-                throw new UnsupportedOperationException("CRUD operations not supported from ODL for auto_attach column for"
-                        + " this version of ovsdb schema due to missing external_ids column");
-            } catch (UnsupportedOperationException e) {
-                LOG.debug(e.getMessage());
-            }
-            return;
-        }
-
-        for (Entry<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> ovsdbNodeEntry
+        for (final Entry<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> ovsdbNodeEntry
                 : createdOrUpdated.entrySet()) {
             updateAutoAttach(transaction, state, ovsdbNodeEntry.getKey(), ovsdbNodeEntry.getValue());
         }
@@ -90,16 +79,22 @@ public class AutoAttachUpdateCommand implements TransactCommand {
             InstanceIdentifier<OvsdbNodeAugmentation> iid,
             OvsdbNodeAugmentation ovsdbNode) {
 
-        List<Autoattach> autoAttachList = ovsdbNode.getAutoattach();
-        if (state.getBridgeNode(iid).isPresent()) {
+        if (!state.getBridgeNode(iid).isPresent()) {
             return;
         }
-        OvsdbNodeAugmentation currentOvsdbNode = state.getBridgeNode(iid).get().getAugmentation(OvsdbNodeAugmentation.class);
-        List<Autoattach> currentAutoAttach = currentOvsdbNode.getAutoattach();
-
+        final List<Autoattach> autoAttachList = ovsdbNode.getAutoattach();
         if (autoAttachList != null) {
-            for (Autoattach autoAttach : autoAttachList) {
-                AutoAttach autoAttachWrapper = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), AutoAttach.class);
+            if (true) {
+                // FIXME: Remove if loop after ovs community supports external_ids column in AutoAttach Table
+                LOG.info("UNSUPPORTED FUNCTIONALITY: Auto Attach related CRUD operations are not supported for"
+                        + " this version of OVSDB schema due to missing external_ids column.");
+                return;
+            }
+
+            final OvsdbNodeAugmentation currentOvsdbNode = state.getBridgeNode(iid).get().getAugmentation(OvsdbNodeAugmentation.class);
+            final List<Autoattach> currentAutoAttach = currentOvsdbNode.getAutoattach();
+            for (final Autoattach autoAttach : autoAttachList) {
+                final AutoAttach autoAttachWrapper = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), AutoAttach.class);
                 if (autoAttach.getSystemName() != null) {
                     autoAttachWrapper.setSystemName(autoAttach.getSystemName());
                 }
@@ -107,20 +102,20 @@ public class AutoAttachUpdateCommand implements TransactCommand {
                     autoAttachWrapper.setSystemDescription(autoAttach.getSystemDescription());
                 }
 
-                List<Mappings> mappingsList = autoAttach.getMappings();
+                final List<Mappings> mappingsList = autoAttach.getMappings();
                 if (mappingsList != null && !mappingsList.isEmpty()) {
-                    Map<Long, Long> newMappings = new HashMap<>();
-                    for (Mappings mappings : mappingsList) {
-                        Long mappingsValue = new Long(mappings.getMappingsValue().toString());
+                    final Map<Long, Long> newMappings = new HashMap<>();
+                    for (final Mappings mappings : mappingsList) {
+                        final Long mappingsValue = new Long(mappings.getMappingsValue().toString());
                         newMappings.put(mappings.getMappingsKey(), mappingsValue);
                     }
                     autoAttachWrapper.setMappings(newMappings);
                 }
 
-                List<AutoattachExternalIds> externalIds = autoAttach.getAutoattachExternalIds();
-                Map<String, String> externalIdsMap = new HashMap<>();
+                final List<AutoattachExternalIds> externalIds = autoAttach.getAutoattachExternalIds();
+                final Map<String, String> externalIdsMap = new HashMap<>();
                 if (externalIds != null) {
-                    for (AutoattachExternalIds externalId : externalIds) {
+                    for (final AutoattachExternalIds externalId : externalIds) {
                         externalIdsMap.put(externalId.getAutoattachExternalIdKey(), externalId.getAutoattachExternalIdValue());
                     }
                 }
@@ -132,10 +127,10 @@ public class AutoAttachUpdateCommand implements TransactCommand {
 //                    LOG.warn("Incomplete AutoAttach external IDs");
 //                }
 
-                Uuid aaUuid = getAutoAttachUuid(currentAutoAttach, autoAttach.getAutoattachId());
+                final Uuid aaUuid = getAutoAttachUuid(currentAutoAttach, autoAttach.getAutoattachId());
                 if (aaUuid != null) {
-                    UUID uuid = new UUID(aaUuid.getValue());
-                    AutoAttach newAutoAttach = TyperUtils.getTypedRowWrapper(
+                    final UUID uuid = new UUID(aaUuid.getValue());
+                    final AutoAttach newAutoAttach = TyperUtils.getTypedRowWrapper(
                             transaction.getDatabaseSchema(), AutoAttach.class, null);
                     newAutoAttach.getUuidColumn().setData(uuid);
                     LOG.trace("Updating autoattach table entries {}", uuid);
@@ -143,11 +138,11 @@ public class AutoAttachUpdateCommand implements TransactCommand {
                             .where(newAutoAttach.getUuidColumn().getSchema().opEqual(uuid)).build());
                     transaction.add(op.comment("Updating AutoAttach table: " + uuid));
                 } else {
-                    Uri bridgeUri = autoAttach.getBridgeId();
-                    String namedUuid = SouthboundMapper.getRandomUUID();
-                    Bridge bridge = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), Bridge.class);
+                    final Uri bridgeUri = autoAttach.getBridgeId();
+                    final String namedUuid = SouthboundMapper.getRandomUUID();
+                    final Bridge bridge = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), Bridge.class);
                     transaction.add(op.insert(autoAttachWrapper).withId(namedUuid));
-                    OvsdbBridgeAugmentation ovsdbBridgeAugmentation = getBridge(iid, bridgeUri);
+                    final OvsdbBridgeAugmentation ovsdbBridgeAugmentation = getBridge(iid, bridgeUri);
                     if (ovsdbBridgeAugmentation != null) {
                         bridge.setName(ovsdbBridgeAugmentation.getBridgeName().getValue());
                         bridge.setAutoAttach(Sets.newHashSet(new UUID(namedUuid)));
@@ -168,7 +163,7 @@ public class AutoAttachUpdateCommand implements TransactCommand {
 
     private OvsdbBridgeAugmentation getBridge(InstanceIdentifier<OvsdbNodeAugmentation> key,
             Uri bridgeUri) {
-        InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid = InstanceIdentifier
+        final InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid = InstanceIdentifier
                 .create(NetworkTopology.class)
                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
                 .child(Node.class, new NodeKey(new NodeId(bridgeUri)))
@@ -176,7 +171,7 @@ public class AutoAttachUpdateCommand implements TransactCommand {
 
         OvsdbBridgeAugmentation bridge = null;
         try (ReadOnlyTransaction transaction = SouthboundProvider.getDb().newReadOnlyTransaction()) {
-            Optional<OvsdbBridgeAugmentation> bridgeOptional = transaction.read(LogicalDatastoreType.OPERATIONAL, bridgeIid).get();
+            final Optional<OvsdbBridgeAugmentation> bridgeOptional = transaction.read(LogicalDatastoreType.OPERATIONAL, bridgeIid).get();
             if (bridgeOptional.isPresent()) {
                 bridge = bridgeOptional.get();
             }
@@ -188,7 +183,7 @@ public class AutoAttachUpdateCommand implements TransactCommand {
 
     private Uuid getAutoAttachUuid(List<Autoattach> currentAutoAttach, Uri autoattachId) {
         if (currentAutoAttach != null && !currentAutoAttach.isEmpty()) {
-            for (Autoattach autoAttach : currentAutoAttach) {
+            for (final Autoattach autoAttach : currentAutoAttach) {
                 if (autoAttach.getAutoattachId().equals(autoattachId)) {
                     return autoAttach.getAutoattachUuid();
                 }
diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/reconciliation/configuration/BridgeConfigReconciliationTask.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/reconciliation/configuration/BridgeConfigReconciliationTask.java
new file mode 100644 (file)
index 0000000..0f60404
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2016 , NEC Corporation and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.ovsdb.southbound.reconciliation.configuration;
+
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
+import org.opendaylight.ovsdb.southbound.OvsdbConnectionManager;
+import org.opendaylight.ovsdb.southbound.SouthboundConstants;
+import org.opendaylight.ovsdb.southbound.SouthboundMapper;
+import org.opendaylight.ovsdb.southbound.ovsdb.transact.BridgeOperationalState;
+import org.opendaylight.ovsdb.southbound.ovsdb.transact.DataChangesManagedByOvsdbNodeEvent;
+import org.opendaylight.ovsdb.southbound.ovsdb.transact.TransactCommandAggregator;
+import org.opendaylight.ovsdb.southbound.reconciliation.ReconciliationManager;
+import org.opendaylight.ovsdb.southbound.reconciliation.ReconciliationTask;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryKey;
+import org.opendaylight.yang.gen.v1.urn.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.topology.Node;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
+
+/**
+ * Configuration Reconciliation task to reconcile existing bridge configurations in the config datastore and the
+ * switch when the latter is up and connected to the controller.
+ * Created by Vinh Nguyen (vinh.nguyen@hcl.com) on 3/21/16.
+ */
+public class BridgeConfigReconciliationTask extends ReconciliationTask{
+
+    private static final Logger LOG = LoggerFactory.getLogger(BridgeConfigReconciliationTask.class);
+    private final OvsdbConnectionInstance connectionInstance;
+
+    public BridgeConfigReconciliationTask(ReconciliationManager reconciliationManager, OvsdbConnectionManager
+            connectionManager, InstanceIdentifier<?> nodeIid, OvsdbConnectionInstance connectionInstance) {
+        super(reconciliationManager, connectionManager, nodeIid, null);
+        this.connectionInstance = connectionInstance;
+
+    }
+
+    @Override
+    public boolean reconcileConfiguration(OvsdbConnectionManager connectionManager) {
+        InstanceIdentifier<Topology> topologyInstanceIdentifier = SouthboundMapper.createTopologyInstanceIdentifier();
+        ReadOnlyTransaction tx = reconciliationManager.getDb().newReadOnlyTransaction();
+
+        // find all bridges of the specific device in the config data store
+        // TODO: this query is not efficient. It retrieves all the Nodes in the datastore, loop over them and look for
+        // the bridges of specific device. It is mre efficient if MDSAL allows query nodes using wildcard on node id
+        // (ie: ovsdb://uuid/<device uuid>/bridge/*) r attributes
+        CheckedFuture<Optional<Topology>, ReadFailedException> readTopologyFuture =
+                tx.read(CONFIGURATION, topologyInstanceIdentifier);
+        Futures.addCallback(readTopologyFuture, new FutureCallback<Optional<Topology>>() {
+            @Override
+            public void onSuccess(@Nullable Optional<Topology> optionalTopology) {
+                if (optionalTopology.isPresent()) {
+                    InstanceIdentifier<Node> nIid = (InstanceIdentifier<Node>) nodeIid;
+                    Topology topology = optionalTopology.get();
+                    if (topology.getNode() != null) {
+                        final Map<InstanceIdentifier<?>, DataObject> changes = new HashMap<>();
+                        for (Node node : topology.getNode()) {
+                            OvsdbBridgeAugmentation bridge = node.getAugmentation(OvsdbBridgeAugmentation.class);
+                            if (bridge != null && bridge.getManagedBy() != null && bridge.getManagedBy().getValue().equals(nIid)) {
+                                changes.putAll(extractBridgeConfigurationChanges(node, bridge));
+                            }
+                        }
+                        if (!changes.isEmpty()) {
+                            reconcileBridgeConfigurations(changes);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.warn("Read Config/DS for Topology failed! {}", nodeIid, t);
+            }
+
+        });
+
+        return true;
+    }
+
+    private Map<InstanceIdentifier<?>, DataObject> extractBridgeConfigurationChanges(
+            final Node bridgeNode, final OvsdbBridgeAugmentation ovsdbBridge) {
+        Map<InstanceIdentifier<?>, DataObject> changes = new HashMap<>();
+        final InstanceIdentifier<Node> bridgeNodeIid =
+                SouthboundMapper.createInstanceIdentifier(connectionInstance, ovsdbBridge.getBridgeName().getValue());
+        final InstanceIdentifier<OvsdbBridgeAugmentation> ovsdbBridgeIid =
+                bridgeNodeIid.builder().augmentation(OvsdbBridgeAugmentation.class).build();
+        changes.put(bridgeNodeIid, bridgeNode);
+        changes.put(ovsdbBridgeIid, ovsdbBridge);
+
+        if (ovsdbBridge.getProtocolEntry() != null) {
+            for (ProtocolEntry protocol : ovsdbBridge.getProtocolEntry()) {
+                if (SouthboundConstants.OVSDB_PROTOCOL_MAP.get(protocol.getProtocol()) != null) {
+                    KeyedInstanceIdentifier<ProtocolEntry, ProtocolEntryKey> protocolIid =
+                            ovsdbBridgeIid.child(ProtocolEntry.class, protocol.getKey());
+                    changes.put(protocolIid, protocol);
+                } else {
+                    throw new IllegalArgumentException("Unknown protocol " + protocol.getProtocol());
+                }
+            }
+        }
+
+        if (ovsdbBridge.getControllerEntry() != null) {
+            for (ControllerEntry controller : ovsdbBridge.getControllerEntry()) {
+                KeyedInstanceIdentifier<ControllerEntry, ControllerEntryKey> controllerIid =
+                        ovsdbBridgeIid.child(ControllerEntry.class, controller.getKey());
+                changes.put(controllerIid, controller);
+            }
+        }
+
+        return changes;
+    }
+
+    private void reconcileBridgeConfigurations(final Map<InstanceIdentifier<?>, DataObject> changes) {
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvents = new AsyncDataChangeEvent() {
+            @Override
+            public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
+                return changes;
+            }
+
+            @Override
+            public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
+                return Collections.emptyMap();
+            }
+
+            @Override
+            public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
+                return Collections.emptyMap();
+            }
+
+            @Override
+            public Set<InstanceIdentifier<?>> getRemovedPaths() {
+                return Collections.emptySet();
+            }
+
+            @Override
+            public DataObject getOriginalSubtree() {
+                return null;
+            }
+
+            @Override
+            public DataObject getUpdatedSubtree() {
+                return null;
+            }
+        };
+
+        connectionInstance.transact(new TransactCommandAggregator(),
+                new BridgeOperationalState(reconciliationManager.getDb(), changeEvents),
+                new DataChangesManagedByOvsdbNodeEvent(
+                        reconciliationManager.getDb(),
+                        connectionInstance.getInstanceIdentifier(),
+                        changeEvents));
+    }
+
+    @Override
+    public void doRetry(boolean wasPreviousAttemptSuccessful) {
+    }
+
+    @Override
+    public void checkReadinessAndProcess() {
+    }
+
+    @Override
+    public long retryDelayInMills() {
+        return 0;
+    }
+}
index c3ac067eed7b2d37756332bd99d11c07694bc0f1..8ea5e639d07c28da4ea97689874fcefdba280229 100644 (file)
@@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory;
 import com.google.common.base.Optional;
 
 public class OvsdbAutoAttachRemovedCommand extends AbstractTransactionCommand {
-    private static final Logger LOG = LoggerFactory.getLogger(OvsdbQueueUpdateCommand.class);
+    private static final Logger LOG = LoggerFactory.getLogger(OvsdbAutoAttachRemovedCommand.class);
 
     private Map<UUID, AutoAttach> removedAutoAttachRows;
 
@@ -42,8 +42,8 @@ public class OvsdbAutoAttachRemovedCommand extends AbstractTransactionCommand {
         super(key, updates, dbSchema);
         try {
             removedAutoAttachRows = TyperUtils.extractRowsRemoved(AutoAttach.class, getUpdates(), getDbSchema());
-        } catch (IllegalArgumentException e) {
-            LOG.debug("AutoAttach not supported on this OVS", e);
+        } catch (final IllegalArgumentException e) {
+            LOG.info("UNSUPPORTED FUNCTIONALITY: AutoAttach not supported on this OVS", e.getMessage());
         }
     }
 
@@ -52,13 +52,13 @@ public class OvsdbAutoAttachRemovedCommand extends AbstractTransactionCommand {
         final InstanceIdentifier<Node> nodeIId = getOvsdbConnectionInstance().getInstanceIdentifier();
         final Optional<Node> ovsdbNode = SouthboundUtil.readNode(transaction, nodeIId);
         if (ovsdbNode.isPresent() && removedAutoAttachRows != null && !removedAutoAttachRows.isEmpty()) {
-            InstanceIdentifier<Node> ovsdbNodeIid =
+            final InstanceIdentifier<Node> ovsdbNodeIid =
                     SouthboundMapper.createInstanceIdentifier(getOvsdbConnectionInstance().getNodeId());
             // FIXME: Iterate on external_ids instead of uuid when Open vSwitch supports external_ids column
-            for (UUID autoAttachUuid : removedAutoAttachRows.keySet()) {
-                AutoattachKey autoAttachKey = getAutoAttachKeyToRemove(ovsdbNode.get(), autoAttachUuid);
+            for (final UUID autoAttachUuid : removedAutoAttachRows.keySet()) {
+                final AutoattachKey autoAttachKey = getAutoAttachKeyToRemove(ovsdbNode.get(), autoAttachUuid);
                 if (autoAttachKey != null) {
-                    InstanceIdentifier<Autoattach> iid = ovsdbNodeIid
+                    final InstanceIdentifier<Autoattach> iid = ovsdbNodeIid
                             .augmentation(OvsdbNodeAugmentation.class)
                             .child(Autoattach.class, autoAttachKey);
                     transaction.delete(LogicalDatastoreType.OPERATIONAL, iid);
@@ -73,11 +73,11 @@ public class OvsdbAutoAttachRemovedCommand extends AbstractTransactionCommand {
     }
 
     private AutoattachKey getAutoAttachKeyToRemove(Node node, UUID autoAttachUuid) {
-        List<Autoattach> autoAttachList = node.getAugmentation(OvsdbNodeAugmentation.class).getAutoattach();
+        final List<Autoattach> autoAttachList = node.getAugmentation(OvsdbNodeAugmentation.class).getAutoattach();
         if (autoAttachList == null || autoAttachList.isEmpty()) {
             return null;
         }
-        for (Autoattach autoAttach : autoAttachList) {
+        for (final Autoattach autoAttach : autoAttachList) {
             if (autoAttach.getAutoattachUuid()
                     .equals(new Uuid(autoAttachUuid.toString()))) {
                 return autoAttach.getKey();
index 40b89c0e0dbd89aa2cb133022ee7e4b5ed52eef9..9f696369e3c364f8dea58fcd5a5f937a76421f06 100644 (file)
@@ -55,8 +55,8 @@ public class OvsdbAutoAttachUpdateCommand extends AbstractTransactionCommand {
         try {
             updatedAutoAttachRows = TyperUtils.extractRowsUpdated(AutoAttach.class, getUpdates(), getDbSchema());
             oldAutoAttachRows = TyperUtils.extractRowsOld(AutoAttach.class, getUpdates(), getDbSchema());
-        } catch (IllegalArgumentException e) {
-            LOG.debug("AutoAttach not supported on this OVS", e);
+        } catch (final IllegalArgumentException e) {
+            LOG.info("UNSUPPORTED FUNCTIONALITY: AutoAttach not supported on this OVS", e.getMessage());
         }
     }
 
@@ -73,17 +73,17 @@ public class OvsdbAutoAttachUpdateCommand extends AbstractTransactionCommand {
         final InstanceIdentifier<Node> nodeIId = getOvsdbConnectionInstance().getInstanceIdentifier();
         final Optional<Node> ovsdbNode = SouthboundUtil.readNode(transaction, nodeIId);
         if (ovsdbNode.isPresent()) {
-            for (Entry<UUID, AutoAttach> entry : updatedAutoAttachRows.entrySet()) {
-                AutoAttach autoAttach = entry.getValue();
-                AutoAttach oldAutoAttach = oldAutoAttachRows.get(entry.getKey());
-                Uri uri = new Uri(SouthboundConstants.AUTOATTACH_URI_PREFIX + "://" + autoAttach.getUuid().toString());
+            for (final Entry<UUID, AutoAttach> entry : updatedAutoAttachRows.entrySet()) {
+                final AutoAttach autoAttach = entry.getValue();
+                final AutoAttach oldAutoAttach = oldAutoAttachRows.get(entry.getKey());
+                final Uri uri = new Uri(SouthboundConstants.AUTOATTACH_URI_PREFIX + "://" + autoAttach.getUuid().toString());
 
                 // FIXME: To be uncommented when Open vSwitch supports external_ids column
 //                Uri uri = new Uri(getAutoAttachId(autoAttach));
 
                 Autoattach currentAutoattach = null;
                 try {
-                    InstanceIdentifier<Autoattach> currentIid = nodeIId
+                    final InstanceIdentifier<Autoattach> currentIid = nodeIId
                             .augmentation(OvsdbNodeAugmentation.class)
                             .child(Autoattach.class, new AutoattachKey(new Uri(oldAutoAttach
                                     .getUuidColumn().getData().toString())));
@@ -93,16 +93,16 @@ public class OvsdbAutoAttachUpdateCommand extends AbstractTransactionCommand {
 //                            .child(Autoattach.class, new AutoattachKey(new Uri(oldAutoAttach
 //                                    .getExternalIdsColumn().getData()
 //                                    .get(SouthboundConstants.AUTOATTACH_ID_EXTERNAL_ID_KEY))));
-                    Optional<Autoattach> optionalAutoattach =
+                    final Optional<Autoattach> optionalAutoattach =
                             transaction.read(LogicalDatastoreType.OPERATIONAL, currentIid).checkedGet();
                     if (optionalAutoattach.isPresent()) {
                         currentAutoattach = optionalAutoattach.get();
                     }
-                } catch (Exception e) {
+                } catch (final Exception e) {
                     LOG.warn("AutoAttach table entries not found in operational datastore, need to create it.", e);
                 }
 
-                AutoattachBuilder autoAttachBuilder = (currentAutoattach != null) ? new AutoattachBuilder(currentAutoattach)
+                final AutoattachBuilder autoAttachBuilder = (currentAutoattach != null) ? new AutoattachBuilder(currentAutoattach)
                         : new AutoattachBuilder()
                         .setAutoattachUuid(new Uuid(entry.getKey().toString()))
                         .setAutoattachId(uri)
@@ -126,10 +126,10 @@ public class OvsdbAutoAttachUpdateCommand extends AbstractTransactionCommand {
                 // FIXME: To be uncommented when Open vSwitch supports external_ids column
 //                setExternalIds(autoAttachBuilder, autoAttach);
 
-                Autoattach autoAttachEntry = autoAttachBuilder.build();
+                final Autoattach autoAttachEntry = autoAttachBuilder.build();
                 LOG.trace("Update Ovsdb Node {} with AutoAttach table entries {}",
                         ovsdbNode.get().getNodeId(), autoAttachEntry);
-                InstanceIdentifier<Autoattach> iid = nodeIId
+                final InstanceIdentifier<Autoattach> iid = nodeIId
                         .augmentation(OvsdbNodeAugmentation.class)
                         .child(Autoattach.class, autoAttachEntry.getKey());
                 transaction.put(LogicalDatastoreType.OPERATIONAL,
@@ -140,11 +140,11 @@ public class OvsdbAutoAttachUpdateCommand extends AbstractTransactionCommand {
 
     private void setMappings (AutoattachBuilder autoAttachBuilder,
             AutoAttach autoAttach) {
-        Map<Long, Long> mappings = autoAttach.getMappingsColumn().getData();
-        Set<Long> mappingsKeys = mappings.keySet();
-        List<Mappings> mappingsList = new ArrayList<>();
-        for (Long mappingsKey : mappingsKeys) {
-            Integer mappingsValue = new Integer(mappings.get(mappingsKey).toString());
+        final Map<Long, Long> mappings = autoAttach.getMappingsColumn().getData();
+        final Set<Long> mappingsKeys = mappings.keySet();
+        final List<Mappings> mappingsList = new ArrayList<>();
+        for (final Long mappingsKey : mappingsKeys) {
+            final Integer mappingsValue = new Integer(mappings.get(mappingsKey).toString());
             if (mappingsKey != null && mappingsValue != null) {
                 mappingsList.add(new MappingsBuilder()
                         .setKey(new MappingsKey(mappingsKey))
index 7bb7eef25f41fe5cd7862bb873f79d8b6460f2c5..181df967e465f1b4cbe184866596fc753b1bbce5 100644 (file)
@@ -114,6 +114,13 @@ public class OvsdbConnectionManagerTest {
 
         //TODO: Write unit tests for entity ownership service related code.
         MemberModifier.suppress(MemberMatcher.method(OvsdbConnectionManager.class, "registerEntityForOwnership", OvsdbConnectionInstance.class));
+
+        ReadOnlyTransaction tx = mock(ReadOnlyTransaction.class);
+        when(db.newReadOnlyTransaction()).thenReturn(tx);
+        when(tx.read(any(LogicalDatastoreType.class),any(InstanceIdentifier.class)))
+                .thenReturn(mock(CheckedFuture.class));
+        when(client.getInstanceIdentifier()).thenReturn(mock(InstanceIdentifier.class));
+
         ovsdbConnectionManager.connected(externalClient);
     }
 
@@ -185,7 +192,8 @@ public class OvsdbConnectionManagerTest {
         MemberModifier.suppress(MemberMatcher.method(OvsdbConnectionManager.class, "getConnectionInstance", ConnectionInfo.class));
         OvsdbConnectionInstance ovsdbConnectionInstance = mock(OvsdbConnectionInstance.class);
         when(ovsdbConnectionManager.getConnectionInstance(any(ConnectionInfo.class))).thenReturn(ovsdbConnectionInstance);
-
+        when(ovsdbConnectionInstance.getInstanceIdentifier()).thenReturn(mock(InstanceIdentifier.class));
+        
         MemberModifier.suppress(MemberMatcher.method(OvsdbConnectionManager.class, "removeInstanceIdentifier", ConnectionInfo.class));
 
         //TODO: Write unit tests for entity ownership service related code.
diff --git a/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/reconciliation/configuration/BridgeConfigReconciliationTaskTest.java b/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/reconciliation/configuration/BridgeConfigReconciliationTaskTest.java
new file mode 100644 (file)
index 0000000..4f82115
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2016 , NEC Corporation and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.ovsdb.southbound.reconciliation.configuration;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+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.southbound.OvsdbConnectionInstance;
+import org.opendaylight.ovsdb.southbound.OvsdbConnectionManager;
+import org.opendaylight.ovsdb.southbound.SouthboundMapper;
+import org.opendaylight.ovsdb.southbound.reconciliation.ReconciliationManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow10;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryKey;
+import org.opendaylight.yang.gen.v1.urn.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.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * Created by Vinh Nguyen (vinh.nguyen@hcl.com) on 3/21/16
+ */
+@PrepareForTest({BridgeConfigReconciliationTask.class, OvsdbConnectionManager.class, OvsdbConnectionInstance.class, InstanceIdentifier.class, Optional.class})
+@RunWith(PowerMockRunner.class)
+public class BridgeConfigReconciliationTaskTest {
+    private final static String NODE_ID = "ovsdb://uuid/6ff3d0cf-4102-429d-b41c-f8027a0fd7f4";
+    private final static String BR01 = "br01";
+    private final static String BR02 = "br02";
+//    @Mock
+    private BridgeConfigReconciliationTask configurationReconciliationTask;
+    @Mock private OvsdbConnectionManager ovsdbConnectionManager;
+    @Mock private OvsdbConnectionInstance ovsdbConnectionInstance;
+    @Mock private DataBroker db;
+    @Mock private ReconciliationManager reconciliationManager;
+    @Mock private Topology topology;
+    @Mock private InstanceIdentifier<Node> iid;
+
+    @Before
+    public void setUp() throws Exception {
+        NodeKey nodeKey = new NodeKey(new NodeId(new Uri(NODE_ID)));
+        List<Node> bridgeNodes = new ArrayList<>();
+        bridgeNodes.add(createBridgeNode(BR01));
+        bridgeNodes.add(createBridgeNode(BR02));
+        when(topology.getNode()).thenReturn(bridgeNodes);
+
+        Optional<Topology> topologyOptional = mock(Optional.class);
+        when(topologyOptional.isPresent()).thenReturn(true);
+        when(topologyOptional.get()).thenReturn(topology);
+        CheckedFuture<Optional<Topology>, ReadFailedException> readTopologyFuture = Futures.immediateCheckedFuture(topologyOptional);
+
+        when(reconciliationManager.getDb()).thenReturn(db);
+        ReadOnlyTransaction tx = mock(ReadOnlyTransaction.class);
+        Mockito.when(db.newReadOnlyTransaction()).thenReturn(tx);
+        Mockito.when(tx.read(any(LogicalDatastoreType.class),any(InstanceIdentifier.class)))
+                .thenReturn(readTopologyFuture);
+
+        when(topology.getNode()).thenReturn(bridgeNodes);
+        when(ovsdbConnectionInstance.getNodeKey()).thenReturn(nodeKey);
+
+        configurationReconciliationTask = new BridgeConfigReconciliationTask(
+                reconciliationManager, ovsdbConnectionManager, iid, ovsdbConnectionInstance);
+    }
+
+    @Test
+    public void testReconcileConfiguration() throws Exception {
+        BridgeConfigReconciliationTask underTest = PowerMockito.spy(configurationReconciliationTask);
+        PowerMockito.doNothing().when(underTest, "reconcileBridgeConfigurations", any(Map.class));
+        assertEquals(true, underTest.reconcileConfiguration(ovsdbConnectionManager));
+        Map<InstanceIdentifier<?>, DataObject> changes = new HashMap<>();
+        for (Node bridgeNode : topology.getNode()) {
+            changes.putAll(createExpectedConfigurationChanges(bridgeNode));
+        }
+        PowerMockito.verifyPrivate(underTest).invoke("reconcileBridgeConfigurations", changes);
+    }
+
+    private Node createBridgeNode(final String bridgeName) {
+        Node bridgeNode = mock(Node.class);
+        OvsdbBridgeAugmentation ovsdbBridgeAugmentation = mock(OvsdbBridgeAugmentation.class);
+        OvsdbNodeRef ovsdbNodeRef = mock(OvsdbNodeRef.class);
+
+        when((InstanceIdentifier<Node>)ovsdbNodeRef.getValue()).thenReturn(iid);
+        OvsdbBridgeName ovsdbBridgeName = new OvsdbBridgeName(bridgeName);
+        when(bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class)).thenReturn(ovsdbBridgeAugmentation);
+        when(ovsdbBridgeAugmentation.getBridgeName()).thenReturn(ovsdbBridgeName);
+        ProtocolEntry protocolEntry = mock(ProtocolEntry.class);
+        ProtocolEntryKey protocolEntryKey = mock(ProtocolEntryKey.class);
+        Mockito.when(protocolEntry.getProtocol()).thenAnswer(new Answer<Class<? extends OvsdbBridgeProtocolBase>>() {
+            public Class<? extends OvsdbBridgeProtocolBase> answer(
+                    InvocationOnMock invocation) throws Throwable {
+                return OvsdbBridgeProtocolOpenflow10.class;
+            }
+        });
+        when(protocolEntry.getKey()).thenReturn(protocolEntryKey);
+        when(ovsdbBridgeAugmentation.getProtocolEntry()).thenReturn(Arrays.asList(protocolEntry));
+
+        ControllerEntry controllerEntry = mock(ControllerEntry.class);
+        ControllerEntryKey controllerEntryKey = mock(ControllerEntryKey.class);
+        when(controllerEntry.getKey()).thenReturn(controllerEntryKey);
+        when(ovsdbBridgeAugmentation.getControllerEntry()).thenReturn(Arrays.asList(controllerEntry));
+
+        when(ovsdbBridgeAugmentation.getManagedBy()).thenReturn(ovsdbNodeRef);
+
+        return bridgeNode;
+    }
+
+    private Map<InstanceIdentifier<?>, DataObject> createExpectedConfigurationChanges(final Node bridgeNode) {
+        OvsdbBridgeAugmentation ovsdbBridge = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
+
+        Map<InstanceIdentifier<?>, DataObject> changes = new HashMap<>();
+        final InstanceIdentifier<Node> bridgeNodeIid =
+                SouthboundMapper.createInstanceIdentifier(ovsdbConnectionInstance, ovsdbBridge.getBridgeName().getValue());
+        final InstanceIdentifier<OvsdbBridgeAugmentation> ovsdbBridgeIid =
+                bridgeNodeIid.builder().augmentation(OvsdbBridgeAugmentation.class).build();
+        changes.put(bridgeNodeIid, bridgeNode);
+        changes.put(ovsdbBridgeIid, ovsdbBridge);
+        for (ProtocolEntry protocolEntry : ovsdbBridge.getProtocolEntry()) {
+            KeyedInstanceIdentifier<ProtocolEntry, ProtocolEntryKey> protocolIid =
+                    ovsdbBridgeIid.child(ProtocolEntry.class, protocolEntry.getKey());
+            changes.put(protocolIid, protocolEntry);
+        }
+        for (ControllerEntry controller : ovsdbBridge.getControllerEntry()) {
+            KeyedInstanceIdentifier<ControllerEntry, ControllerEntryKey> controllerIid =
+                    ovsdbBridgeIid.child(ControllerEntry.class, controller.getKey());
+            changes.put(controllerIid, controller);
+        }
+        return changes;
+    }
+}