A few cleanups
[ovsdb.git] / southbound / southbound-impl / src / main / java / org / opendaylight / ovsdb / southbound / transactions / md / OvsdbControllerUpdateCommand.java
index 4980369a1b2cfc8363e07ba1b8816daa640fb889..94a1bc8b50ca135581017be7e1bcb3da48267221 100644 (file)
@@ -7,34 +7,36 @@
  */
 package org.opendaylight.ovsdb.southbound.transactions.md;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.ovsdb.lib.message.TableUpdates;
 import org.opendaylight.ovsdb.lib.notation.UUID;
 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
 import org.opendaylight.ovsdb.schema.openvswitch.Controller;
+import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
+import org.opendaylight.ovsdb.southbound.SouthboundConstants;
 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
+import org.opendaylight.ovsdb.southbound.SouthboundUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.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.OvsdbNodeAugmentation;
 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.ControllerEntryBuilder;
-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.node.attributes.ConnectionInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 
 import com.google.common.base.Optional;
 
@@ -43,7 +45,7 @@ public class OvsdbControllerUpdateCommand extends AbstractTransactionCommand {
     private Map<UUID, Controller> updatedControllerRows;
     private Map<UUID, Bridge> updatedBridgeRows;
 
-    public OvsdbControllerUpdateCommand(ConnectionInfo key,
+    public OvsdbControllerUpdateCommand(OvsdbConnectionInstance key,
             TableUpdates updates, DatabaseSchema dbSchema) {
         super(key, updates, dbSchema);
         updatedBridgeRows = TyperUtils.extractRowsUpdated(Bridge.class, getUpdates(), getDbSchema());
@@ -53,92 +55,138 @@ public class OvsdbControllerUpdateCommand extends AbstractTransactionCommand {
 
     @Override
     public void execute(ReadWriteTransaction transaction) {
-        final InstanceIdentifier<Node> connectionIId = SouthboundMapper.createInstanceIdentifier(getConnectionInfo());
-        if ( (updatedBridgeRows == null && updatedControllerRows == null )
-                || ( updatedBridgeRows.isEmpty() && updatedControllerRows.isEmpty())) {
-            return;
-        }
-        Optional<Node> node = readNode(transaction, connectionIId);
-        if (node.isPresent()) {
-            updateController(transaction, node.get());
-        }
-        for (Bridge bridge: updatedBridgeRows.values()) {
-            setController(transaction, bridge);
+        if (updatedControllerRows != null && !updatedControllerRows.isEmpty()) {
+            if (updatedBridgeRows != null && !updatedBridgeRows.isEmpty()) {
+                updateController(transaction, updatedControllerRows, updatedBridgeRows);
+            } else {
+                updateController(transaction, updatedControllerRows);
+            }
         }
     }
 
-    private void setController(ReadWriteTransaction transaction, Bridge bridge) {
-        for (ControllerEntry controllerEntry: SouthboundMapper.createControllerEntries(bridge, updatedControllerRows)) {
-            InstanceIdentifier<ControllerEntry> iid =
-                    SouthboundMapper.createInstanceIdentifier(getConnectionInfo(), bridge)
-                    .augmentation(OvsdbBridgeAugmentation.class)
-                    .child(ControllerEntry.class,controllerEntry.getKey());
-            transaction.put(LogicalDatastoreType.OPERATIONAL, iid, controllerEntry);
+    /**
+     * Update the ControllerEntry values for the given {@link Bridge} list.
+     *
+     * <p>
+     * Controller and Bridge are independent tables in the Open_vSwitch schema
+     * but the OVSDB yang model includes the Controller fields in the
+     * Bridge data. In some cases the OVSDB will send Bridge and Controller
+     * updates together and in other cases independently. This method here
+     * assumes the former.
+     * </p>
+     *
+     * @param transaction the {@link ReadWriteTransaction}
+     * @param updatedControllerRows updated {@link Controller} rows
+     * @param updatedBridgeRows updated {@link Bridge} rows
+     */
+    private void updateController(ReadWriteTransaction transaction,
+                                  Map<UUID, Controller> updatedControllerRows,
+                                  Map<UUID, Bridge> updatedBridgeRows) {
+
+        for (Map.Entry<UUID, Bridge> bridgeEntry : updatedBridgeRows.entrySet()) {
+            final List<ControllerEntry> controllerEntries =
+                    SouthboundMapper.createControllerEntries(bridgeEntry.getValue(), updatedControllerRows);
+
+            for (ControllerEntry controllerEntry : controllerEntries) {
+                transaction.merge(LogicalDatastoreType.OPERATIONAL,
+                        getControllerEntryIid(controllerEntry, bridgeEntry.getValue().getNameColumn().getData()),
+                        controllerEntry);
+            }
         }
     }
 
-    private void updateController(ReadWriteTransaction transaction, Node node) {
-        for (Entry<UUID, Controller> controllerUpdate : updatedControllerRows.entrySet()) {
-            Controller controller = controllerUpdate.getValue();
-            Optional<String> bridgeName = getControllerBridge(controllerUpdate.getValue().getUuid());
+    /**
+     * Update the ControllerEntry values after finding the related {@Bridge} list.
+     *
+     * <p>
+     * Controller and Bridge are independent tables in the Open_vSwitch schema
+     * but the OVSDB yang model includes the Controller fields in the
+     * Bridge data. In some cases the OVSDB will send Bridge and Controller
+     * updates together and in other cases independently. This method here
+     * assumes the latter.
+     * </p>
+     *
+     * @param transaction the {@link ReadWriteTransaction}
+     * @param updatedControllerRows updated {@link Controller} rows
 
-            if (!bridgeName.isPresent()) {
-                bridgeName = getControllerBridge( transaction, node, controllerUpdate.getValue());
-            }
-            if (bridgeName.isPresent()) {
-                ControllerEntryKey controlletEntryKey
-                    = new ControllerEntryKey(new Uri(controller.getTargetColumn().getData()));
-                ControllerEntry controllerEntry = new ControllerEntryBuilder()
-                        .setControllerUuid(new Uuid(controller.getUuid().toString()))
-                        .setIsConnected(controllerUpdate.getValue().getIsConnectedColumn().getData())
-                        .build();
-                InstanceIdentifier<ControllerEntry> controllerPath =
-                        SouthboundMapper.createInstanceIdentifier(
-                                getConnectionInfo(), new OvsdbBridgeName(bridgeName.get()))
+     */
+    private void updateController(ReadWriteTransaction transaction,
+                                  Map<UUID, Controller> updatedControllerRows) {
+
+        Map<InstanceIdentifier<Node>, Node> bridgeNodes = getBridgeNodes(transaction);
+        for (Map.Entry<InstanceIdentifier<Node>, Node> bridgeNodeEntry : bridgeNodes.entrySet()) {
+            final List<ControllerEntry> controllerEntries =
+                    SouthboundMapper.createControllerEntries(bridgeNodeEntry.getValue(), updatedControllerRows);
+
+            for (ControllerEntry controllerEntry : controllerEntries) {
+                final InstanceIdentifier<Node> bridgeIid = bridgeNodeEntry.getKey();
+                InstanceIdentifier<ControllerEntry> iid = bridgeIid
                         .augmentation(OvsdbBridgeAugmentation.class)
-                        .child(ControllerEntry.class,controlletEntryKey);
-                transaction.merge(LogicalDatastoreType.OPERATIONAL, controllerPath, controllerEntry);
+                        .child(ControllerEntry.class, controllerEntry.getKey());
+                transaction.merge(LogicalDatastoreType.OPERATIONAL,
+                        iid, controllerEntry);
             }
         }
     }
 
-    private Optional<String> getControllerBridge(UUID controllerUUID) {
-        for (UUID bridgeUUID : updatedBridgeRows.keySet()) {
-            if (this.updatedBridgeRows.get(bridgeUUID).getControllerColumn().getData().contains(controllerUUID)) {
-                return Optional.of(this.updatedBridgeRows.get(bridgeUUID).getNameColumn().getData());
+    /**
+     * Find all the {@link Node} bridge nodes for the given connection.
+     *
+     * @param transaction the {@link ReadWriteTransaction}
+     * @return
+     */
+    private Map<InstanceIdentifier<Node>, Node> getBridgeNodes(ReadWriteTransaction transaction) {
+        Map<InstanceIdentifier<Node>, Node> bridgeNodes = new HashMap<>();
+        final InstanceIdentifier<Node> connectionIId = getOvsdbConnectionInstance().getInstanceIdentifier();
+        final Optional<Node> ovsdbNode = SouthboundUtil.readNode(transaction, connectionIId);
+        if (ovsdbNode.isPresent()) {
+            OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.get().getAugmentation(OvsdbNodeAugmentation.class);
+            if (ovsdbNodeAugmentation != null) {
+                final List<ManagedNodeEntry> managedNodeEntries = ovsdbNodeAugmentation.getManagedNodeEntry();
+                for (ManagedNodeEntry managedNodeEntry : managedNodeEntries) {
+                    final InstanceIdentifier<Node> bridgeIid =
+                            (InstanceIdentifier<Node>) managedNodeEntry.getBridgeRef().getValue();
+                    @SuppressWarnings("unchecked")
+                    final Optional<Node> bridgeNode = SouthboundUtil.readNode(transaction, bridgeIid);
+                    if (bridgeNode.isPresent()) {
+                        bridgeNodes.put(bridgeIid, bridgeNode.get());
+                    } else {
+                        LOG.warn("OVSDB bridge node was not found: {}", bridgeIid);
+                    }
+                }
+            } else {
+                LOG.warn("OvsdbNodeAugmentation was not found: {}", connectionIId);
             }
+        } else {
+            LOG.warn("OVSDB node was not found: {}", connectionIId);
         }
-        return Optional.absent();
-    }
 
-    private Optional<String> getControllerBridge(
-            final ReadWriteTransaction transaction, Node node, Controller controller) {
-        OvsdbNodeAugmentation ovsdbNode = node.getAugmentation(OvsdbNodeAugmentation.class);
-        List<ManagedNodeEntry> managedNodes = ovsdbNode.getManagedNodeEntry();
-        for ( ManagedNodeEntry managedNodeEntry : managedNodes ) {
-            @SuppressWarnings("unchecked")
-            Node managedNode = readNode(transaction
-                    ,(InstanceIdentifier<Node>)managedNodeEntry.getBridgeRef().getValue()).get();
-            ControllerEntryBuilder controllerBuidler = new ControllerEntryBuilder();
-            ControllerEntryKey controllerKey = new ControllerEntryKey(new Uri(controller.getTargetColumn().getData()));
-            controllerBuidler.setKey(controllerKey);
-            OvsdbBridgeAugmentation ovsdbNodeAugment
-                = managedNode.getAugmentation(OvsdbBridgeAugmentation.class);
-            return Optional.of(ovsdbNodeAugment.getBridgeName().getValue());
-        }
-        return Optional.absent();
+        return bridgeNodes;
     }
 
-    private Optional<Node> readNode(final ReadWriteTransaction transaction, final InstanceIdentifier<Node> nodePath) {
-        Optional<Node> node = Optional.absent();
-        try {
-            node = transaction.read(
-                    LogicalDatastoreType.OPERATIONAL, nodePath)
-                    .checkedGet();
-        } catch (final ReadFailedException e) {
-            LOG.warn("Read Operational/DS for Node fail! {}",
-                    nodePath, e);
-        }
-        return node;
+    /**
+     * Create the {@link InstanceIdentifier} for the {@link ControllerEntry}.
+     *
+     * @param controllerEntry the {@link ControllerEntry}
+     * @param bridgeName the name of the bridge
+     * @return the {@link InstanceIdentifier}
+     */
+    private InstanceIdentifier<ControllerEntry> getControllerEntryIid(
+            ControllerEntry controllerEntry, String bridgeName) {
+
+        OvsdbConnectionInstance client = getOvsdbConnectionInstance();
+        String nodeString = client.getNodeKey().getNodeId().getValue()
+                + "/bridge/" + bridgeName;
+        NodeId nodeId = new NodeId(new Uri(nodeString));
+        NodeKey nodeKey = new NodeKey(nodeId);
+        InstanceIdentifier<Node> bridgeIid = InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class,new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
+                .child(Node.class,nodeKey)
+                .build();
+
+        InstanceIdentifier<ControllerEntry> iid = bridgeIid
+                .augmentation(OvsdbBridgeAugmentation.class)
+                .child(ControllerEntry.class, controllerEntry.getKey());
+        return iid;
     }
 }