BUG 5746 - Ovsdb QoS and Queue model enhancements
[ovsdb.git] / southbound / southbound-impl / src / main / java / org / opendaylight / ovsdb / southbound / transactions / md / OvsdbQueueUpdateCommand.java
1 /*
2  * Copyright (c) 2016 Intel Communications Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.ovsdb.southbound.transactions.md;
10
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16 import java.util.Map.Entry;
17
18 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.ovsdb.lib.message.TableUpdates;
21 import org.opendaylight.ovsdb.lib.notation.UUID;
22 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
23 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
24 import org.opendaylight.ovsdb.schema.openvswitch.Queue;
25 import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
26 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
27 import org.opendaylight.ovsdb.southbound.SouthboundUtil;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIds;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIdsBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIdsKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfig;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfigBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfigKey;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 import com.google.common.base.Optional;
47
48 public class OvsdbQueueUpdateCommand extends AbstractTransactionCommand {
49     private static final Logger LOG = LoggerFactory.getLogger(OvsdbQueueUpdateCommand.class);
50
51     private Map<UUID, Queue> updatedQueueRows;
52     private Map<UUID, Queue> oldQueueRows;
53
54     public OvsdbQueueUpdateCommand(OvsdbConnectionInstance key,
55             TableUpdates updates, DatabaseSchema dbSchema) {
56         super(key, updates, dbSchema);
57         updatedQueueRows = TyperUtils.extractRowsUpdated(Queue.class,getUpdates(), getDbSchema());
58         oldQueueRows = TyperUtils.extractRowsOld(Queue.class, getUpdates(), getDbSchema());
59     }
60
61     @Override
62     public void execute(ReadWriteTransaction transaction) {
63         if (updatedQueueRows != null && !updatedQueueRows.isEmpty()) {
64             updateQueue(transaction);
65         }
66     }
67
68     /**
69      * Update the Queues values after finding the related {@OpenVSwitch} list.
70      * <p>
71      * Queue and OpenVSwitch are independent tables in the Open_vSwitch schema
72      * but the OVSDB yang model includes the Queue fields in the
73      * OvsdbNode data. In some cases the OVSDB will send OpenVSwitch and Queue
74      * updates together and in other cases independently. This method here
75      * assumes the latter.
76      * </p>
77      *
78      * @param transaction the {@link ReadWriteTransaction}
79      * @param updatedQueueRows updated {@link Queue} rows
80
81      */
82     private void updateQueue(ReadWriteTransaction transaction) {
83
84         final InstanceIdentifier<Node> nodeIId = getOvsdbConnectionInstance().getInstanceIdentifier();
85         final Optional<Node> ovsdbNode = SouthboundUtil.readNode(transaction, nodeIId);
86         if (ovsdbNode.isPresent()) {
87             for (Entry<UUID, Queue> entry : updatedQueueRows.entrySet()) {
88                 Queue queue = entry.getValue();
89                 Queue oldQueue = oldQueueRows.get(entry.getKey());
90                 QueuesBuilder queuesBuilder = new QueuesBuilder();
91                 queuesBuilder.setQueueId(new Uri(getQueueId(queue)));
92                 queuesBuilder.setQueueUuid(new Uuid(entry.getKey().toString()));
93                 Collection<Long> dscp = queue.getDscpColumn().getData();
94                 if (!dscp.isEmpty()) {
95                     queuesBuilder.setDscp(dscp.iterator().next().shortValue());
96                 }
97                 setOtherConfig(transaction, queuesBuilder, oldQueue, queue, nodeIId);
98                 setExternalIds(transaction, queuesBuilder, oldQueue, queue, nodeIId);
99
100                 Queues queues = queuesBuilder.build();
101                 LOG.debug("Update Ovsdb Node {} with queue entries {}",ovsdbNode.get(), queues);
102                 InstanceIdentifier<Queues> iid = nodeIId
103                         .augmentation(OvsdbNodeAugmentation.class)
104                         .child(Queues.class, queues.getKey());
105                 transaction.merge(LogicalDatastoreType.OPERATIONAL,
106                         iid, queues);
107             }
108         }
109     }
110
111     private String getQueueId(Queue queue) {
112         if (queue.getExternalIdsColumn() != null
113                 && queue.getExternalIdsColumn().getData() != null
114                 && queue.getExternalIdsColumn().getData().containsKey(SouthboundConstants.IID_EXTERNAL_ID_KEY)) {
115             InstanceIdentifier<Queues> queueIid = (InstanceIdentifier<Queues>) SouthboundUtil.deserializeInstanceIdentifier(
116                     queue.getExternalIdsColumn().getData().get(SouthboundConstants.IID_EXTERNAL_ID_KEY));
117             if (queueIid != null) {
118                 QueuesKey queuesKey = queueIid.firstKeyOf(Queues.class);
119                 if (queuesKey != null) {
120                     return queuesKey.getQueueId().getValue();
121                 }
122             }
123         }
124         return SouthboundConstants.QUEUE_URI_PREFIX + "://" + queue.getUuid().toString();
125     }
126
127     private void setOtherConfig(ReadWriteTransaction transaction,
128             QueuesBuilder queuesBuilder, Queue oldQueue, Queue queue,
129             InstanceIdentifier<Node> nodeIId) {
130         Map<String, String> oldOtherConfigs = null;
131         Map<String, String> otherConfigs = null;
132
133         if (queue.getOtherConfigColumn() != null) {
134             otherConfigs = queue.getOtherConfigColumn().getData();
135         }
136         if (oldQueue != null && oldQueue.getOtherConfigColumn() != null) {
137             oldOtherConfigs = oldQueue.getOtherConfigColumn().getData();
138         }
139         if ((oldOtherConfigs != null) && !oldOtherConfigs.isEmpty()) {
140             removeOldConfigs(transaction, queuesBuilder, oldOtherConfigs, queue, nodeIId);
141         }
142         if (otherConfigs != null && !otherConfigs.isEmpty()) {
143             setNewOtherConfigs(queuesBuilder, otherConfigs);
144         }
145     }
146
147     private void removeOldConfigs(ReadWriteTransaction transaction,
148             QueuesBuilder queuesBuilder, Map<String, String> oldOtherConfigs,
149             Queue queue, InstanceIdentifier<Node> nodeIId) {
150         InstanceIdentifier<Queues> queueIId = nodeIId
151                 .augmentation(OvsdbNodeAugmentation.class)
152                 .child(Queues.class, queuesBuilder.build().getKey());
153         Set<String> otherConfigKeys = oldOtherConfigs.keySet();
154         for (String otherConfigKey : otherConfigKeys) {
155             KeyedInstanceIdentifier<QueuesOtherConfig, QueuesOtherConfigKey> otherIId =
156                     queueIId
157                     .child(QueuesOtherConfig.class, new QueuesOtherConfigKey(otherConfigKey));
158             transaction.delete(LogicalDatastoreType.OPERATIONAL, otherIId);
159         }
160     }
161
162     private void setNewOtherConfigs(QueuesBuilder queuesBuilder,
163             Map<String, String> otherConfig) {
164         Set<String> otherConfigKeys = otherConfig.keySet();
165         List<QueuesOtherConfig> otherConfigList = new ArrayList<>();
166         String otherConfigValue;
167         for (String otherConfigKey : otherConfigKeys) {
168             otherConfigValue = otherConfig.get(otherConfigKey);
169             if (otherConfigKey != null && otherConfigValue != null) {
170                 otherConfigList.add(new QueuesOtherConfigBuilder().setQueueOtherConfigKey(otherConfigKey)
171                         .setQueueOtherConfigValue(otherConfigValue).build());
172             }
173         }
174         queuesBuilder.setQueuesOtherConfig(otherConfigList);
175     }
176
177     private void setExternalIds(ReadWriteTransaction transaction,
178             QueuesBuilder queuesBuilder, Queue oldQueue, Queue queue,
179             InstanceIdentifier<Node> nodeIId) {
180         Map<String, String> oldExternalIds = null;
181         Map<String, String> externalIds = null;
182
183         if (queue.getExternalIdsColumn() != null) {
184             externalIds = queue.getExternalIdsColumn().getData();
185         }
186         if (oldQueue != null && oldQueue.getExternalIdsColumn() != null) {
187             oldExternalIds = oldQueue.getExternalIdsColumn().getData();
188         }
189         if ((oldExternalIds != null) && !oldExternalIds.isEmpty()) {
190             removeOldExternalIds(transaction, queuesBuilder, oldExternalIds, queue, nodeIId);
191         }
192         if (externalIds != null && !externalIds.isEmpty()) {
193             setNewExternalIds(queuesBuilder, externalIds);
194         }
195     }
196
197     private void removeOldExternalIds(ReadWriteTransaction transaction,
198             QueuesBuilder queuesBuilder, Map<String, String> oldExternalIds,
199             Queue queue, InstanceIdentifier<Node> nodeIId) {
200         InstanceIdentifier<Queues> queueIId = nodeIId
201                 .augmentation(OvsdbNodeAugmentation.class)
202                 .child(Queues.class, queuesBuilder.build().getKey());
203         Set<String> externalIdsKeys = oldExternalIds.keySet();
204         for (String extIdKey : externalIdsKeys) {
205             KeyedInstanceIdentifier<QueuesExternalIds, QueuesExternalIdsKey> externalIId =
206                     queueIId
207                     .child(QueuesExternalIds.class, new QueuesExternalIdsKey(extIdKey));
208             transaction.delete(LogicalDatastoreType.OPERATIONAL, externalIId);
209         }
210     }
211
212     private void setNewExternalIds(QueuesBuilder queuesBuilder,
213             Map<String, String> externalIds) {
214         Set<String> externalIdsKeys = externalIds.keySet();
215         List<QueuesExternalIds> externalIdsList = new ArrayList<>();
216         String externalIdValue;
217         for (String extIdKey : externalIdsKeys) {
218             externalIdValue = externalIds.get(extIdKey);
219             if (extIdKey != null && externalIdValue != null) {
220                 externalIdsList.add(new QueuesExternalIdsBuilder().setQueuesExternalIdKey(extIdKey)
221                         .setQueuesExternalIdValue(externalIdValue).build());
222             }
223         }
224         queuesBuilder.setQueuesExternalIds(externalIdsList);
225     }
226
227 }