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