2 * Copyright (c) 2015, 2017 China Telecom Beijing Research Institute and others. All rights reserved.
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
9 package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
11 import com.google.common.base.Preconditions;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.HashMap;
15 import java.util.List;
17 import java.util.Map.Entry;
18 import java.util.Optional;
20 import java.util.concurrent.ConcurrentHashMap;
21 import org.apache.commons.lang3.tuple.Pair;
22 import org.opendaylight.mdsal.binding.api.DataBroker;
23 import org.opendaylight.mdsal.binding.api.DataTreeModification;
24 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
25 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
26 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepConnectionInstance;
27 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
28 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundUtil;
29 import org.opendaylight.ovsdb.lib.notation.UUID;
30 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeBase;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalPortAugmentation;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Acls;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalMcastMacs;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalMcastMacsKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacsKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalRouters;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalRoutersKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitchesKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacsKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Switches;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.Tunnels;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelsKey;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
57 import org.opendaylight.yangtools.yang.binding.Identifiable;
58 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
62 //TODO: need to be optimized, get entry by iid not name
63 public class HwvtepOperationalState {
65 private static final Logger LOG = LoggerFactory.getLogger(HwvtepOperationalState.class);
67 private final Map<InstanceIdentifier<Node>, Node> operationalNodes = new HashMap<>();
68 private ReadWriteTransaction transaction;
69 HashMap<InstanceIdentifier<TerminationPoint>, UUID> inflightLocators = new HashMap<>();
70 private final HwvtepDeviceInfo deviceInfo;
71 private final HwvtepConnectionInstance connectionInstance;
72 private final Map<Class<? extends Identifiable>, Map<InstanceIdentifier, UUID>> currentTxUUIDs =
73 new ConcurrentHashMap<>();
74 private final Map<Class<? extends Identifiable>, Map<InstanceIdentifier, Boolean>> currentTxDeletedKeys =
75 new ConcurrentHashMap<>();
77 /* stores the modified and deleted data for each child type of each node id
78 Map<nodeid , Pair < updated, deleted >
79 each updated/ deleted contains Map < child type, List<ChildData>>
80 child type is the child of hwvtep Global augmentation
82 private Map<InstanceIdentifier<Node>,
83 Pair<Map<Class<? extends Identifiable>, List<Identifiable>>,
84 Map<Class<? extends Identifiable>, List<Identifiable>>>> modifiedData = new HashMap<>();
85 private boolean inReconciliation = false;
86 private final DataBroker db;
87 private final Collection<DataTreeModification<Node>> changes;
88 long transactionId = 0;
90 public HwvtepOperationalState(final DataBroker db, final HwvtepConnectionInstance connectionInstance,
91 final Collection<DataTreeModification<Node>> changes) {
92 this.connectionInstance = connectionInstance;
93 this.deviceInfo = connectionInstance.getDeviceInfo();
95 this.changes = changes;
96 this.transaction = db.newReadWriteTransaction();
99 public HwvtepOperationalState(final HwvtepConnectionInstance connectionInstance) {
100 this.connectionInstance = connectionInstance;
101 this.deviceInfo = connectionInstance.getDeviceInfo();
102 this.db = connectionInstance.getDataBroker();
104 transaction = connectionInstance.getDataBroker().newReadWriteTransaction();
105 Optional<Node> readNode = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL,
106 connectionInstance.getInstanceIdentifier());
107 if (readNode.isPresent()) {
108 operationalNodes.put(connectionInstance.getInstanceIdentifier(), readNode.get());
112 public HwvtepOperationalState(final DataBroker db,
113 final HwvtepConnectionInstance connectionInstance,
114 final Collection<DataTreeModification<Node>> changes,
115 final Node globalOperNode,
117 this(db, connectionInstance, changes);
118 operationalNodes.put(connectionInstance.getInstanceIdentifier(), globalOperNode);
119 HwvtepGlobalAugmentation globalAugmentation = globalOperNode.augmentation(HwvtepGlobalAugmentation.class);
120 if (globalAugmentation != null) {
121 if (!HwvtepSouthboundUtil.isEmptyMap(globalAugmentation.getSwitches())) {
122 operationalNodes.put((InstanceIdentifier<Node>)
123 globalAugmentation.getSwitches().values().iterator().next().getSwitchRef().getValue(), psNode);
128 public void readOperationalNodes() {
129 if (inReconciliation) {
132 if (changes == null) {
133 LOG.warn("Could not read operational nodes for {} as changes is",
134 connectionInstance.getNodeId().getValue());
137 Map<InstanceIdentifier<Node>, Node> nodeCreateOrUpdate =
138 TransactUtils.extractCreatedOrUpdatedOrRemoved(changes, Node.class);
139 if (nodeCreateOrUpdate != null) {
140 transaction = db.newReadWriteTransaction();
141 for (Entry<InstanceIdentifier<Node>, Node> entry: nodeCreateOrUpdate.entrySet()) {
142 Optional<Node> readNode = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL,
144 //add related globalNode or physicalSwitchNode to operationalNodes map
145 //for example, when creating physical port, logical switch is needed
146 //but logical switch is in HwvtepGlobalAugmentation rather than PhysicalSwitchAugmentation
147 if (readNode.isPresent()) {
148 operationalNodes.put(entry.getKey(), readNode.get());
149 HwvtepGlobalAugmentation hgAugmentation =
150 readNode.get().augmentation(HwvtepGlobalAugmentation.class);
151 PhysicalSwitchAugmentation psAugmentation =
152 readNode.get().augmentation(PhysicalSwitchAugmentation.class);
153 if (hgAugmentation != null && hgAugmentation.getSwitches() != null) {
154 for (Switches pswitch : hgAugmentation.getSwitches().values()) {
155 @SuppressWarnings("unchecked")
156 InstanceIdentifier<Node> psNodeIid =
157 (InstanceIdentifier<Node>) pswitch.getSwitchRef().getValue();
158 Optional<Node> psNode =
159 new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, psNodeIid);
160 if (psNode.isPresent()) {
161 operationalNodes.put(psNodeIid, psNode.get());
165 if (psAugmentation != null) {
166 @SuppressWarnings("unchecked")
167 InstanceIdentifier<Node> hgNodeIid =
168 (InstanceIdentifier<Node>) psAugmentation.getManagedBy().getValue();
169 Optional<Node> hgNode = new MdsalUtils(db).readOptional(
170 LogicalDatastoreType.OPERATIONAL, hgNodeIid);
171 if (hgNode.isPresent()) {
172 operationalNodes.put(hgNodeIid, hgNode.get());
180 public Optional<Node> getGlobalNode(final InstanceIdentifier<?> iid) {
181 InstanceIdentifier<Node> nodeIid = iid.firstIdentifierOf(Node.class);
182 return Optional.ofNullable(operationalNodes.get(nodeIid));
185 public Optional<HwvtepGlobalAugmentation> getHwvtepGlobalAugmentation(final InstanceIdentifier<?> iid) {
186 Preconditions.checkNotNull(iid);
187 Optional<Node> nodeOptional = getGlobalNode(iid);
188 if (nodeOptional.isPresent()) {
189 return Optional.ofNullable(nodeOptional.get().augmentation(HwvtepGlobalAugmentation.class));
191 return Optional.empty();
194 public Optional<PhysicalSwitchAugmentation> getPhysicalSwitchAugmentation(final InstanceIdentifier<?> iid) {
195 Preconditions.checkNotNull(iid);
196 Optional<Node> nodeOptional = getGlobalNode(iid);
197 if (nodeOptional.isPresent()) {
198 return Optional.ofNullable(nodeOptional.get().augmentation(PhysicalSwitchAugmentation.class));
200 return Optional.empty();
203 public Optional<Map<TerminationPointKey, TerminationPoint>> getTerminationPointList(
204 final InstanceIdentifier<?> iid) {
205 Preconditions.checkNotNull(iid);
206 Optional<Node> nodeOptional = getGlobalNode(iid);
207 if (nodeOptional.isPresent() && nodeOptional.get().getTerminationPoint() != null) {
208 return Optional.ofNullable(nodeOptional.get().getTerminationPoint());
210 return Optional.empty();
213 public Optional<LogicalSwitches> getLogicalSwitches(final InstanceIdentifier<?> iid,
214 final LogicalSwitchesKey logicalSwitchesKey) {
215 Preconditions.checkNotNull(iid);
216 Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(iid);
217 if (nodeOptional.isPresent()) {
218 LogicalSwitches lswitch = nodeOptional.get().nonnullLogicalSwitches().get(logicalSwitchesKey);
219 if (lswitch != null) {
220 return Optional.of(lswitch);
223 return Optional.empty();
226 public Optional<LogicalSwitches> getLogicalSwitches(final InstanceIdentifier<LogicalSwitches> iid) {
227 return new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid);
230 public Optional<Tunnels> getTunnels(final InstanceIdentifier<?> iid, final TunnelsKey tunnelsKey) {
231 Preconditions.checkNotNull(iid);
232 Optional<PhysicalSwitchAugmentation> psOptional = getPhysicalSwitchAugmentation(iid);
233 if (psOptional.isPresent()) {
234 Tunnels tunnel = psOptional.get().nonnullTunnels().get(tunnelsKey);
235 if (tunnel != null) {
236 return Optional.of(tunnel);
239 return Optional.empty();
242 public Optional<Tunnels> getTunnels(final InstanceIdentifier<Tunnels> iid) {
243 Optional<Tunnels> tunnels = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid);
247 public Optional<HwvtepPhysicalPortAugmentation> getPhysicalPortAugmentation(final InstanceIdentifier<?> iid,
248 final HwvtepNodeName hwvtepNodeName) {
249 Preconditions.checkNotNull(iid);
250 Optional<Map<TerminationPointKey, TerminationPoint>> nodeOptional = getTerminationPointList(iid);
251 if (nodeOptional.isPresent()) {
252 for (TerminationPoint tp : nodeOptional.get().values()) {
253 HwvtepPhysicalPortAugmentation hppAugmentation =
254 tp.augmentation(HwvtepPhysicalPortAugmentation.class);
255 if (hppAugmentation != null && hppAugmentation.getHwvtepNodeName().equals(hwvtepNodeName)) {
256 return Optional.ofNullable(hppAugmentation);
260 return Optional.empty();
263 public Optional<HwvtepPhysicalLocatorAugmentation> getPhysicalLocatorAugmentation(final InstanceIdentifier<?> iid,
264 final IpAddress dstIp, final Class<? extends EncapsulationTypeBase> encapType) {
265 Preconditions.checkNotNull(iid);
266 Optional<Map<TerminationPointKey, TerminationPoint>> nodeOptional = getTerminationPointList(iid);
267 if (nodeOptional.isPresent()) {
268 for (TerminationPoint tp : nodeOptional.get().values()) {
269 HwvtepPhysicalLocatorAugmentation hppAugmentation =
270 tp.augmentation(HwvtepPhysicalLocatorAugmentation.class);
271 if (hppAugmentation != null && hppAugmentation.getDstIp().equals(dstIp)
272 && hppAugmentation.getEncapsulationType().equals(encapType)) {
273 return Optional.ofNullable(hppAugmentation);
277 return Optional.empty();
280 public Optional<HwvtepPhysicalLocatorAugmentation>
281 getPhysicalLocatorAugmentation(final InstanceIdentifier<TerminationPoint> iid) {
282 Optional<TerminationPoint> tp =
283 new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid);
284 if (tp.isPresent()) {
285 return Optional.ofNullable(tp.get().augmentation(HwvtepPhysicalLocatorAugmentation.class));
287 return Optional.empty();
290 public Optional<LocalMcastMacs> getLocalMcastMacs(final InstanceIdentifier<?> iid, final LocalMcastMacsKey key) {
291 Preconditions.checkNotNull(iid);
292 Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(iid);
293 if (nodeOptional.isPresent()) {
294 LocalMcastMacs mac = nodeOptional.get().nonnullLocalMcastMacs().get(key);
296 return Optional.of(mac);
299 return Optional.empty();
302 public Optional<RemoteMcastMacs> getRemoteMcastMacs(final InstanceIdentifier<?> iid, final RemoteMcastMacsKey key) {
303 Preconditions.checkNotNull(iid);
304 Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(iid);
305 if (nodeOptional.isPresent()) {
306 RemoteMcastMacs mac = nodeOptional.get().nonnullRemoteMcastMacs().get(key);
308 return Optional.of(mac);
311 return Optional.empty();
314 public Optional<LocalUcastMacs> getLocalUcastMacs(final InstanceIdentifier<?> iid, final LocalUcastMacsKey key) {
315 Preconditions.checkNotNull(iid);
316 Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(iid);
317 if (nodeOptional.isPresent()) {
318 LocalUcastMacs mac = nodeOptional.get().nonnullLocalUcastMacs().get(key);
320 return Optional.of(mac);
323 return Optional.empty();
326 public Optional<RemoteUcastMacs> getRemoteUcastMacs(final InstanceIdentifier<?> iid, final RemoteUcastMacsKey key) {
327 Preconditions.checkNotNull(iid);
328 Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(iid);
329 if (nodeOptional.isPresent()) {
330 RemoteUcastMacs mac = nodeOptional.get().nonnullRemoteUcastMacs().get(key);
332 return Optional.of(mac);
335 return Optional.empty();
338 public Optional<LogicalRouters> getLogicalRouters(final InstanceIdentifier<?> iid,
339 final LogicalRoutersKey logicalRoutersKey) {
340 Preconditions.checkNotNull(iid);
341 Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(iid);
342 if (nodeOptional.isPresent()) {
343 LogicalRouters lrouter = nodeOptional.get().nonnullLogicalRouters().get(logicalRoutersKey);
344 if (lrouter != null) {
345 return Optional.of(lrouter);
348 return Optional.empty();
351 public Optional<Acls> getAcls(final InstanceIdentifier<Acls> iid) {
352 Optional<Acls> acl = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid);
356 public ReadWriteTransaction getReadWriteTransaction() {
360 public void setPhysicalLocatorInFlight(final InstanceIdentifier<TerminationPoint> iid,
362 inflightLocators.put(iid, uuid);
365 public UUID getPhysicalLocatorInFlight(final InstanceIdentifier<TerminationPoint> iid) {
366 return inflightLocators.get(iid);
369 public HwvtepConnectionInstance getConnectionInstance() {
370 return connectionInstance;
373 public HwvtepDeviceInfo getDeviceInfo() {
377 public void updateCurrentTxData(final Class<? extends Identifiable> cls, final InstanceIdentifier key,
379 HwvtepSouthboundUtil.updateData(currentTxUUIDs, cls, key, uuid);
382 public void updateCurrentTxDeleteData(final Class<? extends Identifiable> cls, final InstanceIdentifier key) {
383 HwvtepSouthboundUtil.updateData(currentTxDeletedKeys, cls, key, Boolean.TRUE);
386 public UUID getUUIDFromCurrentTx(final Class<? extends Identifiable> cls, final InstanceIdentifier key) {
387 return HwvtepSouthboundUtil.getData(currentTxUUIDs, cls, key);
390 public boolean isKeyPartOfCurrentTx(final Class<? extends Identifiable> cls, final InstanceIdentifier key) {
391 return HwvtepSouthboundUtil.containsKey(currentTxUUIDs, cls, key);
394 public Set<InstanceIdentifier> getDeletedKeysInCurrentTx(final Class<? extends Identifiable> cls) {
395 if (currentTxDeletedKeys.containsKey(cls)) {
396 return currentTxDeletedKeys.get(cls).keySet();
398 return Collections.emptySet();
401 public List<? extends Identifiable> getUpdatedData(final InstanceIdentifier<Node> key,
402 final Class<? extends Identifiable> cls) {
403 List<Identifiable> result = null;
404 if (modifiedData.get(key) != null && modifiedData.get(key).getLeft() != null) {
405 result = modifiedData.get(key).getLeft().get(cls);
407 if (result == null) {
408 result = Collections.emptyList();
413 public List<? extends Identifiable> getDeletedData(final InstanceIdentifier<Node> key,
414 final Class<? extends Identifiable> cls) {
415 List<Identifiable> result = null;
416 if (modifiedData.get(key) != null && modifiedData.get(key).getRight() != null) {
417 result = modifiedData.get(key).getRight().get(cls);
419 if (result == null) {
420 result = Collections.emptyList();
425 public void setModifiedData(final Map<InstanceIdentifier<Node>,
426 Pair<Map<Class<? extends Identifiable>, List<Identifiable>>,
427 Map<Class<? extends Identifiable>, List<Identifiable>>>> modifiedData) {
428 this.modifiedData = modifiedData;
431 public boolean isInReconciliation() {
432 return inReconciliation;
435 public void setInReconciliation(final boolean inReconciliation) {
436 this.inReconciliation = inReconciliation;
439 public DataBroker getDataBroker() {
444 public void clearIntransitKeys() {
445 currentTxUUIDs.forEach((cls, map) -> {
446 map.forEach((iid, uuid) -> deviceInfo.clearInTransit(cls, iid));
448 currentTxDeletedKeys.forEach((cls, map) -> {
449 map.forEach((iid, val) -> deviceInfo.clearInTransit(cls, iid));
451 currentTxUUIDs.clear();
452 currentTxDeletedKeys.clear();
453 deviceInfo.onOperDataAvailable();
456 public long getTransactionId() {
457 return transactionId;