in the datapath.
other_config : enable-statistics: optional string
- either ture or false. Set this value to true to enable populating the
+ either ture or false. Set this value to true to enable populating the
statistics column or to false to explicitly disable it.";
key "other-config-key";
}
list qos-entries {
- key "qos-uuid";
+ key "qos-id";
+ leaf qos-id {
+ description "An identifier used for QoS entries in the MD-SAL.";
+ type inet:uri;
+ }
leaf qos-uuid {
description "The unique identifier of the QoS.";
type yang:uuid;
}
list queue-list {
description "The list of queues used by the QoS";
- key "queue-uuid";
+ key "queue-number";
+ leaf queue-number {
+ description "The queue number of the record in the QoS entry";
+ type uint32;
+ }
leaf queue-uuid {
- description "The unique identifier of the queue.";
+ description "The unique identifier of the queue record.";
type yang:uuid;
}
}
}
list queues {
- key "queue-uuid";
+ key "queue-id";
+ leaf queue-id {
+ description "An identifier used for Queue entries in the MD-SAL.";
+ type inet:uri;
+ }
leaf queue-uuid {
description "The unique identifier of the queue.";
type yang:uuid;
leaf dscp {
type uint8;
}
+ list queues-external-ids {
+ key "queues-external-id-key";
+ leaf queues-external-id-key {
+ description "queues external-id name/key";
+ type string;
+ mandatory true;
+ }
+ leaf queues-external-id-value {
+ description "queues-external-id value";
+ type string;
+ mandatory true;
+ }
+ }
list queues-other-config {
description "
Configuration for linux-htb QoS:
other_config : lacp-fallback-ab: optional string
either true or false Determines the behavior of openvswitch bond in LACP mode.
- If the partner switch does not support LACP, setting this
+ If the partner switch does not support LACP, setting this
option to true allows openvswitch to fallback to active-backup.
If the option is set to false, the bond will be disabled.
In both the cases, once the partner switch is configured
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeSystem;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeNetdev;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.QosTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.QosTypeLinuxHfsc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.QosTypeLinuxHtb;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
import com.google.common.collect.ImmutableBiMap;
public static final String OVSDB_URI_PREFIX = "ovsdb";
public static final String BRIDGE_URI_PREFIX = "bridge";
public static final String TP_URI_PREFIX = "terminationpoint";
+ public static final String QOS_URI_PREFIX = "qos";
+ public static final String QUEUE_URI_PREFIX = "queue";
public static final Integer DEFAULT_OVSDB_PORT = 6640;
public static final String DEFAULT_OPENFLOW_PORT = "6653";
public static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
public static final String UUID = "uuid";
+ public static final String QOS_LINUX_HTB = "linux-htb";
+ public static final String QOS_LINUX_HFSC = "linux-hfsc";
+ public static final ImmutableBiMap<Class<? extends QosTypeBase>,String> QOS_TYPE_MAP
+ = new ImmutableBiMap.Builder<Class<? extends QosTypeBase>,String>()
+ .put(QosTypeLinuxHtb.class,QOS_LINUX_HTB)
+ .put(QosTypeLinuxHfsc.class,QOS_LINUX_HFSC)
+ .build();
+
public static final ImmutableBiMap<Class<? extends OvsdbBridgeProtocolBase>,String> OVSDB_PROTOCOL_MAP
= new ImmutableBiMap.Builder<Class<? extends OvsdbBridgeProtocolBase>,String>()
.put(OvsdbBridgeProtocolOpenflow10.class,"OpenFlow10")
.put(DatapathTypeNetdev.class,"netdev")
.build();
public static final String IID_EXTERNAL_ID_KEY = "opendaylight-iid";
+ public static final String QOS_ID_EXTERNAL_ID_KEY = "opendaylight-qos-id";
+ public static final String QUEUE_ID_EXTERNAL_ID_KEY = "opendaylight-queue-id";
public enum VLANMODES {
ACCESS("access"),
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.Set;
import org.opendaylight.ovsdb.lib.OvsdbClient;
import org.opendaylight.ovsdb.schema.openvswitch.Controller;
import org.opendaylight.ovsdb.schema.openvswitch.Manager;
import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
+import org.opendaylight.ovsdb.schema.openvswitch.Qos;
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.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
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.DatapathId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeSystem;
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.QosTypeBase;
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.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.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfigBuilder;
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;
}
}
+ /**
+ * Return the MD-SAL QoS type class corresponding to the QoS type {@link Qos}
+ *
+ * @param type the QoS type to match {@link String}
+ * @return class matching the input QoS type {@link QosTypeBase}
+ */
+ public static Class<? extends QosTypeBase> createQosType(String type) {
+ Preconditions.checkNotNull(type);
+ if (type.isEmpty()) {
+ LOG.info("QoS type not supplied");
+ return QosTypeBase.class;
+ } else {
+ ImmutableBiMap<String, Class<? extends QosTypeBase>> mapper =
+ SouthboundConstants.QOS_TYPE_MAP.inverse();
+ if (mapper.get(type) == null) {
+ LOG.info("QoS type not found in model: {}", type);
+ return QosTypeBase.class;
+ } else {
+ return mapper.get(type);
+ }
+ }
+ }
+
+ public static String createQosType(Class<? extends QosTypeBase> qosTypeClass) {
+ String qosType = SouthboundConstants.DATAPATH_TYPE_MAP.get(QosTypeBase.class);
+
+ if (qosTypeClass != null && !qosTypeClass.equals(QosTypeBase.class)) {
+ qosType = SouthboundConstants.QOS_TYPE_MAP.get(qosTypeClass);
+ if (qosType == null) {
+ throw new IllegalArgumentException("Unknown QoS type" + qosTypeClass.getName());
+ }
+ }
+ return qosType;
+ }
+
+
public static InstanceIdentifier<Node> getInstanceIdentifier(OpenVSwitch ovs) {
InstanceIdentifier<Node> iid = null;
if (ovs.getExternalIdsColumn() != null
--- /dev/null
+/*
+ * Copyright (c) 2016 Intel 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.ovsdb.transact;
+
+import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.ovsdb.lib.notation.Mutator;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.ovsdb.schema.openvswitch.Qos;
+import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
+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.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntries;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
+
+public class QosRemovedCommand extends AbstractTransactCommand {
+ private static final Logger LOG = LoggerFactory.getLogger(QosRemovedCommand.class);
+
+ public QosRemovedCommand(BridgeOperationalState state,
+ AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+ super(state, changes);
+ }
+
+ @Override
+ public void execute(TransactionBuilder transaction) {
+ Set<InstanceIdentifier<QosEntries>> removed =
+ TransactUtils.extractRemoved(getChanges(),QosEntries.class);
+
+ Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> originals
+ = TransactUtils.extractOriginal(getChanges(),OvsdbNodeAugmentation.class);
+
+ Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> updated
+ = TransactUtils.extractUpdated(getChanges(), OvsdbNodeAugmentation.class);
+
+ Iterator<InstanceIdentifier<OvsdbNodeAugmentation>> itr = originals.keySet().iterator();
+ while (itr.hasNext()) {
+ InstanceIdentifier<OvsdbNodeAugmentation> ovsdbNodeIid = itr.next();
+ OvsdbNodeAugmentation original = originals.get(ovsdbNodeIid);
+ OvsdbNodeAugmentation update = updated.get(ovsdbNodeIid);
+
+ if (original != null && update != null) {
+ List<QosEntries> origQosEntries = original.getQosEntries();
+ List<QosEntries> updatedQosEntries = update.getQosEntries();
+ if (origQosEntries != null && !origQosEntries.isEmpty()) {
+ for (QosEntries origQosEntry : origQosEntries) {
+ OvsdbNodeAugmentation operNode = getOperationalState().getBridgeNode(ovsdbNodeIid).get().getAugmentation(OvsdbNodeAugmentation.class);
+ List<QosEntries> operQosEntries = operNode.getQosEntries();
+
+ boolean found = false;
+ if (updatedQosEntries != null && !updatedQosEntries.isEmpty()) {
+ for (QosEntries updatedQosEntry : updatedQosEntries) {
+ if (origQosEntry.getQosId().equals(updatedQosEntry.getQosId())) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ LOG.debug("Received request to delete QoS entry {}",origQosEntry.getQosId());
+ Uuid qosUuid = getQosEntryUuid(operQosEntries, origQosEntry.getQosId());
+ if (qosUuid != null) {
+ Qos qos = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), Qos.class, null);
+ transaction.add(op.delete(qos.getSchema())
+ .where(qos.getUuidColumn().getSchema().opEqual(new UUID(qosUuid.getValue())))
+ .build());
+ } else {
+ LOG.warn("Unable to delete QoS{} for node {} because it was not found in the operational store, "
+ + "and thus we cannot retrieve its UUID", origQosEntry.getQosId(), ovsdbNodeIid);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private Uuid getQosEntryUuid(List<QosEntries> operQosEntries, Uri qosId) {
+ if (operQosEntries != null && !operQosEntries.isEmpty()) {
+ for (QosEntries qosEntry : operQosEntries) {
+ if (qosEntry.getQosId().equals(qosId)) {
+ return qosEntry.getQosUuid();
+ }
+ }
+ }
+ return null;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Intel 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.ovsdb.transact;
+
+import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.ovsdb.lib.notation.Condition;
+import org.opendaylight.ovsdb.lib.notation.Mutator;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.operations.Mutate;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.ovsdb.schema.openvswitch.Port;
+import org.opendaylight.ovsdb.schema.openvswitch.Qos;
+import org.opendaylight.ovsdb.southbound.SouthboundConstants;
+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.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+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.OvsdbTerminationPointAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueList;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableMap;
+
+public class QosUpdateCommand extends AbstractTransactCommand {
+ private static final Logger LOG = LoggerFactory.getLogger(QosUpdateCommand.class);
+
+
+ public QosUpdateCommand(BridgeOperationalState state, AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+ super(state, changes);
+ }
+
+ @Override
+ public void execute(TransactionBuilder transaction) {
+ Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> created =
+ TransactUtils.extractCreated(getChanges(),OvsdbNodeAugmentation.class);
+ for (Entry<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> ovsdbNodeEntry:
+ created.entrySet()) {
+ updateQos(transaction, ovsdbNodeEntry.getKey(), ovsdbNodeEntry.getValue());
+ }
+ Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> updated =
+ TransactUtils.extractUpdated(getChanges(),OvsdbNodeAugmentation.class);
+ for (Entry<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> ovsdbNodeEntry:
+ updated.entrySet()) {
+ updateQos(transaction, ovsdbNodeEntry.getKey(), ovsdbNodeEntry.getValue());
+ }
+ }
+
+ private void updateQos(
+ TransactionBuilder transaction,
+ InstanceIdentifier<OvsdbNodeAugmentation> iid, OvsdbNodeAugmentation ovsdbNode) {
+
+ List<QosEntries> qosEntries = ovsdbNode.getQosEntries();
+
+ if (!getOperationalState().getBridgeNode(iid).isPresent()) {
+ return;
+ }
+ OvsdbNodeAugmentation operNode = getOperationalState().getBridgeNode(iid).get().getAugmentation(OvsdbNodeAugmentation.class);
+ List<QosEntries> operQosEntries = operNode.getQosEntries();
+
+ if (qosEntries != null) {
+ for (QosEntries qosEntry : qosEntries) {
+ Qos qos = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), Qos.class);
+
+ if (qosEntry.getQosType() != null) {
+ qos.setType(SouthboundMapper.createQosType(qosEntry.getQosType()));
+ }
+
+ Uuid qosUuid = getQosEntryUuid(operQosEntries, qosEntry.getQosId());
+ UUID uuid = null;
+ if (qosUuid != null) {
+ uuid = new UUID(qosUuid.getValue());
+ }
+
+ List<QueueList> queueList = qosEntry.getQueueList();
+ Map<Long, UUID>newQueueList = new HashMap<>();
+ if (queueList != null && !queueList.isEmpty()) {
+ for (QueueList queue : queueList) {
+ newQueueList.put(queue.getQueueNumber(), new UUID(queue.getQueueUuid().getValue()));
+ }
+ }
+ qos.setQueues(newQueueList);
+
+ List<QosExternalIds> externalIds = qosEntry.getQosExternalIds();
+ Map<String, String> externalIdsMap = new HashMap<>();
+ if (externalIds != null) {
+ for (QosExternalIds externalId : externalIds) {
+ externalIdsMap.put(externalId.getQosExternalIdKey(), externalId.getQosExternalIdValue());
+ }
+ }
+ externalIdsMap.put(SouthboundConstants.QOS_ID_EXTERNAL_ID_KEY, qosEntry.getQosId().getValue());
+ try {
+ qos.setExternalIds(ImmutableMap.copyOf(externalIdsMap));
+ } catch (NullPointerException e) {
+ LOG.warn("Incomplete Qos external IDs");
+ }
+
+ List<QosOtherConfig> otherConfigs = qosEntry.getQosOtherConfig();
+ if (otherConfigs != null) {
+ Map<String, String> otherConfigsMap = new HashMap<>();
+ for (QosOtherConfig otherConfig : otherConfigs) {
+ otherConfigsMap.put(otherConfig.getOtherConfigKey(), otherConfig.getOtherConfigValue());
+ }
+ try {
+ qos.setOtherConfig(ImmutableMap.copyOf(otherConfigsMap));
+ } catch (NullPointerException e) {
+ LOG.warn("Incomplete Qos other_config", e);
+ }
+ }
+ if (uuid == null) {
+ transaction.add(op.insert(qos)).build();
+ } else {
+ Qos extraQos = TyperUtils.getTypedRowWrapper(
+ transaction.getDatabaseSchema(), Qos.class, null);
+ extraQos.getUuidColumn().setData(uuid);
+ transaction.add(op.update(qos)
+ .where(extraQos.getUuidColumn().getSchema().opEqual(uuid)).build());
+ }
+ transaction.build();
+ }
+ }
+ }
+
+ private Uuid getQosEntryUuid(List<QosEntries> operQosEntries, Uri qosId) {
+ if (operQosEntries != null && !operQosEntries.isEmpty()) {
+ for (QosEntries qosEntry : operQosEntries) {
+ if (qosEntry.getQosId().equals(qosId)) {
+ return qosEntry.getQosUuid();
+ }
+ }
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Intel 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.ovsdb.transact;
+
+import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.ovsdb.lib.notation.Mutator;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.ovsdb.schema.openvswitch.Queue;
+import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
+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.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
+
+public class QueueRemovedCommand extends AbstractTransactCommand {
+ private static final Logger LOG = LoggerFactory.getLogger(QueueRemovedCommand.class);
+
+ public QueueRemovedCommand(BridgeOperationalState state,
+ AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+ super(state, changes);
+ }
+
+ @Override
+ public void execute(TransactionBuilder transaction) {
+ Set<InstanceIdentifier<Queues>> removed =
+ TransactUtils.extractRemoved(getChanges(),Queues.class);
+
+ Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> originals
+ = TransactUtils.extractOriginal(getChanges(),OvsdbNodeAugmentation.class);
+
+ Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> updated
+ = TransactUtils.extractUpdated(getChanges(), OvsdbNodeAugmentation.class);
+
+ Iterator<InstanceIdentifier<OvsdbNodeAugmentation>> itr = originals.keySet().iterator();
+ while (itr.hasNext()) {
+ InstanceIdentifier<OvsdbNodeAugmentation> ovsdbNodeIid = itr.next();
+ OvsdbNodeAugmentation original = originals.get(ovsdbNodeIid);
+ OvsdbNodeAugmentation update = updated.get(ovsdbNodeIid);
+
+ if (original != null && update != null) {
+ List<Queues> origQueues = original.getQueues();
+ List<Queues> updatedQueues = update.getQueues();
+ if (origQueues != null && !origQueues.isEmpty()) {
+ for (Queues origQueue : origQueues) {
+ OvsdbNodeAugmentation operNode = getOperationalState().getBridgeNode(ovsdbNodeIid).get().getAugmentation(OvsdbNodeAugmentation.class);
+ List<Queues> operQueues = operNode.getQueues();
+
+ boolean found = false;
+ if (updatedQueues != null && !updatedQueues.isEmpty()) {
+ for (Queues updatedQueue : updatedQueues) {
+ if (origQueue.getQueueId().equals(updatedQueue.getQueueId())) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ LOG.debug("Received request to delete Queue entry {}",origQueue.getQueueId());
+ Uuid queueUuid = getQueueUuid(operQueues, origQueue.getQueueId());
+ if (queueUuid != null) {
+ Queue queue = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), Queue.class, null);
+ transaction.add(op.delete(queue.getSchema())
+ .where(queue.getUuidColumn().getSchema().opEqual(new UUID(queueUuid.getValue())))
+ .build());
+ } else {
+ LOG.warn("Unable to delete Queue{} for node {} because it was not found in the operational store, "
+ + "and thus we cannot retrieve its UUID", ovsdbNodeIid, origQueue.getQueueId());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private Uuid getQueueUuid(List<Queues> operQueues, Uri queueId) {
+ if (operQueues != null && !operQueues.isEmpty()) {
+ for (Queues queueEntry : operQueues) {
+ if (queueEntry.getQueueId().equals(queueId)) {
+ return queueEntry.getQueueUuid();
+ }
+ }
+ }
+ return null;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Intel 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.ovsdb.transact;
+
+import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.ovsdb.lib.notation.Mutator;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.operations.Mutate;
+import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.ovsdb.schema.openvswitch.Qos;
+import org.opendaylight.ovsdb.schema.openvswitch.Queue;
+import org.opendaylight.ovsdb.southbound.SouthboundConstants;
+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.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+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.QosEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfig;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableMap;
+
+public class QueueUpdateCommand extends AbstractTransactCommand {
+ private static final Logger LOG = LoggerFactory.getLogger(QueueUpdateCommand.class);
+
+
+ public QueueUpdateCommand(BridgeOperationalState state, AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+ super(state, changes);
+ }
+
+ @Override
+ public void execute(TransactionBuilder transaction) {
+ Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> created =
+ TransactUtils.extractCreated(getChanges(),OvsdbNodeAugmentation.class);
+ for (Entry<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> ovsdbNodeEntry:
+ created.entrySet()) {
+ updateQueue(transaction, ovsdbNodeEntry.getKey(), ovsdbNodeEntry.getValue());
+ }
+ Map<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> updated =
+ TransactUtils.extractUpdated(getChanges(),OvsdbNodeAugmentation.class);
+ for (Entry<InstanceIdentifier<OvsdbNodeAugmentation>, OvsdbNodeAugmentation> ovsdbNodeEntry:
+ updated.entrySet()) {
+ updateQueue(transaction, ovsdbNodeEntry.getKey(), ovsdbNodeEntry.getValue());
+ }
+ }
+
+ private void updateQueue(
+ TransactionBuilder transaction,
+ InstanceIdentifier<OvsdbNodeAugmentation> iid, OvsdbNodeAugmentation ovsdbNode) {
+
+ List<Queues> queueList = ovsdbNode.getQueues();
+
+ if (!getOperationalState().getBridgeNode(iid).isPresent()) {
+ return;
+ }
+ OvsdbNodeAugmentation operNode = getOperationalState().getBridgeNode(iid).get().getAugmentation(OvsdbNodeAugmentation.class);
+ List<Queues> operQueues = operNode.getQueues();
+
+ if (queueList != null) {
+ for (Queues queueEntry : queueList) {
+ Queue queue = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), Queue.class);
+
+ if (queueEntry.getDscp() != null) {
+ try {
+ Set<Long> dscpSet = new HashSet<>();
+ if (dscpSet.add(new Long(queueEntry.getDscp().toString()))) {
+ queue.setDscp(dscpSet);
+ }
+ } catch (NumberFormatException e) {
+ LOG.warn("Invalid DSCP {} setting for Queue {}", queueEntry.getDscp(), queueEntry, e);
+ }
+ }
+
+ Uuid queueUuid = getQueueEntryUuid(operQueues, queueEntry.getQueueId());
+ UUID uuid = null;
+ if (queueUuid != null) {
+ uuid = new UUID(queueUuid.getValue());
+ }
+
+ List<QueuesExternalIds> externalIds = queueEntry.getQueuesExternalIds();
+ Map<String, String> externalIdsMap = new HashMap<>();
+ if (externalIds != null) {
+ for (QueuesExternalIds externalId : externalIds) {
+ externalIdsMap.put(externalId.getQueuesExternalIdKey(), externalId.getQueuesExternalIdValue());
+ }
+ }
+ externalIdsMap.put(SouthboundConstants.QUEUE_ID_EXTERNAL_ID_KEY, queueEntry.getQueueId().getValue());
+ try {
+ queue.setExternalIds(ImmutableMap.copyOf(externalIdsMap));
+ } catch (NullPointerException e) {
+ LOG.warn("Incomplete Queue external IDs");
+ }
+
+ List<QueuesOtherConfig> otherConfigs = queueEntry.getQueuesOtherConfig();
+ if (otherConfigs != null) {
+ Map<String, String> otherConfigsMap = new HashMap<>();
+ for (QueuesOtherConfig otherConfig : otherConfigs) {
+ otherConfigsMap.put(otherConfig.getQueueOtherConfigKey(), otherConfig.getQueueOtherConfigValue());
+ }
+ try {
+ queue.setOtherConfig(ImmutableMap.copyOf(otherConfigsMap));
+ } catch (NullPointerException e) {
+ LOG.warn("Incomplete Queue other_config", e);
+ }
+ }
+ if (uuid == null) {
+ transaction.add(op.insert(queue)).build();
+ } else {
+ transaction.add(op.update(queue)).build();
+ Queue extraQueue = TyperUtils.getTypedRowWrapper(
+ transaction.getDatabaseSchema(), Queue.class, null);
+ extraQueue.getUuidColumn().setData(uuid);
+ transaction.add(op.update(queue.getSchema())
+ .where(extraQueue.getUuidColumn().getSchema().opEqual(uuid)).build());
+ }
+ transaction.build();
+ }
+ }
+ }
+
+ private Uuid getQueueEntryUuid(List<Queues> operQueues, Uri queueId) {
+ if (operQueues != null && !operQueues.isEmpty()) {
+ for (Queues queueEntry : operQueues) {
+ if (queueEntry.getQueueId().equals(queueId)) {
+ return queueEntry.getQueueUuid();
+ }
+ }
+ }
+ return null;
+ }
+}
import java.util.Set;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
import org.opendaylight.ovsdb.schema.openvswitch.Interface;
import org.opendaylight.ovsdb.schema.openvswitch.Port;
import org.opendaylight.ovsdb.southbound.SouthboundConstants;
+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.OvsdbPortInterfaceAttributes.VlanMode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
updatePortVlanTrunk(terminationPoint, port);
updatePortVlanMode(terminationPoint, port);
updatePortExternalIds(terminationPoint, port);
+ updatePortQos(terminationPoint, port);
}
+ private void updatePortQos(
+ final OvsdbTerminationPointAugmentation terminationPoint,
+ final Port port) {
+
+ Set<UUID> uuidSet = Sets.newHashSet();
+ Uuid qosUuid = terminationPoint.getQos();
+ if (qosUuid != null) {
+ uuidSet.add(new UUID(qosUuid.getValue()));
+ }
+ port.setQos(uuidSet);
+ }
+
+
private void updateOfPort(
final OvsdbTerminationPointAugmentation terminationPoint,
final Interface ovsInterface) {
commands.add(new TerminationPointCreateCommand(state,changes));
commands.add(new TerminationPointDeleteCommand(state, changes));
commands.add(new OvsdbNodeUpdateCommand(changes));
+ commands.add(new QosUpdateCommand(state, changes));
+ commands.add(new QosRemovedCommand(state, changes));
+ commands.add(new QueueUpdateCommand(state, changes));
+ commands.add(new QueueRemovedCommand(state, changes));
commands.add(new TerminationPointUpdateCommand(state, changes));
}
commands.add(new OpenVSwitchUpdateCommand(key, updates, dbSchema));
commands.add(new OvsdbManagersUpdateCommand(key, updates, dbSchema));
commands.add(new OvsdbManagersRemovedCommand(key, updates, dbSchema));
+ commands.add(new OvsdbQosUpdateCommand(key, updates, dbSchema));
+ commands.add(new OvsdbQosRemovedCommand(key, updates, dbSchema));
+ commands.add(new OvsdbQueueUpdateCommand(key, updates, dbSchema));
+ commands.add(new OvsdbQueueRemovedCommand(key, updates, dbSchema));
commands.add(new OvsdbBridgeUpdateCommand(key, updates, dbSchema));
commands.add(new OvsdbBridgeRemovedCommand(key, updates, dbSchema));
commands.add(new OvsdbControllerUpdateCommand(key, updates, dbSchema));
interfaceOldRows.remove(interfaceUUID);
}
tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
- if (portOldRows.containsKey(portUpdate.getKey())) {
+ if (portOldRows.containsKey(portUpdate.getKey()) && !portQosCleared(portUpdate)) {
transaction.merge(LogicalDatastoreType.OPERATIONAL,
tpPath, tpBuilder.build());
} else {
updateVlan(port, ovsdbTerminationPointBuilder);
updateVlanTrunks(port, ovsdbTerminationPointBuilder);
updateVlanMode(port, ovsdbTerminationPointBuilder);
+ updateQos(port, ovsdbTerminationPointBuilder);
updatePortExternalIds(port, ovsdbTerminationPointBuilder);
updatePortOtherConfig(port, ovsdbTerminationPointBuilder);
}
}
}
+ private void updateQos(final Port port,
+ final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
+ if (port.getQosColumn() == null) {
+ return;
+ }
+ Collection<UUID> qosUuidCol = port.getQosColumn().getData();
+ if (!qosUuidCol.isEmpty()) {
+ Iterator<UUID> itr = qosUuidCol.iterator();
+ UUID qosUuid = itr.next();
+ ovsdbTerminationPointBuilder.setQos(new Uuid(qosUuid.toString()));
+ }
+ }
+
private void updateOfPort(final Interface interf,
final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
}
}
+ private boolean portQosCleared(Entry<UUID, Port> portUpdate) {
+ if (portUpdate.getValue().getQosColumn() == null) {
+ return false;
+ }
+ Collection<UUID> newQos = portUpdate.getValue().getQosColumn().getData();
+ if (portOldRows.get(portUpdate.getKey()).getQosColumn() == null) {
+ return false;
+ }
+ Collection<UUID> oldQos = portOldRows.get(portUpdate.getKey()).getQosColumn().getData();
+
+ if (newQos.isEmpty() && !oldQos.isEmpty()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
private InstanceIdentifier<TerminationPoint> getInstanceIdentifier(InstanceIdentifier<Node> bridgeIid,Port port) {
if (port.getExternalIdsColumn() != null
&& port.getExternalIdsColumn().getData() != null
--- /dev/null
+/*
+ * Copyright (c) 2016 Intel 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.Iterator;
+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.Qos;
+import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
+import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
+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.yang.types.rev130715.Uuid;
+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.QosEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class OvsdbQosRemovedCommand extends AbstractTransactionCommand {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsdbQueueUpdateCommand.class);
+
+ private Map<UUID, Qos> removedQosRows;
+ private Map<UUID, OpenVSwitch> updatedOpenVSwitchRows;
+
+ public OvsdbQosRemovedCommand(OvsdbConnectionInstance key,
+ TableUpdates updates, DatabaseSchema dbSchema) {
+ super(key, updates, dbSchema);
+ updatedOpenVSwitchRows = TyperUtils.extractRowsUpdated(OpenVSwitch.class, getUpdates(), getDbSchema());
+ removedQosRows = TyperUtils.extractRowsRemoved(Qos.class, getUpdates(), getDbSchema());
+ }
+
+ @Override
+ public void execute(ReadWriteTransaction transaction) {
+ final InstanceIdentifier<Node> nodeIId = getOvsdbConnectionInstance().getInstanceIdentifier();
+ final Optional<Node> ovsdbNode = SouthboundUtil.readNode(transaction, nodeIId);
+ if (ovsdbNode.isPresent()) {
+ for (@SuppressWarnings("unused") OpenVSwitch openVSwitch : updatedOpenVSwitchRows.values()) {
+ List<InstanceIdentifier<QosEntries>> result = new ArrayList<>();
+ InstanceIdentifier<Node> ovsdbNodeIid =
+ SouthboundMapper.createInstanceIdentifier(getOvsdbConnectionInstance().getNodeId());
+ if (removedQosRows != null && !removedQosRows.isEmpty()) {
+ for (UUID qosUuid : removedQosRows.keySet()) {
+ QosEntriesKey qosKey = getQosEntriesKey(ovsdbNode.get(), qosUuid);
+ if (qosKey != null) {
+ InstanceIdentifier<QosEntries> iid = ovsdbNodeIid
+ .augmentation(OvsdbNodeAugmentation.class)
+ .child(QosEntries.class, qosKey);
+ result.add(iid);
+ }
+ }
+ }
+ deleteQos(transaction, result);
+ }
+ }
+ }
+
+ private QosEntriesKey getQosEntriesKey(Node node, UUID qosUuid) {
+ List<QosEntries> qosList = node.getAugmentation(OvsdbNodeAugmentation.class).getQosEntries();
+ if (qosList == null || qosList.isEmpty()) {
+ LOG.debug("Deleting Qos {}, Ovsdb Node {} does not have a Qos list.", qosUuid.toString(), node);
+ return null;
+ }
+ Iterator<QosEntries> itr = qosList.iterator();
+ Uuid qUuid = new Uuid(qosUuid.toString());
+ while (itr.hasNext()) {
+ QosEntries qos = itr.next();
+ if (qos.getQosUuid().equals(qUuid)) {
+ return qos.getKey();
+ }
+ }
+ LOG.debug("Deleted Queue {} not found in Ovsdb Node {}", qosUuid.toString(), node);
+ return null;
+ }
+
+ private void deleteQos(ReadWriteTransaction transaction,
+ List<InstanceIdentifier<QosEntries>> qosEntryIids) {
+ for (InstanceIdentifier<QosEntries> qosEntryIid: qosEntryIids) {
+ transaction.delete(LogicalDatastoreType.OPERATIONAL, qosEntryIid);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Intel 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.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+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.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.Qos;
+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.yang.types.rev130715.Uuid;
+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.QosEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIdsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIdsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfigKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueListKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class OvsdbQosUpdateCommand extends AbstractTransactionCommand {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsdbQosUpdateCommand.class);
+
+ private Map<UUID, Qos> updatedQosRows;
+ private Map<UUID, Qos> oldQosRows;
+
+ public OvsdbQosUpdateCommand(OvsdbConnectionInstance key,
+ TableUpdates updates, DatabaseSchema dbSchema) {
+ super(key, updates, dbSchema);
+ updatedQosRows = TyperUtils.extractRowsUpdated(Qos.class,getUpdates(), getDbSchema());
+ oldQosRows = TyperUtils.extractRowsOld(Qos.class, getUpdates(), getDbSchema());
+ }
+
+ @Override
+ public void execute(ReadWriteTransaction transaction) {
+ if (updatedQosRows != null && !updatedQosRows.isEmpty()) {
+ updateQos(transaction, updatedQosRows);
+ }
+ }
+
+ /**
+ * Update the QosEntries values after finding the related {@link OpenVSwitch} list.
+ * <p>
+ * Qos and OpenVSwitch are independent tables in the Open_vSwitch schema
+ * but the OVSDB yang model includes the Qos fields in the
+ * OvsdbNode data. In some cases the OVSDB will send OpenVSwitch and Qos
+ * updates together and in other cases independently. This method here
+ * assumes the latter.
+ * </p>
+ *
+ * @param transaction the {@link ReadWriteTransaction}
+ * @param updatedQosRows updated {@link Qos} rows
+
+ */
+ private void updateQos(ReadWriteTransaction transaction,
+ Map<UUID, Qos> updatedQosRows) {
+
+ final InstanceIdentifier<Node> nodeIId = getOvsdbConnectionInstance().getInstanceIdentifier();
+ final Optional<Node> ovsdbNode = SouthboundUtil.readNode(transaction, nodeIId);
+ if (ovsdbNode.isPresent()) {
+ for (Entry<UUID, Qos> entry : updatedQosRows.entrySet()) {
+ Qos qos = entry.getValue();
+ Qos oldQos = oldQosRows.get(entry.getKey());
+ QosEntriesBuilder qosEntryBuilder = new QosEntriesBuilder();
+ qosEntryBuilder.setQosId(new Uri(getQosId(qos)));
+ qosEntryBuilder.setQosUuid(new Uuid(entry.getKey().toString()));
+ qosEntryBuilder.setQosType(
+ SouthboundMapper.createQosType(qos.getTypeColumn().getData().toString()));
+ setOtherConfig(transaction, qosEntryBuilder, oldQos, qos, nodeIId);
+ setExternalIds(transaction, qosEntryBuilder, oldQos, qos, nodeIId);
+ setQueueList(transaction, qosEntryBuilder, oldQos, qos, nodeIId);
+
+ QosEntries qosEntry = qosEntryBuilder.build();
+ LOG.debug("Update Ovsdb Node {} with qos entries {}",ovsdbNode.get(), qosEntry);
+ InstanceIdentifier<QosEntries> iid = nodeIId
+ .augmentation(OvsdbNodeAugmentation.class)
+ .child(QosEntries.class, qosEntry.getKey());
+ transaction.merge(LogicalDatastoreType.OPERATIONAL,
+ iid, qosEntry);
+ }
+ }
+ }
+
+ private String getQosId(Qos qos) {
+ if (qos.getExternalIdsColumn() != null
+ && qos.getExternalIdsColumn().getData() != null
+ && qos.getExternalIdsColumn().getData().containsKey(SouthboundConstants.QOS_ID_EXTERNAL_ID_KEY)) {
+ return qos.getExternalIdsColumn().getData().get(SouthboundConstants.QOS_ID_EXTERNAL_ID_KEY);
+ } else {
+ return SouthboundConstants.QOS_URI_PREFIX + "://" + qos.getUuid().toString();
+ }
+ }
+
+ private void setOtherConfig(ReadWriteTransaction transaction,
+ QosEntriesBuilder qosEntryBuilder, Qos oldQos, Qos qos,
+ InstanceIdentifier<Node> nodeIId) {
+ Map<String, String> oldOtherConfigs = null;
+ Map<String, String> otherConfigs = null;
+
+ if (qos.getOtherConfigColumn() != null) {
+ otherConfigs = qos.getOtherConfigColumn().getData();
+ }
+ if (oldQos != null && oldQos.getOtherConfigColumn() != null) {
+ oldOtherConfigs = oldQos.getOtherConfigColumn().getData();
+ }
+ if ((oldOtherConfigs != null) && !oldOtherConfigs.isEmpty()) {
+ removeOldConfigs(transaction, qosEntryBuilder, oldOtherConfigs, qos, nodeIId);
+ }
+ if (otherConfigs != null && !otherConfigs.isEmpty()) {
+ setNewOtherConfigs(qosEntryBuilder, otherConfigs);
+ }
+ }
+
+ private void removeOldConfigs(ReadWriteTransaction transaction,
+ QosEntriesBuilder qosEntryBuilder, Map<String, String> oldOtherConfigs,
+ Qos qos, InstanceIdentifier<Node> nodeIId) {
+ InstanceIdentifier<QosEntries> qosIId = nodeIId
+ .augmentation(OvsdbNodeAugmentation.class)
+ .child(QosEntries.class, qosEntryBuilder.build().getKey());
+ Set<String> otherConfigKeys = oldOtherConfigs.keySet();
+ for (String otherConfigKey : otherConfigKeys) {
+ KeyedInstanceIdentifier<QosOtherConfig, QosOtherConfigKey> otherIId =
+ qosIId
+ .child(QosOtherConfig.class, new QosOtherConfigKey(otherConfigKey));
+ transaction.delete(LogicalDatastoreType.OPERATIONAL, otherIId);
+ }
+ }
+
+ private void setNewOtherConfigs(QosEntriesBuilder qosEntryBuilder,
+ Map<String, String> otherConfig) {
+ Set<String> otherConfigKeys = otherConfig.keySet();
+ List<QosOtherConfig> otherConfigList = new ArrayList<>();
+ String otherConfigValue;
+ for (String otherConfigKey : otherConfigKeys) {
+ otherConfigValue = otherConfig.get(otherConfigKey);
+ if (otherConfigKey != null && otherConfigValue != null) {
+ otherConfigList.add(new QosOtherConfigBuilder().setOtherConfigKey(otherConfigKey)
+ .setOtherConfigValue(otherConfigValue).build());
+ }
+ }
+ qosEntryBuilder.setQosOtherConfig(otherConfigList);
+ }
+
+ private void setExternalIds(ReadWriteTransaction transaction,
+ QosEntriesBuilder qosEntryBuilder, Qos oldQos, Qos qos,
+ InstanceIdentifier<Node> nodeIId) {
+ Map<String, String> oldExternalIds = null;
+ Map<String, String> externalIds = null;
+
+ if (qos.getExternalIdsColumn() != null) {
+ externalIds = qos.getExternalIdsColumn().getData();
+ }
+ if (oldQos != null && oldQos.getExternalIdsColumn() != null) {
+ oldExternalIds = oldQos.getExternalIdsColumn().getData();
+ }
+ if ((oldExternalIds != null) && !oldExternalIds.isEmpty()) {
+ removeOldExternalIds(transaction, qosEntryBuilder, oldExternalIds, qos, nodeIId);
+ }
+ if (externalIds != null && !externalIds.isEmpty()) {
+ setNewExternalIds(qosEntryBuilder, externalIds);
+ }
+ }
+
+ private void removeOldExternalIds(ReadWriteTransaction transaction,
+ QosEntriesBuilder qosEntryBuilder, Map<String, String> oldExternalIds,
+ Qos qos, InstanceIdentifier<Node> nodeIId) {
+ InstanceIdentifier<QosEntries> qosIId = nodeIId
+ .augmentation(OvsdbNodeAugmentation.class)
+ .child(QosEntries.class, qosEntryBuilder.build().getKey());
+ Set<String> externalIdsKeys = oldExternalIds.keySet();
+ for (String extIdKey : externalIdsKeys) {
+ KeyedInstanceIdentifier<QosExternalIds, QosExternalIdsKey> externalIId =
+ qosIId
+ .child(QosExternalIds.class, new QosExternalIdsKey(extIdKey));
+ transaction.delete(LogicalDatastoreType.OPERATIONAL, externalIId);
+ }
+ }
+
+ private void setNewExternalIds(QosEntriesBuilder qosEntryBuilder,
+ Map<String, String> externalIds) {
+ Set<String> externalIdsKeys = externalIds.keySet();
+ List<QosExternalIds> externalIdsList = new ArrayList<>();
+ String extIdValue;
+ for (String extIdKey : externalIdsKeys) {
+ extIdValue = externalIds.get(extIdKey);
+ if (extIdKey != null && extIdValue != null) {
+ externalIdsList.add(new QosExternalIdsBuilder().setQosExternalIdKey(extIdKey)
+ .setQosExternalIdValue(extIdValue).build());
+ }
+ }
+ qosEntryBuilder.setQosExternalIds(externalIdsList);
+ }
+
+ private void setQueueList(ReadWriteTransaction transaction,
+ QosEntriesBuilder qosEntryBuilder, Qos oldQos, Qos qos,
+ InstanceIdentifier<Node> nodeIId) {
+ Map<Long,UUID> oldQueueList = null;
+ Map<Long,UUID> queueList = null;
+
+ if (qos.getQueuesColumn() != null) {
+ queueList = qos.getQueuesColumn().getData();
+ }
+ if (oldQos != null && oldQos.getQueuesColumn() != null) {
+ oldQueueList = oldQos.getQueuesColumn().getData();
+ }
+ if ((oldQueueList != null) && !oldQueueList.isEmpty()) {
+ removeOldQueues(transaction, qosEntryBuilder, oldQueueList, qos, nodeIId);
+ }
+ if (queueList != null && !queueList.isEmpty()) {
+ setNewQueues(qosEntryBuilder, queueList);
+ }
+ }
+
+ private void removeOldQueues(ReadWriteTransaction transaction,
+ QosEntriesBuilder qosEntryBuilder, Map<Long, UUID> oldQueueList,
+ Qos qos, InstanceIdentifier<Node> nodeIId) {
+ InstanceIdentifier<QosEntries> qosIId = nodeIId
+ .augmentation(OvsdbNodeAugmentation.class)
+ .child(QosEntries.class, qosEntryBuilder.build().getKey());
+ Collection<Long> queueListKeys = oldQueueList.keySet();
+ for (Long queueListKey : queueListKeys) {
+ KeyedInstanceIdentifier<QueueList, QueueListKey> otherIId =
+ qosIId
+ .child(QueueList.class, new QueueListKey(new Long(queueListKey.toString())));
+ transaction.delete(LogicalDatastoreType.OPERATIONAL, otherIId);
+ }
+ }
+
+ private void setNewQueues(QosEntriesBuilder qosEntryBuilder,
+ Map<Long, UUID> queueList) {
+ Set<Entry<Long, UUID>> queueEntries = queueList.entrySet();
+ List<QueueList> newQueueList = new ArrayList<>();
+ for (Entry<Long, UUID> queueEntry : queueEntries) {
+ newQueueList.add(
+ new QueueListBuilder().setQueueNumber(queueEntry.getKey())
+ .setQueueUuid(new Uuid(queueEntry.getValue().toString())).build());
+ }
+ qosEntryBuilder.setQueueList(newQueueList);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Intel 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.Iterator;
+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.OpenVSwitch;
+import org.opendaylight.ovsdb.schema.openvswitch.Queue;
+import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
+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.yang.types.rev130715.Uuid;
+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.Queues;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class OvsdbQueueRemovedCommand extends AbstractTransactionCommand {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsdbQueueUpdateCommand.class);
+
+ private Map<UUID, Queue> removedQueueRows;
+ private Map<UUID, OpenVSwitch> updatedOpenVSwitchRows;
+
+ public OvsdbQueueRemovedCommand(OvsdbConnectionInstance key,
+ TableUpdates updates, DatabaseSchema dbSchema) {
+ super(key, updates, dbSchema);
+ updatedOpenVSwitchRows = TyperUtils.extractRowsUpdated(OpenVSwitch.class, getUpdates(), getDbSchema());
+ removedQueueRows = TyperUtils.extractRowsRemoved(Queue.class, getUpdates(), getDbSchema());
+ }
+
+ @Override
+ public void execute(ReadWriteTransaction transaction) {
+ final InstanceIdentifier<Node> nodeIId = getOvsdbConnectionInstance().getInstanceIdentifier();
+ final Optional<Node> ovsdbNode = SouthboundUtil.readNode(transaction, nodeIId);
+ if (ovsdbNode.isPresent()) {
+ for (@SuppressWarnings("unused") OpenVSwitch openVSwitch : updatedOpenVSwitchRows.values()) {
+ List<InstanceIdentifier<Queues>> result = new ArrayList<>();
+ InstanceIdentifier<Node> ovsdbNodeIid =
+ SouthboundMapper.createInstanceIdentifier(getOvsdbConnectionInstance().getNodeId());
+ if (removedQueueRows != null && !removedQueueRows.isEmpty()) {
+ for (UUID queueUuid : removedQueueRows.keySet()) {
+ QueuesKey queueKey = getQueueKey(ovsdbNode.get(), queueUuid);
+ if (queueKey != null) {
+ InstanceIdentifier<Queues> iid = ovsdbNodeIid
+ .augmentation(OvsdbNodeAugmentation.class)
+ .child(Queues.class, queueKey);
+ result.add(iid);
+ }
+ }
+ }
+ deleteQueue(transaction, result);
+ }
+ }
+ }
+
+ private QueuesKey getQueueKey(Node node, UUID queueUuid) {
+ List<Queues> queueList = node.getAugmentation(OvsdbNodeAugmentation.class).getQueues();
+ if (queueList == null || queueList.isEmpty()) {
+ LOG.debug("Deleting Queue {}, Ovsdb Node {} does not have a Queue list.", queueUuid.toString(), node);
+ return null;
+ }
+ Iterator<Queues> itr = queueList.iterator();
+ Uuid qUuid = new Uuid(queueUuid.toString());
+ while (itr.hasNext()) {
+ Queues queue = itr.next();
+ if (queue.getQueueUuid().equals(qUuid)) {
+ return queue.getKey();
+ }
+ }
+ LOG.debug("Deleted Queue {} not found in Ovsdb Node {}", queueUuid.toString(), node);
+ return null;
+ }
+
+ private void deleteQueue(ReadWriteTransaction transaction,
+ List<InstanceIdentifier<Queues>> queueIids) {
+ for (InstanceIdentifier<Queues> queueIid: queueIids) {
+ transaction.delete(LogicalDatastoreType.OPERATIONAL, queueIid);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Intel 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.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+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.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.Queue;
+import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
+import org.opendaylight.ovsdb.southbound.SouthboundConstants;
+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.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIdsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIdsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfigKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class OvsdbQueueUpdateCommand extends AbstractTransactionCommand {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsdbQueueUpdateCommand.class);
+
+ private Map<UUID, Queue> updatedQueueRows;
+ private Map<UUID, Queue> oldQueueRows;
+
+ public OvsdbQueueUpdateCommand(OvsdbConnectionInstance key,
+ TableUpdates updates, DatabaseSchema dbSchema) {
+ super(key, updates, dbSchema);
+ updatedQueueRows = TyperUtils.extractRowsUpdated(Queue.class,getUpdates(), getDbSchema());
+ oldQueueRows = TyperUtils.extractRowsOld(Queue.class, getUpdates(), getDbSchema());
+ }
+
+ @Override
+ public void execute(ReadWriteTransaction transaction) {
+ if (updatedQueueRows != null && !updatedQueueRows.isEmpty()) {
+ updateQueue(transaction);
+ }
+ }
+
+ /**
+ * Update the Queues values after finding the related {@OpenVSwitch} list.
+ * <p>
+ * Queue and OpenVSwitch are independent tables in the Open_vSwitch schema
+ * but the OVSDB yang model includes the Queue fields in the
+ * OvsdbNode data. In some cases the OVSDB will send OpenVSwitch and Queue
+ * updates together and in other cases independently. This method here
+ * assumes the latter.
+ * </p>
+ *
+ * @param transaction the {@link ReadWriteTransaction}
+ * @param updatedQueueRows updated {@link Queue} rows
+
+ */
+ private void updateQueue(ReadWriteTransaction transaction) {
+
+ final InstanceIdentifier<Node> nodeIId = getOvsdbConnectionInstance().getInstanceIdentifier();
+ final Optional<Node> ovsdbNode = SouthboundUtil.readNode(transaction, nodeIId);
+ if (ovsdbNode.isPresent()) {
+ for (Entry<UUID, Queue> entry : updatedQueueRows.entrySet()) {
+ Queue queue = entry.getValue();
+ Queue oldQueue = oldQueueRows.get(entry.getKey());
+ QueuesBuilder queuesBuilder = new QueuesBuilder();
+ queuesBuilder.setQueueId(new Uri(getQueueId(queue)));
+ queuesBuilder.setQueueUuid(new Uuid(entry.getKey().toString()));
+ Collection<Long> dscp = queue.getDscpColumn().getData();
+ if (!dscp.isEmpty()) {
+ try {
+ queuesBuilder.setDscp(new Short(dscp.iterator().next().toString()));
+ } catch (NumberFormatException e) {
+ queuesBuilder.setDscp(new Short("0"));
+ }
+ }
+ setOtherConfig(transaction, queuesBuilder, oldQueue, queue, nodeIId);
+ setExternalIds(transaction, queuesBuilder, oldQueue, queue, nodeIId);
+
+ Queues queues = queuesBuilder.build();
+ LOG.debug("Update Ovsdb Node {} with queue entries {}",ovsdbNode.get(), queues);
+ InstanceIdentifier<Queues> iid = nodeIId
+ .augmentation(OvsdbNodeAugmentation.class)
+ .child(Queues.class, queues.getKey());
+ transaction.merge(LogicalDatastoreType.OPERATIONAL,
+ iid, queues);
+ }
+ }
+ }
+
+ private String getQueueId(Queue queue) {
+ if (queue.getExternalIdsColumn() != null
+ && queue.getExternalIdsColumn().getData() != null
+ && queue.getExternalIdsColumn().getData().containsKey(SouthboundConstants.QUEUE_ID_EXTERNAL_ID_KEY)) {
+ return queue.getExternalIdsColumn().getData().get(SouthboundConstants.QUEUE_ID_EXTERNAL_ID_KEY);
+ } else {
+ return SouthboundConstants.QUEUE_URI_PREFIX + "://" + queue.getUuid().toString();
+ }
+ }
+
+ private void setOtherConfig(ReadWriteTransaction transaction,
+ QueuesBuilder queuesBuilder, Queue oldQueue, Queue queue,
+ InstanceIdentifier<Node> nodeIId) {
+ Map<String, String> oldOtherConfigs = null;
+ Map<String, String> otherConfigs = null;
+
+ if (queue.getOtherConfigColumn() != null) {
+ otherConfigs = queue.getOtherConfigColumn().getData();
+ }
+ if (oldQueue != null && oldQueue.getOtherConfigColumn() != null) {
+ oldOtherConfigs = oldQueue.getOtherConfigColumn().getData();
+ }
+ if ((oldOtherConfigs != null) && !oldOtherConfigs.isEmpty()) {
+ removeOldConfigs(transaction, queuesBuilder, oldOtherConfigs, queue, nodeIId);
+ }
+ if (otherConfigs != null && !otherConfigs.isEmpty()) {
+ setNewOtherConfigs(queuesBuilder, otherConfigs);
+ }
+ }
+
+ private void removeOldConfigs(ReadWriteTransaction transaction,
+ QueuesBuilder queuesBuilder, Map<String, String> oldOtherConfigs,
+ Queue queue, InstanceIdentifier<Node> nodeIId) {
+ InstanceIdentifier<Queues> queueIId = nodeIId
+ .augmentation(OvsdbNodeAugmentation.class)
+ .child(Queues.class, queuesBuilder.build().getKey());
+ Set<String> otherConfigKeys = oldOtherConfigs.keySet();
+ for (String otherConfigKey : otherConfigKeys) {
+ KeyedInstanceIdentifier<QueuesOtherConfig, QueuesOtherConfigKey> otherIId =
+ queueIId
+ .child(QueuesOtherConfig.class, new QueuesOtherConfigKey(otherConfigKey));
+ transaction.delete(LogicalDatastoreType.OPERATIONAL, otherIId);
+ }
+ }
+
+ private void setNewOtherConfigs(QueuesBuilder queuesBuilder,
+ Map<String, String> otherConfig) {
+ Set<String> otherConfigKeys = otherConfig.keySet();
+ List<QueuesOtherConfig> otherConfigList = new ArrayList<>();
+ String otherConfigValue;
+ for (String otherConfigKey : otherConfigKeys) {
+ otherConfigValue = otherConfig.get(otherConfigKey);
+ if (otherConfigKey != null && otherConfigValue != null) {
+ otherConfigList.add(new QueuesOtherConfigBuilder().setQueueOtherConfigKey(otherConfigKey)
+ .setQueueOtherConfigValue(otherConfigValue).build());
+ }
+ }
+ queuesBuilder.setQueuesOtherConfig(otherConfigList);
+ }
+
+ private void setExternalIds(ReadWriteTransaction transaction,
+ QueuesBuilder queuesBuilder, Queue oldQueue, Queue queue,
+ InstanceIdentifier<Node> nodeIId) {
+ Map<String, String> oldExternalIds = null;
+ Map<String, String> externalIds = null;
+
+ if (queue.getExternalIdsColumn() != null) {
+ externalIds = queue.getExternalIdsColumn().getData();
+ }
+ if (oldQueue != null && oldQueue.getExternalIdsColumn() != null) {
+ oldExternalIds = oldQueue.getExternalIdsColumn().getData();
+ }
+ if ((oldExternalIds != null) && !oldExternalIds.isEmpty()) {
+ removeOldExternalIds(transaction, queuesBuilder, oldExternalIds, queue, nodeIId);
+ }
+ if (externalIds != null && !externalIds.isEmpty()) {
+ setNewExternalIds(queuesBuilder, externalIds);
+ }
+ }
+
+ private void removeOldExternalIds(ReadWriteTransaction transaction,
+ QueuesBuilder queuesBuilder, Map<String, String> oldExternalIds,
+ Queue queue, InstanceIdentifier<Node> nodeIId) {
+ InstanceIdentifier<Queues> queueIId = nodeIId
+ .augmentation(OvsdbNodeAugmentation.class)
+ .child(Queues.class, queuesBuilder.build().getKey());
+ Set<String> externalIdsKeys = oldExternalIds.keySet();
+ for (String extIdKey : externalIdsKeys) {
+ KeyedInstanceIdentifier<QueuesExternalIds, QueuesExternalIdsKey> externalIId =
+ queueIId
+ .child(QueuesExternalIds.class, new QueuesExternalIdsKey(extIdKey));
+ transaction.delete(LogicalDatastoreType.OPERATIONAL, externalIId);
+ }
+ }
+
+ private void setNewExternalIds(QueuesBuilder queuesBuilder,
+ Map<String, String> externalIds) {
+ Set<String> externalIdsKeys = externalIds.keySet();
+ List<QueuesExternalIds> externalIdsList = new ArrayList<>();
+ String externalIdValue;
+ for (String extIdKey : externalIdsKeys) {
+ externalIdValue = externalIds.get(extIdKey);
+ if (extIdKey != null && externalIdValue != null) {
+ externalIdsList.add(new QueuesExternalIdsBuilder().setQueuesExternalIdKey(extIdKey)
+ .setQueuesExternalIdValue(externalIdValue).build());
+ }
+ }
+ queuesBuilder.setQueuesExternalIds(externalIdsList);
+ }
+
+}
@PrepareForTest({})
@RunWith(PowerMockRunner.class)
public class TransactCommandAggregatorTest {
- private static final int NUMBER_OF_COMMANDS = 11;
+ private static final int NUMBER_OF_COMMANDS = 15;
private List<TransactCommand> commands = new ArrayList<>();
private TransactCommandAggregator transactCommandAggregator;
@Mock private AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes;
commands.add(mock(TerminationPointCreateCommand.class));
commands.add(mock(TerminationPointDeleteCommand.class));
commands.add(mock(OvsdbNodeUpdateCommand.class));
+ commands.add(mock(QosUpdateCommand.class));
+ commands.add(mock(QosRemovedCommand.class));
+ commands.add(mock(QueueUpdateCommand.class));
+ commands.add(mock(QueueRemovedCommand.class));
commands.add(mock(TerminationPointUpdateCommand.class));
MemberModifier.field(TransactCommandAggregator.class, "commands").set(transactCommandAggregator, commands);
}
@PrepareForTest({})
@RunWith(PowerMockRunner.class)
public class OvsdbOperationalCommandAggregatorTest {
- private static final int NUMBER_OF_COMMANDS = 9;
+ private static final int NUMBER_OF_COMMANDS = 13;
private List<TransactionCommand> commands = new ArrayList<>();
private OvsdbOperationalCommandAggregator ovsdbOperationalCommandAggregator;
commands.add(mock(OpenVSwitchUpdateCommand.class));
commands.add(mock(OvsdbManagersUpdateCommand.class));
commands.add(mock(OvsdbManagersRemovedCommand.class));
+ commands.add(mock(OvsdbQosUpdateCommand.class));
+ commands.add(mock(OvsdbQosRemovedCommand.class));
+ commands.add(mock(OvsdbQueueUpdateCommand.class));
+ commands.add(mock(OvsdbQueueRemovedCommand.class));
commands.add(mock(OvsdbBridgeUpdateCommand.class));
commands.add(mock(OvsdbBridgeRemovedCommand.class));
commands.add(mock(OvsdbControllerUpdateCommand.class));