For application southbound plugin only give a device level view and not a connection level view.
To make net-virt cluster aware, it needs to the managers of the ovsdb server, so that
when it creates ovs bridges, it can connect them to the same controllers through OF plugin
Tests:
ovs-vsctl set-manager tcp:ip:6640
ovs-vsctl set-manager tcp:ip:6640 tcp:ip2:6640
ovs-vsctl set-manager tcp:ip:6640
ovs-vsctl del-manager
Change-Id: I8b68fef9583f4fbcc330a0e9fc239015851b3f7c
Signed-off-by: Anil Vishnoi <vishnoianil@gmail.com>
Manager manager = getClient().createTypedRowWrapper(Manager.class);
manager.setInactivityProbe(Sets.newHashSet(8192L));
manager.setMaxBackoff(Sets.newHashSet(4094L));
- manager.setTarget(Sets.newHashSet("172.16.50.50:6640"));
+ manager.setTarget("tcp:172.16.50.50:6640");
manager.setExternalIds(externalIds);
TransactionBuilder transactionBuilder = getClient().transactBuilder(getDbSchema())
public interface Manager extends TypedBaseTable<GenericTableSchema> {
@TypedColumn (name="target", method= MethodType.GETCOLUMN, fromVersion = "1.0.0")
- Column<GenericTableSchema, Set<String>> getTargetColumn();
+ Column<GenericTableSchema, String> getTargetColumn();
@TypedColumn (name="target", method= MethodType.SETDATA, fromVersion = "1.0.0")
- void setTarget(Set<String> target) ;
+ void setTarget(String target) ;
@TypedColumn (name = "is_connected", method = MethodType.GETCOLUMN, fromVersion = "1.1.0")
Column<GenericTableSchema, Boolean> getIsConnectedColumn();
type string;
}
}
-
+
+ list manager-entry {
+ description "Node managers info";
+ config false;
+ key "target";
+ leaf target {
+ description "Uri that user set to connect to the controller";
+ type inet:uri;
+ }
+ leaf is-connected {
+ type boolean;
+ }
+ }
}
identity interface-type-base {
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.schema.openvswitch.Manager;
+import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
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.OvsdbBridgeProtocolBase;
+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.ProtocolEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
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.ConnectionInfoBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntryBuilder;
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;
connectionInfoBuilder.setRemotePort(connectionInfo.getRemotePort());
return connectionInfoBuilder.build();
}
+
+ /**
+ * Create the {@link ManagerEntry} list given an OVSDB {@link OpenVSwitch}
+ * and {@link Manager} rows.
+ *
+ * @param ovsdbNode the {@link OpenVSwitch} to update
+ * @param updatedManagerRows the list of {@link Manager} managers with updates
+ * @return list of {@link ManagerEntry} entries
+ */
+ public static List<ManagerEntry> createManagerEntries(OpenVSwitch ovsdbNode,
+ Map<UUID, Manager> updatedManagerRows) {
+
+ LOG.debug("createManagerEntries OpenVSwitch: {}\n, updatedManagerRows: {}",
+ ovsdbNode, updatedManagerRows);
+ final Set<UUID> managerUUIDs = ovsdbNode.getManagerOptionsColumn().getData();
+ final List<ManagerEntry> managerEntries = new ArrayList<ManagerEntry>();
+ for (UUID managerUUID : managerUUIDs ) {
+ final Manager manager = updatedManagerRows.get(managerUUID);
+ addManagerEntries(managerEntries, manager);
+ }
+ LOG.debug("managerEntries: {}", managerEntries);
+ return managerEntries;
+ }
+
+ /**
+ * Create the {@link ManagerEntry} list given an MDSAL {@link Node} ovsdbNode
+ * and {@link Manager} rows.
+ *
+ * @param ovsdbNode the {@link Node} to update
+ * @param updatedManagerRows the list of {@link Manager} managers with updates
+ * @return list of {@link ManagerEntry} entries
+ */
+ public static List<ManagerEntry> createManagerEntries(Node ovsdbNode,
+ Map<Uri, Manager> updatedManagerRows) {
+
+ LOG.debug("createManagerEntries based on OVSDB Node: {}\n, updatedManagerRows: {}",
+ ovsdbNode, updatedManagerRows);
+ final List<ManagerEntry> managerEntriesCreated = new ArrayList<ManagerEntry>();
+ final OvsdbNodeAugmentation ovsdbNodeAugmentation =
+ ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
+ if (ovsdbNodeAugmentation == null) {
+ return managerEntriesCreated;
+ }
+
+ final List<ManagerEntry> managerEntries = ovsdbNodeAugmentation.getManagerEntry();
+ if (managerEntries != null) {
+ for (ManagerEntry managerEntry : managerEntries) {
+ final Manager manager = updatedManagerRows.get(managerEntry.getTarget());
+ addManagerEntries(managerEntriesCreated, manager);
+ }
+ }
+ LOG.debug("managerEntries: {}", managerEntriesCreated);
+ return managerEntriesCreated;
+ }
+
+ /**
+ * Add the OVSDB {@link Manager} updates to the MDSAL {@link ManagerEntry} list.
+ *
+ * @param managerEntries the list of {@link ManagerEntry} to update
+ * @param manager the updated OVSDB {@link Manager}
+ */
+ public static void addManagerEntries(List<ManagerEntry> managerEntries,
+ final Manager manager) {
+
+ if (manager != null && manager.getTargetColumn() != null) {
+ final String targetString = (String)manager.getTargetColumn().getData();
+ managerEntries.add(new ManagerEntryBuilder()
+ .setTarget(new Uri(targetString))
+ .setIsConnected(manager.getIsConnectedColumn().getData()).build());
+ }
+ }
+
}
--- /dev/null
+/*
+ * Copyright (c) 2015 Brocade Communications Systems, Inc. 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.transactions.md;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.Manager;
+import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
+import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
+import org.opendaylight.ovsdb.southbound.SouthboundMapper;
+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.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntryKey;
+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 com.google.common.base.Preconditions;
+
+public class OvsdbManagersRemovedCommand extends AbstractTransactionCommand {
+
+ private Map<UUID, OpenVSwitch> oldOpenVSwitchRows;
+ private Map<UUID, Manager> removedManagerRows;
+ private Map<UUID, OpenVSwitch> updatedOpenVSwitchRows;
+
+ public OvsdbManagersRemovedCommand(OvsdbConnectionInstance key,
+ TableUpdates updates, DatabaseSchema dbSchema) {
+ super(key, updates, dbSchema);
+ updatedOpenVSwitchRows = TyperUtils.extractRowsUpdated(OpenVSwitch.class, getUpdates(), getDbSchema());
+ oldOpenVSwitchRows = TyperUtils.extractRowsOld(OpenVSwitch.class, getUpdates(), getDbSchema());
+ removedManagerRows = TyperUtils.extractRowsRemoved(Manager.class,
+ getUpdates(), getDbSchema());
+ }
+
+ @Override
+ public void execute(ReadWriteTransaction transaction) {
+ for (OpenVSwitch openVSwitch : updatedOpenVSwitchRows.values()) {
+ InstanceIdentifier<Node> ovsdbNodeIid =
+ SouthboundMapper.createInstanceIdentifier(getOvsdbConnectionInstance().getNodeId());
+ deleteManagers(transaction, managerEntriesToRemove(ovsdbNodeIid,openVSwitch));
+ }
+ }
+
+ private void deleteManagers(ReadWriteTransaction transaction,
+ List<InstanceIdentifier<ManagerEntry>> managerEntryIids) {
+ for (InstanceIdentifier<ManagerEntry> managerEntryIid: managerEntryIids) {
+ transaction.delete(LogicalDatastoreType.OPERATIONAL, managerEntryIid);
+ }
+ }
+
+ private List<InstanceIdentifier<ManagerEntry>> managerEntriesToRemove(
+ InstanceIdentifier<Node> ovsdbNodeIid, OpenVSwitch openVSwitch) {
+ Preconditions.checkNotNull(ovsdbNodeIid);
+ Preconditions.checkNotNull(openVSwitch);
+
+ List<InstanceIdentifier<ManagerEntry>> result =
+ new ArrayList<InstanceIdentifier<ManagerEntry>>();
+ OpenVSwitch oldOvsdbNode = oldOpenVSwitchRows.get(openVSwitch.getUuid());
+
+ if (oldOvsdbNode != null && oldOvsdbNode.getManagerOptionsColumn() != null) {
+ for (UUID managerUuid: oldOvsdbNode.getManagerOptionsColumn().getData()) {
+ if (openVSwitch.getManagerOptionsColumn() == null
+ || !openVSwitch.getManagerOptionsColumn().getData().contains(managerUuid)) {
+ Manager manager = removedManagerRows.get(managerUuid);
+ if (manager != null && manager.getTargetColumn() != null) {
+ InstanceIdentifier<ManagerEntry> iid = ovsdbNodeIid
+ .augmentation(OvsdbNodeAugmentation.class)
+ .child(ManagerEntry.class,
+ new ManagerEntryKey(
+ new Uri(manager.getTargetColumn().getData())));
+ result.add(iid);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Brocade Communications Systems, Inc. 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.transactions.md;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.Manager;
+import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
+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.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+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 com.google.common.base.Optional;
+
+public class OvsdbManagersUpdateCommand extends AbstractTransactionCommand {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsdbManagersUpdateCommand.class);
+
+ private Map<UUID, Manager> updatedManagerRows;
+ private Map<UUID, OpenVSwitch> updatedOpenVSwitchRows;
+
+ public OvsdbManagersUpdateCommand(OvsdbConnectionInstance key,
+ TableUpdates updates, DatabaseSchema dbSchema) {
+ super(key, updates, dbSchema);
+ updatedOpenVSwitchRows = TyperUtils.extractRowsUpdated(OpenVSwitch.class, getUpdates(), getDbSchema());
+ updatedManagerRows = TyperUtils.extractRowsUpdated(Manager.class,getUpdates(), getDbSchema());
+ }
+
+ @Override
+ public void execute(ReadWriteTransaction transaction) {
+ if (updatedManagerRows != null && !updatedManagerRows.isEmpty()) {
+ Map<Uri, Manager> updatedManagerRowsWithUri = getUriManagerMap(updatedManagerRows);
+ if (updatedOpenVSwitchRows != null && !updatedOpenVSwitchRows.isEmpty()) {
+ updateManagers(transaction, updatedManagerRows, updatedOpenVSwitchRows);
+ } else {
+ updateManagers(transaction, updatedManagerRowsWithUri);
+ }
+ }
+ }
+
+ /**
+ * Update the Manager values for the given {@link OpenVSwitch} list.
+ *
+ * <p>
+ * Manager and OpenVSwitch are independent tables in the Open_vSwitch schema
+ * but the OVSDB yang model includes the Manager fields in the
+ * OVSDB Node data. In some cases the OVSDB will send OpenVSwitch and Manager
+ * updates together and in other cases independently. This method here
+ * assumes the former.
+ * </p>
+ *
+ * @param transaction the {@link ReadWriteTransaction}
+ * @param updatedManagerRows updated {@link Manager} rows
+ * @param updatedOpenVSwitchRows updated {@link OpenVSwitch} rows
+ */
+ private void updateManagers(ReadWriteTransaction transaction,
+ Map<UUID, Manager> updatedManagerRows,
+ Map<UUID, OpenVSwitch> updatedOpenVSwitchRows) {
+
+ for (Map.Entry<UUID, OpenVSwitch> ovsdbNodeEntry : updatedOpenVSwitchRows.entrySet()) {
+ final List<ManagerEntry> managerEntries =
+ SouthboundMapper.createManagerEntries(ovsdbNodeEntry.getValue(), updatedManagerRows);
+ LOG.debug("Update Ovsdb Node {} with manager entries {}",ovsdbNodeEntry.getValue(), managerEntries);
+ for (ManagerEntry managerEntry : managerEntries) {
+ transaction.merge(LogicalDatastoreType.OPERATIONAL,
+ getManagerEntryIid(managerEntry),
+ managerEntry);
+ }
+ }
+ }
+
+ /**
+ * Update the ManagerEntry values after finding the related {@OpenVSwitch} list.
+ *
+ * <p>
+ * Manager and OpenVSwitch are independent tables in the Open_vSwitch schema
+ * but the OVSDB yang model includes the Manager fields in the
+ * OvsdbNode data. In some cases the OVSDB will send OpenVSwitch and Manager
+ * updates together and in other cases independently. This method here
+ * assumes the latter.
+ * </p>
+ *
+ * @param transaction the {@link ReadWriteTransaction}
+ * @param updatedManagerRows updated {@link Manager} rows
+
+ */
+ private void updateManagers(ReadWriteTransaction transaction,
+ Map<Uri, Manager> updatedManagerRows) {
+
+ final InstanceIdentifier<Node> connectionIId = getOvsdbConnectionInstance().getInstanceIdentifier();
+ final Optional<Node> ovsdbNode = SouthboundUtil.readNode(transaction, connectionIId);
+ if (ovsdbNode.isPresent()) {
+ final List<ManagerEntry> managerEntries =
+ SouthboundMapper.createManagerEntries(ovsdbNode.get(), updatedManagerRows);
+
+ LOG.debug("Update Ovsdb Node {} with manager entries {}",ovsdbNode.get(), managerEntries);
+ for (ManagerEntry managerEntry : managerEntries) {
+ InstanceIdentifier<ManagerEntry> iid = connectionIId
+ .augmentation(OvsdbNodeAugmentation.class)
+ .child(ManagerEntry.class, managerEntry.getKey());
+ transaction.merge(LogicalDatastoreType.OPERATIONAL,
+ iid, managerEntry);
+ }
+ }
+ }
+
+ /**
+ * Create the {@link InstanceIdentifier} for the {@link ManagerEntry}.
+ *
+ * @param managerEntry the {@link ManagerEntry}
+ * @return the {@link InstanceIdentifier}
+ */
+ private InstanceIdentifier<ManagerEntry> getManagerEntryIid(ManagerEntry managerEntry) {
+
+ OvsdbConnectionInstance client = getOvsdbConnectionInstance();
+ String nodeString = client.getNodeKey().getNodeId().getValue();
+ NodeId nodeId = new NodeId(new Uri(nodeString));
+ NodeKey nodeKey = new NodeKey(nodeId);
+ InstanceIdentifier<Node> ovsdbNodeIid = InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class,new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
+ .child(Node.class,nodeKey)
+ .build();
+
+ InstanceIdentifier<ManagerEntry> iid = ovsdbNodeIid
+ .augmentation(OvsdbNodeAugmentation.class)
+ .child(ManagerEntry.class, managerEntry.getKey());
+ return iid;
+ }
+
+ private Map<Uri, Manager> getUriManagerMap(Map<UUID,Manager> uuidManagerMap) {
+ Map<Uri, Manager> uriManagerMap = new HashMap<>();
+ for (Map.Entry<UUID, Manager> uuidManagerMapEntry : uuidManagerMap.entrySet()) {
+ uriManagerMap.put(
+ new Uri(uuidManagerMapEntry.getValue().getTargetColumn().getData()),
+ uuidManagerMapEntry.getValue());
+ }
+ return uriManagerMap;
+
+ }
+}
public OvsdbOperationalCommandAggregator(OvsdbConnectionInstance key,TableUpdates updates,
DatabaseSchema dbSchema) {
commands.add(new OpenVSwitchUpdateCommand(key, updates, dbSchema));
+ commands.add(new OvsdbManagersUpdateCommand(key, updates, dbSchema));
+ commands.add(new OvsdbManagersRemovedCommand(key, updates, dbSchema));
commands.add(new OvsdbBridgeUpdateCommand(key, updates, dbSchema));
commands.add(new OvsdbBridgeRemovedCommand(key, updates, dbSchema));
commands.add(new OvsdbControllerUpdateCommand(key, updates, dbSchema));