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.orElseThrow());
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 Node rdNode = readNode.orElseThrow();
149 operationalNodes.put(entry.getKey(), rdNode);
150 HwvtepGlobalAugmentation hgAugmentation = rdNode.augmentation(HwvtepGlobalAugmentation.class);
151 PhysicalSwitchAugmentation psAugmentation = rdNode.augmentation(PhysicalSwitchAugmentation.class);
152 if (hgAugmentation != null) {
153 for (Switches pswitch : hgAugmentation.nonnullSwitches().values()) {
154 @SuppressWarnings("unchecked")
155 InstanceIdentifier<Node> psNodeIid =
156 (InstanceIdentifier<Node>) pswitch.getSwitchRef().getValue();
157 Optional<Node> psNode =
158 new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, psNodeIid);
159 if (psNode.isPresent()) {
160 operationalNodes.put(psNodeIid, psNode.orElseThrow());
164 if (psAugmentation != null) {
165 @SuppressWarnings("unchecked")
166 InstanceIdentifier<Node> hgNodeIid =
167 (InstanceIdentifier<Node>) psAugmentation.getManagedBy().getValue();
168 Optional<Node> hgNode = new MdsalUtils(db).readOptional(
169 LogicalDatastoreType.OPERATIONAL, hgNodeIid);
170 if (hgNode.isPresent()) {
171 operationalNodes.put(hgNodeIid, hgNode.orElseThrow());
179 public Optional<Node> getGlobalNode(final InstanceIdentifier<?> iid) {
180 InstanceIdentifier<Node> nodeIid = iid.firstIdentifierOf(Node.class);
181 return Optional.ofNullable(operationalNodes.get(nodeIid));
184 public Optional<HwvtepGlobalAugmentation> getHwvtepGlobalAugmentation(final InstanceIdentifier<?> iid) {
185 return getGlobalNode(requireNonNull(iid))
186 .flatMap(node -> Optional.ofNullable(node.augmentation(HwvtepGlobalAugmentation.class)));
189 public Optional<PhysicalSwitchAugmentation> getPhysicalSwitchAugmentation(final InstanceIdentifier<?> iid) {
190 return getGlobalNode(requireNonNull(iid))
191 .flatMap(node -> Optional.ofNullable(node.augmentation(PhysicalSwitchAugmentation.class)));
194 public Optional<Map<TerminationPointKey, TerminationPoint>> getTerminationPointList(
195 final InstanceIdentifier<?> iid) {
196 return getGlobalNode(requireNonNull(iid))
197 .flatMap(node -> Optional.ofNullable(node.getTerminationPoint()));
200 public Optional<LogicalSwitches> getLogicalSwitches(final InstanceIdentifier<?> iid,
201 final LogicalSwitchesKey logicalSwitchesKey) {
202 return getHwvtepGlobalAugmentation(requireNonNull(iid))
203 .flatMap(node -> Optional.ofNullable(node.nonnullLogicalSwitches().get(logicalSwitchesKey)));
206 public Optional<LogicalSwitches> getLogicalSwitches(final InstanceIdentifier<LogicalSwitches> iid) {
207 return new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid);
210 public Optional<Tunnels> getTunnels(final InstanceIdentifier<?> iid, final TunnelsKey tunnelsKey) {
211 return getPhysicalSwitchAugmentation(requireNonNull(iid))
212 .flatMap(ps -> Optional.ofNullable(ps.nonnullTunnels().get(tunnelsKey)));
215 public Optional<Tunnels> getTunnels(final InstanceIdentifier<Tunnels> iid) {
216 Optional<Tunnels> tunnels = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid);
220 public Optional<HwvtepPhysicalPortAugmentation> getPhysicalPortAugmentation(final InstanceIdentifier<?> iid,
221 final HwvtepNodeName hwvtepNodeName) {
222 Optional<Map<TerminationPointKey, TerminationPoint>> nodeOptional =
223 getTerminationPointList(requireNonNull(iid));
224 if (nodeOptional.isPresent()) {
225 for (TerminationPoint tp : nodeOptional.orElseThrow().values()) {
226 HwvtepPhysicalPortAugmentation hppAugmentation =
227 tp.augmentation(HwvtepPhysicalPortAugmentation.class);
228 if (hppAugmentation != null && hppAugmentation.getHwvtepNodeName().equals(hwvtepNodeName)) {
229 return Optional.of(hppAugmentation);
233 return Optional.empty();
236 public Optional<HwvtepPhysicalLocatorAugmentation> getPhysicalLocatorAugmentation(final InstanceIdentifier<?> iid,
237 final IpAddress dstIp, final EncapsulationTypeBase encapType) {
238 Optional<Map<TerminationPointKey, TerminationPoint>> nodeOptional =
239 getTerminationPointList(requireNonNull(iid));
240 if (nodeOptional.isPresent()) {
241 for (TerminationPoint tp : nodeOptional.orElseThrow().values()) {
242 HwvtepPhysicalLocatorAugmentation hppAugmentation =
243 tp.augmentation(HwvtepPhysicalLocatorAugmentation.class);
244 if (hppAugmentation != null && hppAugmentation.getDstIp().equals(dstIp)
245 && hppAugmentation.getEncapsulationType().equals(encapType)) {
246 return Optional.ofNullable(hppAugmentation);
250 return Optional.empty();
253 public Optional<HwvtepPhysicalLocatorAugmentation>
254 getPhysicalLocatorAugmentation(final InstanceIdentifier<TerminationPoint> iid) {
255 Optional<TerminationPoint> optTp = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid);
256 return optTp.flatMap(tp -> Optional.ofNullable(tp.augmentation(HwvtepPhysicalLocatorAugmentation.class)));
259 public Optional<LocalMcastMacs> getLocalMcastMacs(final InstanceIdentifier<?> iid, final LocalMcastMacsKey key) {
260 return getHwvtepGlobalAugmentation(requireNonNull(iid))
261 .flatMap(node -> Optional.ofNullable(node.nonnullLocalMcastMacs().get(key)));
264 public Optional<RemoteMcastMacs> getRemoteMcastMacs(final InstanceIdentifier<?> iid, final RemoteMcastMacsKey key) {
265 return getHwvtepGlobalAugmentation(requireNonNull(iid))
266 .flatMap(node -> Optional.ofNullable(node.nonnullRemoteMcastMacs().get(key)));
269 public Optional<LocalUcastMacs> getLocalUcastMacs(final InstanceIdentifier<?> iid, final LocalUcastMacsKey key) {
270 return getHwvtepGlobalAugmentation(requireNonNull(iid))
271 .flatMap(node -> Optional.ofNullable(node.nonnullLocalUcastMacs().get(key)));
274 public Optional<RemoteUcastMacs> getRemoteUcastMacs(final InstanceIdentifier<?> iid, final RemoteUcastMacsKey key) {
275 return getHwvtepGlobalAugmentation(requireNonNull(iid))
276 .flatMap(node -> Optional.ofNullable(node.nonnullRemoteUcastMacs().get(key)));
279 public Optional<LogicalRouters> getLogicalRouters(final InstanceIdentifier<?> iid,
280 final LogicalRoutersKey logicalRoutersKey) {
281 return getHwvtepGlobalAugmentation(requireNonNull(iid))
282 .flatMap(node -> Optional.ofNullable(node.nonnullLogicalRouters().get(logicalRoutersKey)));
285 public Optional<Acls> getAcls(final InstanceIdentifier<Acls> iid) {
286 return new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid);
289 public ReadWriteTransaction getReadWriteTransaction() {
293 public void setPhysicalLocatorInFlight(final InstanceIdentifier<TerminationPoint> iid,
295 inflightLocators.put(iid, uuid);
298 public UUID getPhysicalLocatorInFlight(final InstanceIdentifier<TerminationPoint> iid) {
299 return inflightLocators.get(iid);
302 public HwvtepConnectionInstance getConnectionInstance() {
303 return connectionInstance;
306 public HwvtepDeviceInfo getDeviceInfo() {
310 public void updateCurrentTxData(final Class<? extends Identifiable> cls, final InstanceIdentifier key,
312 HwvtepSouthboundUtil.updateData(currentTxUUIDs, cls, key, uuid);
315 public void updateCurrentTxDeleteData(final Class<? extends Identifiable> cls, final InstanceIdentifier key) {
316 HwvtepSouthboundUtil.updateData(currentTxDeletedKeys, cls, key, Boolean.TRUE);
319 public UUID getUUIDFromCurrentTx(final Class<? extends Identifiable> cls, final InstanceIdentifier key) {
320 return HwvtepSouthboundUtil.getData(currentTxUUIDs, cls, key);
323 public boolean isKeyPartOfCurrentTx(final Class<? extends Identifiable> cls, final InstanceIdentifier key) {
324 return HwvtepSouthboundUtil.containsKey(currentTxUUIDs, cls, key);
327 public Set<InstanceIdentifier> getDeletedKeysInCurrentTx(final Class<? extends Identifiable> cls) {
328 if (currentTxDeletedKeys.containsKey(cls)) {
329 return currentTxDeletedKeys.get(cls).keySet();
331 return Collections.emptySet();
334 public List<? extends Identifiable> getUpdatedData(final InstanceIdentifier<Node> key,
335 final Class<? extends Identifiable> cls) {
336 List<Identifiable> result = null;
337 if (modifiedData.get(key) != null && modifiedData.get(key).getLeft() != null) {
338 result = modifiedData.get(key).getLeft().get(cls);
340 if (result == null) {
341 result = Collections.emptyList();
346 public List<? extends Identifiable> getDeletedData(final InstanceIdentifier<Node> key,
347 final Class<? extends Identifiable> cls) {
348 List<Identifiable> result = null;
349 if (modifiedData.get(key) != null && modifiedData.get(key).getRight() != null) {
350 result = modifiedData.get(key).getRight().get(cls);
352 if (result == null) {
353 result = Collections.emptyList();
358 public void setModifiedData(final Map<InstanceIdentifier<Node>,
359 Pair<Map<Class<? extends Identifiable>, List<Identifiable>>,
360 Map<Class<? extends Identifiable>, List<Identifiable>>>> modifiedData) {
361 this.modifiedData = modifiedData;
364 public boolean isInReconciliation() {
365 return inReconciliation;
368 public void setInReconciliation(final boolean inReconciliation) {
369 this.inReconciliation = inReconciliation;
372 public DataBroker getDataBroker() {
377 public void clearIntransitKeys() {
378 currentTxUUIDs.forEach((cls, map) -> {
379 map.forEach((iid, uuid) -> deviceInfo.clearInTransit(cls, iid));
381 currentTxDeletedKeys.forEach((cls, map) -> {
382 map.forEach((iid, val) -> deviceInfo.clearInTransit(cls, iid));
384 currentTxUUIDs.clear();
385 currentTxDeletedKeys.clear();
386 deviceInfo.onOperDataAvailable();
389 public long getTransactionId() {
390 return transactionId;