Freeze upstream versions
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / l2gw / ha / handlers / NodeConnectedHandler.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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.netvirt.elan.l2gw.ha.handlers;
9
10 import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
11
12 import java.util.Map;
13 import java.util.Optional;
14 import java.util.concurrent.ExecutionException;
15 import org.opendaylight.genius.utils.hwvtep.HwvtepHACache;
16 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
17 import org.opendaylight.mdsal.binding.api.DataBroker;
18 import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
19 import org.opendaylight.mdsal.binding.util.Datastore.Operational;
20 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
21 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
22 import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
23 import org.opendaylight.netvirt.elan.l2gw.ha.HwvtepHAUtil;
24 import org.opendaylight.netvirt.elan.l2gw.ha.listeners.HAJobScheduler;
25 import org.opendaylight.netvirt.elan.l2gw.ha.merge.GlobalAugmentationMerger;
26 import org.opendaylight.netvirt.elan.l2gw.ha.merge.GlobalNodeMerger;
27 import org.opendaylight.netvirt.elan.l2gw.ha.merge.PSAugmentationMerger;
28 import org.opendaylight.netvirt.elan.l2gw.ha.merge.PSNodeMerger;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentationBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalRef;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentationBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Switches;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.SwitchesKey;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 public class NodeConnectedHandler {
43
44     private static final Logger LOG = LoggerFactory.getLogger(NodeConnectedHandler.class);
45
46     private final GlobalAugmentationMerger globalAugmentationMerger = GlobalAugmentationMerger.getInstance();
47     private final PSAugmentationMerger psAugmentationMerger = PSAugmentationMerger.getInstance();
48     private final GlobalNodeMerger globalNodeMerger = GlobalNodeMerger.getInstance();
49     private final PSNodeMerger psNodeMerger = PSNodeMerger.getInstance();
50     private final ManagedNewTransactionRunner txRunner;
51
52     public NodeConnectedHandler(final DataBroker db) {
53         this.txRunner = new ManagedNewTransactionRunnerImpl(db);
54     }
55
56     /**
57      * Takes care of merging the data when a node gets connected.
58      * When a ha child node gets connected , we perform the following.
59      * Merge the ha parent config data to child node.
60      * Merge the ha parent physical node config data to child physical node.
61      * Merge the child operational data to parent operational data.
62      * Merge the child physical switch node operational data to parent physical switch operational node .
63      *
64      * @param childNode   Ha child node
65      * @param childNodePath Ha child Iid
66      * @param haNodePath  Ha Iid
67      * @param haGlobalCfg Ha Global Config Node
68      * @param haPSCfg Ha Physical Config Node
69      * @param operTx Transaction
70      */
71     public void handleNodeConnected(Node childNode,
72                                     InstanceIdentifier<Node> childNodePath,
73                                     InstanceIdentifier<Node> haNodePath,
74                                     Optional<Node> haGlobalCfg,
75                                     Optional<Node> haPSCfg,
76                                     TypedReadWriteTransaction<Configuration> confTx,
77                                     TypedReadWriteTransaction<Operational> operTx)
78             throws ExecutionException, InterruptedException {
79         HwvtepHAUtil.buildGlobalConfigForHANode(confTx, childNode, haNodePath, haGlobalCfg);
80         copyChildOpToHA(childNode, haNodePath, operTx);
81         readAndCopyChildPSOpToHAPS(childNode, haNodePath, operTx);
82         if (haGlobalCfg.isPresent()) {
83             //copy ha config to newly connected child case of reconnected child
84             if (haPSCfg.isPresent()) {
85                 /*
86                  copy task of physical switch node is done in the next transaction
87                  The reason being if it is done in the same transaction,
88                  hwvtep plugin is not able to proess this update and send vlanbindings to device
89                  as it is expecting the logical switch to be already present in operational ds
90                  (created in the device)
91                  */
92                 HAJobScheduler.getInstance().submitJob(() -> {
93                     LoggingFutures.addErrorLogging(
94                         txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, jobTx -> {
95                             HwvtepHACache.getInstance().updateConnectedNodeStatus(childNodePath);
96                             LOG.info("HA child reconnected handleNodeReConnected {}",
97                                 childNode.getNodeId().getValue());
98                             copyHAPSConfigToChildPS(haPSCfg.get(), childNodePath, jobTx);
99                         }), LOG, "Failed to process");
100                 });
101
102             }
103             copyHANodeConfigToChild(haGlobalCfg.get(), childNodePath, confTx);
104         }
105         deleteChildPSConfigIfHAPSConfigIsMissing(haGlobalCfg, childNode, confTx);
106     }
107
108     private static void deleteChildPSConfigIfHAPSConfigIsMissing(Optional<Node> haPSCfg,
109                                                                  Node childNode,
110                                                                  TypedReadWriteTransaction<Configuration> tx)
111             throws ExecutionException, InterruptedException {
112         if (haPSCfg.isPresent()) {
113             return;
114         }
115         LOG.info("HA ps node not present cleanup child {}" , childNode);
116         HwvtepGlobalAugmentation augmentation = childNode.augmentation(HwvtepGlobalAugmentation.class);
117         if (augmentation != null) {
118             Map<SwitchesKey, Switches> switches = augmentation.nonnullSwitches();
119             if (switches != null) {
120                 for (Switches ps : switches.values()) {
121                     HwvtepHAUtil.deleteNodeIfPresent(tx, ps.getSwitchRef().getValue());
122                 }
123             }
124         } else {
125             LOG.info("Global augumentation not present for connected ha child node {}" , childNode);
126         }
127     }
128
129     /**
130      * Merge data of child PS node to HA ps node .
131      *
132      * @param childGlobalNode Ha Global Child node
133      * @param haNodePath Ha node path
134      * @param tx  Transaction
135      */
136     void readAndCopyChildPSOpToHAPS(Node childGlobalNode,
137                                     InstanceIdentifier<Node> haNodePath,
138                                     TypedReadWriteTransaction<Operational> tx)
139             throws ExecutionException, InterruptedException {
140
141         if (childGlobalNode == null || childGlobalNode.augmentation(HwvtepGlobalAugmentation.class) == null) {
142             return;
143         }
144         Map<SwitchesKey, Switches> keySwitchesMap
145                 = childGlobalNode.augmentation(HwvtepGlobalAugmentation.class).nonnullSwitches();
146         if (keySwitchesMap == null) {
147             return;
148         }
149         for (Switches ps : keySwitchesMap.values()) {
150             Node childPsNode = tx.read((InstanceIdentifier<Node>) ps.getSwitchRef().getValue()).get()
151                     .orElse(null);
152             if (childPsNode != null) {
153                 InstanceIdentifier<Node> haPsPath = HwvtepHAUtil.convertPsPath(childPsNode, haNodePath);
154                 copyChildPSOpToHAPS(childPsNode, haNodePath, haPsPath, tx);
155             }
156         }
157     }
158
159     /**
160      * Copy HA global node data to Child HA node of config data tree .
161      *
162      * @param srcNode Node which to be transformed
163      * @param childPath Path to which source node will be transformed
164      * @param tx Transaction
165      */
166     private void copyHANodeConfigToChild(Node srcNode,
167                                          InstanceIdentifier<Node> childPath,
168                                          TypedReadWriteTransaction<Configuration> tx) {
169         if (srcNode == null) {
170             return;
171         }
172         HwvtepGlobalAugmentation src = srcNode.augmentation(HwvtepGlobalAugmentation.class);
173         if (src == null) {
174             return;
175         }
176         NodeBuilder nodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(childPath);
177         HwvtepGlobalAugmentationBuilder dstBuilder = new HwvtepGlobalAugmentationBuilder();
178
179         globalAugmentationMerger.mergeConfigData(dstBuilder, src, childPath);
180         globalNodeMerger.mergeConfigData(nodeBuilder, srcNode, childPath);
181         nodeBuilder.addAugmentation(dstBuilder.build());
182         Node dstNode = nodeBuilder.build();
183         tx.mergeParentStructurePut(childPath, dstNode);
184     }
185
186     /**
187      * Copy HA child node to HA node of Operational data tree.
188      *
189      * @param childNode HA Child Node
190      * @param haNodePath HA node path
191      * @param tx Transaction
192      */
193     private void copyChildOpToHA(Node childNode,
194                                  InstanceIdentifier<Node> haNodePath,
195                                  TypedReadWriteTransaction<Operational> tx)
196             throws ExecutionException, InterruptedException {
197         if (childNode == null) {
198             return;
199         }
200         HwvtepGlobalAugmentation childData = childNode.augmentation(HwvtepGlobalAugmentation.class);
201         if (childData == null) {
202             return;
203         }
204         NodeBuilder haNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haNodePath);
205         HwvtepGlobalAugmentationBuilder haBuilder = new HwvtepGlobalAugmentationBuilder();
206
207         Optional<Node> existingHANodeOptional = tx.read(haNodePath).get();
208         Node existingHANode = existingHANodeOptional.isPresent() ? existingHANodeOptional.get() : null;
209         HwvtepGlobalAugmentation existingHAData = HwvtepHAUtil.getGlobalAugmentationOfNode(existingHANode);
210
211         globalAugmentationMerger.mergeOperationalData(haBuilder, existingHAData, childData, haNodePath);
212         globalNodeMerger.mergeOperationalData(haNodeBuilder, existingHANode, childNode, haNodePath);
213
214         haBuilder.setManagers(HwvtepHAUtil.buildManagersForHANode(childNode, existingHANodeOptional));
215         haBuilder.setSwitches(HwvtepHAUtil.buildSwitchesForHANode(childNode, haNodePath, existingHANodeOptional));
216         haBuilder.setDbVersion(childData.getDbVersion());
217         haNodeBuilder.addAugmentation(haBuilder.build());
218         Node haNode = haNodeBuilder.build();
219         tx.mergeParentStructureMerge(haNodePath, haNode);
220     }
221
222     /**
223      * Merge data to Physical switch from HA node path .
224      *
225      * @param psAugmentation  Physical Switch Augmation of Node
226      * @param builder Physical Switch Augmentation Builder
227      * @param haNodePath HA node Path
228      */
229     public void mergeOpManagedByAttributes(PhysicalSwitchAugmentation psAugmentation,
230                                            PhysicalSwitchAugmentationBuilder builder,
231                                            InstanceIdentifier<Node> haNodePath) {
232         builder.setManagedBy(new HwvtepGlobalRef(haNodePath));
233         builder.setHwvtepNodeName(psAugmentation.getHwvtepNodeName());
234         builder.setHwvtepNodeDescription(psAugmentation.getHwvtepNodeDescription());
235         builder.setTunnelIps(psAugmentation.getTunnelIps());
236         builder.setPhysicalSwitchUuid(HwvtepHAUtil.getUUid(psAugmentation.getHwvtepNodeName().getValue()));
237     }
238
239     /**
240      * Copy HA physical switch data to Child Physical switch node of config data tree.
241      *
242      * @param haPsNode HA physical Switch Node
243      * @param childPath HA Child Node path
244      * @param tx Transaction
245      */
246     public void copyHAPSConfigToChildPS(Node haPsNode,
247                                         InstanceIdentifier<Node> childPath,
248                                         TypedReadWriteTransaction<Configuration> tx) {
249         InstanceIdentifier<Node> childPsPath = HwvtepHAUtil.convertPsPath(haPsNode, childPath);
250
251         NodeBuilder childPsBuilder = HwvtepHAUtil.getNodeBuilderForPath(childPsPath);
252         PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
253         PhysicalSwitchAugmentation src = haPsNode.augmentation(PhysicalSwitchAugmentation.class);
254
255         psAugmentationMerger.mergeConfigData(dstBuilder, src, childPath);
256         psNodeMerger.mergeConfigData(childPsBuilder, haPsNode, childPath);
257
258         childPsBuilder.addAugmentation(dstBuilder.build());
259         Node childPSNode = childPsBuilder.build();
260         tx.mergeParentStructurePut(childPsPath, childPSNode);
261     }
262
263     /**
264      * Copy child physical switch node data to HA physical switch data of Operational data tree.
265      *
266      * @param childPsNode HA child PS node
267      * @param haPath  HA node path
268      * @param haPspath Ha Physical Switch Node path
269      * @param tx Transaction
270      */
271     public void copyChildPSOpToHAPS(Node childPsNode,
272                                     InstanceIdentifier<Node> haPath,
273                                     InstanceIdentifier<Node> haPspath,
274                                     TypedReadWriteTransaction<Operational> tx)
275             throws ExecutionException, InterruptedException {
276
277         NodeBuilder haPSNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haPspath);
278         PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
279
280         PhysicalSwitchAugmentation src = childPsNode.augmentation(PhysicalSwitchAugmentation.class);
281
282         Node existingHAPSNode = tx.read(haPspath).get().orElse(null);
283         PhysicalSwitchAugmentation existingHAPSAugumentation =
284                 HwvtepHAUtil.getPhysicalSwitchAugmentationOfNode(existingHAPSNode);
285
286         psAugmentationMerger.mergeOperationalData(dstBuilder, existingHAPSAugumentation, src, haPath);
287         psNodeMerger.mergeOperationalData(haPSNodeBuilder, existingHAPSNode, childPsNode, haPath);
288         mergeOpManagedByAttributes(src, dstBuilder, haPath);
289
290         haPSNodeBuilder.addAugmentation(dstBuilder.build());
291         Node haPsNode = haPSNodeBuilder.build();
292         tx.mergeParentStructureMerge(haPspath, haPsNode);
293     }
294
295 }