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
8 package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
10 import static java.util.Objects.requireNonNull;
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 deviceInfo = connectionInstance.getDeviceInfo();
95 this.changes = changes;
96 transaction = db.newReadWriteTransaction();
99 public HwvtepOperationalState(final HwvtepConnectionInstance connectionInstance) {
100 this.connectionInstance = connectionInstance;
101 deviceInfo = connectionInstance.getDeviceInfo();
102 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 Optional<Node> nodeOptional = getGlobalNode(requireNonNull(iid));
187 if (nodeOptional.isPresent()) {
188 return Optional.ofNullable(nodeOptional.get().augmentation(HwvtepGlobalAugmentation.class));
190 return Optional.empty();
193 public Optional<PhysicalSwitchAugmentation> getPhysicalSwitchAugmentation(final InstanceIdentifier<?> iid) {
194 Optional<Node> nodeOptional = getGlobalNode(requireNonNull(iid));
195 if (nodeOptional.isPresent()) {
196 return Optional.ofNullable(nodeOptional.get().augmentation(PhysicalSwitchAugmentation.class));
198 return Optional.empty();
201 public Optional<Map<TerminationPointKey, TerminationPoint>> getTerminationPointList(
202 final InstanceIdentifier<?> iid) {
203 Optional<Node> nodeOptional = getGlobalNode(requireNonNull(iid));
204 if (nodeOptional.isPresent() && nodeOptional.get().getTerminationPoint() != null) {
205 return Optional.ofNullable(nodeOptional.get().getTerminationPoint());
207 return Optional.empty();
210 public Optional<LogicalSwitches> getLogicalSwitches(final InstanceIdentifier<?> iid,
211 final LogicalSwitchesKey logicalSwitchesKey) {
212 Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(requireNonNull(iid));
213 if (nodeOptional.isPresent()) {
214 LogicalSwitches lswitch = nodeOptional.get().nonnullLogicalSwitches().get(logicalSwitchesKey);
215 if (lswitch != null) {
216 return Optional.of(lswitch);
219 return Optional.empty();
222 public Optional<LogicalSwitches> getLogicalSwitches(final InstanceIdentifier<LogicalSwitches> iid) {
223 return new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid);
226 public Optional<Tunnels> getTunnels(final InstanceIdentifier<?> iid, final TunnelsKey tunnelsKey) {
227 Optional<PhysicalSwitchAugmentation> psOptional = getPhysicalSwitchAugmentation(requireNonNull(iid));
228 if (psOptional.isPresent()) {
229 Tunnels tunnel = psOptional.get().nonnullTunnels().get(tunnelsKey);
230 if (tunnel != null) {
231 return Optional.of(tunnel);
234 return Optional.empty();
237 public Optional<Tunnels> getTunnels(final InstanceIdentifier<Tunnels> iid) {
238 Optional<Tunnels> tunnels = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid);
242 public Optional<HwvtepPhysicalPortAugmentation> getPhysicalPortAugmentation(final InstanceIdentifier<?> iid,
243 final HwvtepNodeName hwvtepNodeName) {
244 Optional<Map<TerminationPointKey, TerminationPoint>> nodeOptional =
245 getTerminationPointList(requireNonNull(iid));
246 if (nodeOptional.isPresent()) {
247 for (TerminationPoint tp : nodeOptional.get().values()) {
248 HwvtepPhysicalPortAugmentation hppAugmentation =
249 tp.augmentation(HwvtepPhysicalPortAugmentation.class);
250 if (hppAugmentation != null && hppAugmentation.getHwvtepNodeName().equals(hwvtepNodeName)) {
251 return Optional.ofNullable(hppAugmentation);
255 return Optional.empty();
258 public Optional<HwvtepPhysicalLocatorAugmentation> getPhysicalLocatorAugmentation(final InstanceIdentifier<?> iid,
259 final IpAddress dstIp, final EncapsulationTypeBase encapType) {
260 Optional<Map<TerminationPointKey, TerminationPoint>> nodeOptional =
261 getTerminationPointList(requireNonNull(iid));
262 if (nodeOptional.isPresent()) {
263 for (TerminationPoint tp : nodeOptional.get().values()) {
264 HwvtepPhysicalLocatorAugmentation hppAugmentation =
265 tp.augmentation(HwvtepPhysicalLocatorAugmentation.class);
266 if (hppAugmentation != null && hppAugmentation.getDstIp().equals(dstIp)
267 && hppAugmentation.getEncapsulationType().equals(encapType)) {
268 return Optional.ofNullable(hppAugmentation);
272 return Optional.empty();
275 public Optional<HwvtepPhysicalLocatorAugmentation>
276 getPhysicalLocatorAugmentation(final InstanceIdentifier<TerminationPoint> iid) {
277 Optional<TerminationPoint> tp =
278 new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid);
279 if (tp.isPresent()) {
280 return Optional.ofNullable(tp.get().augmentation(HwvtepPhysicalLocatorAugmentation.class));
282 return Optional.empty();
285 public Optional<LocalMcastMacs> getLocalMcastMacs(final InstanceIdentifier<?> iid, final LocalMcastMacsKey key) {
286 Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(requireNonNull(iid));
287 if (nodeOptional.isPresent()) {
288 LocalMcastMacs mac = nodeOptional.get().nonnullLocalMcastMacs().get(key);
290 return Optional.of(mac);
293 return Optional.empty();
296 public Optional<RemoteMcastMacs> getRemoteMcastMacs(final InstanceIdentifier<?> iid, final RemoteMcastMacsKey key) {
297 Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(requireNonNull(iid));
298 if (nodeOptional.isPresent()) {
299 RemoteMcastMacs mac = nodeOptional.get().nonnullRemoteMcastMacs().get(key);
301 return Optional.of(mac);
304 return Optional.empty();
307 public Optional<LocalUcastMacs> getLocalUcastMacs(final InstanceIdentifier<?> iid, final LocalUcastMacsKey key) {
308 Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(requireNonNull(iid));
309 if (nodeOptional.isPresent()) {
310 LocalUcastMacs mac = nodeOptional.get().nonnullLocalUcastMacs().get(key);
312 return Optional.of(mac);
315 return Optional.empty();
318 public Optional<RemoteUcastMacs> getRemoteUcastMacs(final InstanceIdentifier<?> iid, final RemoteUcastMacsKey key) {
319 Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(requireNonNull(iid));
320 if (nodeOptional.isPresent()) {
321 RemoteUcastMacs mac = nodeOptional.get().nonnullRemoteUcastMacs().get(key);
323 return Optional.of(mac);
326 return Optional.empty();
329 public Optional<LogicalRouters> getLogicalRouters(final InstanceIdentifier<?> iid,
330 final LogicalRoutersKey logicalRoutersKey) {
331 Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(requireNonNull(iid));
332 if (nodeOptional.isPresent()) {
333 LogicalRouters lrouter = nodeOptional.get().nonnullLogicalRouters().get(logicalRoutersKey);
334 if (lrouter != null) {
335 return Optional.of(lrouter);
338 return Optional.empty();
341 public Optional<Acls> getAcls(final InstanceIdentifier<Acls> iid) {
342 Optional<Acls> acl = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid);
346 public ReadWriteTransaction getReadWriteTransaction() {
350 public void setPhysicalLocatorInFlight(final InstanceIdentifier<TerminationPoint> iid,
352 inflightLocators.put(iid, uuid);
355 public UUID getPhysicalLocatorInFlight(final InstanceIdentifier<TerminationPoint> iid) {
356 return inflightLocators.get(iid);
359 public HwvtepConnectionInstance getConnectionInstance() {
360 return connectionInstance;
363 public HwvtepDeviceInfo getDeviceInfo() {
367 public void updateCurrentTxData(final Class<? extends Identifiable> cls, final InstanceIdentifier key,
369 HwvtepSouthboundUtil.updateData(currentTxUUIDs, cls, key, uuid);
372 public void updateCurrentTxDeleteData(final Class<? extends Identifiable> cls, final InstanceIdentifier key) {
373 HwvtepSouthboundUtil.updateData(currentTxDeletedKeys, cls, key, Boolean.TRUE);
376 public UUID getUUIDFromCurrentTx(final Class<? extends Identifiable> cls, final InstanceIdentifier key) {
377 return HwvtepSouthboundUtil.getData(currentTxUUIDs, cls, key);
380 public boolean isKeyPartOfCurrentTx(final Class<? extends Identifiable> cls, final InstanceIdentifier key) {
381 return HwvtepSouthboundUtil.containsKey(currentTxUUIDs, cls, key);
384 public Set<InstanceIdentifier> getDeletedKeysInCurrentTx(final Class<? extends Identifiable> cls) {
385 if (currentTxDeletedKeys.containsKey(cls)) {
386 return currentTxDeletedKeys.get(cls).keySet();
388 return Collections.emptySet();
391 public List<? extends Identifiable> getUpdatedData(final InstanceIdentifier<Node> key,
392 final Class<? extends Identifiable> cls) {
393 List<Identifiable> result = null;
394 if (modifiedData.get(key) != null && modifiedData.get(key).getLeft() != null) {
395 result = modifiedData.get(key).getLeft().get(cls);
397 if (result == null) {
398 result = Collections.emptyList();
403 public List<? extends Identifiable> getDeletedData(final InstanceIdentifier<Node> key,
404 final Class<? extends Identifiable> cls) {
405 List<Identifiable> result = null;
406 if (modifiedData.get(key) != null && modifiedData.get(key).getRight() != null) {
407 result = modifiedData.get(key).getRight().get(cls);
409 if (result == null) {
410 result = Collections.emptyList();
415 public void setModifiedData(final Map<InstanceIdentifier<Node>,
416 Pair<Map<Class<? extends Identifiable>, List<Identifiable>>,
417 Map<Class<? extends Identifiable>, List<Identifiable>>>> modifiedData) {
418 this.modifiedData = modifiedData;
421 public boolean isInReconciliation() {
422 return inReconciliation;
425 public void setInReconciliation(final boolean inReconciliation) {
426 this.inReconciliation = inReconciliation;
429 public DataBroker getDataBroker() {
434 public void clearIntransitKeys() {
435 currentTxUUIDs.forEach((cls, map) -> {
436 map.forEach((iid, uuid) -> deviceInfo.clearInTransit(cls, iid));
438 currentTxDeletedKeys.forEach((cls, map) -> {
439 map.forEach((iid, val) -> deviceInfo.clearInTransit(cls, iid));
441 currentTxUUIDs.clear();
442 currentTxDeletedKeys.clear();
443 deviceInfo.onOperDataAvailable();
446 public long getTransactionId() {
447 return transactionId;