Migrate users of Optional.get()
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / transact / HwvtepOperationalState.java
1 /*
2  * Copyright (c) 2015, 2017 China Telecom Beijing Research Institute 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 package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
9
10 import static java.util.Objects.requireNonNull;
11
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Map.Entry;
18 import java.util.Optional;
19 import java.util.Set;
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;
61
62 //TODO: need to be optimized, get entry by iid not name
63 public class HwvtepOperationalState {
64
65     private static final Logger LOG = LoggerFactory.getLogger(HwvtepOperationalState.class);
66
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<>();
76
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
81      */
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;
89
90     public HwvtepOperationalState(final DataBroker db, final HwvtepConnectionInstance connectionInstance,
91                                   final Collection<DataTreeModification<Node>> changes) {
92         this.connectionInstance = connectionInstance;
93         deviceInfo = connectionInstance.getDeviceInfo();
94         this.db = db;
95         this.changes = changes;
96         transaction = db.newReadWriteTransaction();
97     }
98
99     public HwvtepOperationalState(final HwvtepConnectionInstance connectionInstance) {
100         this.connectionInstance = connectionInstance;
101         deviceInfo = connectionInstance.getDeviceInfo();
102         db = connectionInstance.getDataBroker();
103         changes = null;
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());
109         }
110     }
111
112     public HwvtepOperationalState(final DataBroker db,
113                                   final HwvtepConnectionInstance connectionInstance,
114                                   final Collection<DataTreeModification<Node>> changes,
115                                   final Node globalOperNode,
116                                   final Node psNode) {
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);
124             }
125         }
126     }
127
128     public void readOperationalNodes() {
129         if (inReconciliation) {
130             return;
131         }
132         if (changes == null) {
133             LOG.warn("Could not read operational nodes for {} as changes is",
134                     connectionInstance.getNodeId().getValue());
135             return;
136         }
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,
143                         entry.getKey());
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());
161                             }
162                         }
163                     }
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());
172                         }
173                     }
174                 }
175             }
176         }
177     }
178
179     public Optional<Node> getGlobalNode(final InstanceIdentifier<?> iid) {
180         InstanceIdentifier<Node> nodeIid = iid.firstIdentifierOf(Node.class);
181         return Optional.ofNullable(operationalNodes.get(nodeIid));
182     }
183
184     public Optional<HwvtepGlobalAugmentation> getHwvtepGlobalAugmentation(final InstanceIdentifier<?> iid) {
185         return getGlobalNode(requireNonNull(iid))
186             .flatMap(node -> Optional.ofNullable(node.augmentation(HwvtepGlobalAugmentation.class)));
187     }
188
189     public Optional<PhysicalSwitchAugmentation> getPhysicalSwitchAugmentation(final InstanceIdentifier<?> iid) {
190         return getGlobalNode(requireNonNull(iid))
191             .flatMap(node -> Optional.ofNullable(node.augmentation(PhysicalSwitchAugmentation.class)));
192     }
193
194     public Optional<Map<TerminationPointKey, TerminationPoint>> getTerminationPointList(
195             final InstanceIdentifier<?> iid) {
196         return getGlobalNode(requireNonNull(iid))
197             .flatMap(node -> Optional.ofNullable(node.getTerminationPoint()));
198     }
199
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)));
204     }
205
206     public Optional<LogicalSwitches> getLogicalSwitches(final InstanceIdentifier<LogicalSwitches> iid) {
207         return new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid);
208     }
209
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)));
213     }
214
215     public Optional<Tunnels> getTunnels(final InstanceIdentifier<Tunnels> iid) {
216         Optional<Tunnels> tunnels = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid);
217         return tunnels;
218     }
219
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);
230                 }
231             }
232         }
233         return Optional.empty();
234     }
235
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);
247                 }
248             }
249         }
250         return Optional.empty();
251     }
252
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)));
257     }
258
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)));
262     }
263
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)));
267     }
268
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)));
272     }
273
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)));
277     }
278
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)));
283     }
284
285     public Optional<Acls> getAcls(final InstanceIdentifier<Acls> iid) {
286         return new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid);
287     }
288
289     public ReadWriteTransaction getReadWriteTransaction() {
290         return transaction;
291     }
292
293     public void setPhysicalLocatorInFlight(final InstanceIdentifier<TerminationPoint> iid,
294                                            final UUID uuid) {
295         inflightLocators.put(iid, uuid);
296     }
297
298     public UUID getPhysicalLocatorInFlight(final InstanceIdentifier<TerminationPoint> iid) {
299         return inflightLocators.get(iid);
300     }
301
302     public HwvtepConnectionInstance getConnectionInstance() {
303         return connectionInstance;
304     }
305
306     public HwvtepDeviceInfo getDeviceInfo() {
307         return deviceInfo;
308     }
309
310     public void updateCurrentTxData(final Class<? extends Identifiable> cls, final InstanceIdentifier key,
311             final UUID uuid) {
312         HwvtepSouthboundUtil.updateData(currentTxUUIDs, cls, key, uuid);
313     }
314
315     public void updateCurrentTxDeleteData(final Class<? extends Identifiable> cls, final InstanceIdentifier key) {
316         HwvtepSouthboundUtil.updateData(currentTxDeletedKeys, cls, key, Boolean.TRUE);
317     }
318
319     public UUID getUUIDFromCurrentTx(final Class<? extends Identifiable> cls, final InstanceIdentifier key) {
320         return HwvtepSouthboundUtil.getData(currentTxUUIDs, cls, key);
321     }
322
323     public boolean isKeyPartOfCurrentTx(final Class<? extends Identifiable> cls, final InstanceIdentifier key) {
324         return HwvtepSouthboundUtil.containsKey(currentTxUUIDs, cls, key);
325     }
326
327     public Set<InstanceIdentifier> getDeletedKeysInCurrentTx(final Class<? extends Identifiable> cls) {
328         if (currentTxDeletedKeys.containsKey(cls)) {
329             return currentTxDeletedKeys.get(cls).keySet();
330         }
331         return Collections.emptySet();
332     }
333
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);
339         }
340         if (result == null) {
341             result = Collections.emptyList();
342         }
343         return result;
344     }
345
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);
351         }
352         if (result == null) {
353             result = Collections.emptyList();
354         }
355         return result;
356     }
357
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;
362     }
363
364     public boolean isInReconciliation() {
365         return inReconciliation;
366     }
367
368     public void setInReconciliation(final boolean inReconciliation) {
369         this.inReconciliation = inReconciliation;
370     }
371
372     public DataBroker getDataBroker() {
373         return db;
374     }
375
376
377     public void clearIntransitKeys() {
378         currentTxUUIDs.forEach((cls, map) -> {
379             map.forEach((iid, uuid) -> deviceInfo.clearInTransit(cls, iid));
380         });
381         currentTxDeletedKeys.forEach((cls, map) -> {
382             map.forEach((iid, val) -> deviceInfo.clearInTransit(cls, iid));
383         });
384         currentTxUUIDs.clear();
385         currentTxDeletedKeys.clear();
386         deviceInfo.onOperDataAvailable();
387     }
388
389     public long getTransactionId() {
390         return transactionId;
391     }
392 }