Switch to sevntu forbidden method check
[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.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 org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
17 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
19 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
20 import org.opendaylight.genius.utils.hwvtep.HwvtepNodeHACache;
21 import org.opendaylight.netvirt.elan.l2gw.ha.HwvtepHAUtil;
22 import org.opendaylight.netvirt.elan.l2gw.ha.listeners.HAJobScheduler;
23 import org.opendaylight.netvirt.elan.l2gw.ha.merge.GlobalAugmentationMerger;
24 import org.opendaylight.netvirt.elan.l2gw.ha.merge.GlobalNodeMerger;
25 import org.opendaylight.netvirt.elan.l2gw.ha.merge.PSAugmentationMerger;
26 import org.opendaylight.netvirt.elan.l2gw.ha.merge.PSNodeMerger;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentationBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalRef;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentationBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Switches;
33 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 public class NodeConnectedHandler {
40
41     private static final Logger LOG = LoggerFactory.getLogger(NodeConnectedHandler.class);
42
43     private final GlobalAugmentationMerger globalAugmentationMerger = GlobalAugmentationMerger.getInstance();
44     private final PSAugmentationMerger psAugmentationMerger = PSAugmentationMerger.getInstance();
45     private final GlobalNodeMerger globalNodeMerger = GlobalNodeMerger.getInstance();
46     private final PSNodeMerger psNodeMerger = PSNodeMerger.getInstance();
47     private final DataBroker db;
48     private final HwvtepNodeHACache hwvtepNodeHACache;
49
50     public NodeConnectedHandler(final DataBroker db, final HwvtepNodeHACache hwvtepNodeHACache) {
51         this.db = db;
52         this.hwvtepNodeHACache = hwvtepNodeHACache;
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      */
71     @SuppressWarnings("checkstyle:ForbidCertainMethod")
72     public void handleNodeConnected(Node childNode,
73                                     InstanceIdentifier<Node> childNodePath,
74                                     InstanceIdentifier<Node> haNodePath,
75                                     Optional<Node> haGlobalCfg,
76                                     Optional<Node> haPSCfg,
77                                     ReadWriteTransaction tx)
78             throws ReadFailedException {
79         HwvtepHAUtil.buildGlobalConfigForHANode(tx, childNode, haNodePath, haGlobalCfg);
80         copyChildOpToHA(childNode, haNodePath, tx);
81         readAndCopyChildPSOpToHAPS(childNode, haNodePath, tx);
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                     try {
94                         hwvtepNodeHACache.updateConnectedNodeStatus(childNodePath);
95                         LOG.info("HA child reconnected handleNodeReConnected {}",
96                                 childNode.getNodeId().getValue());
97                         ReadWriteTransaction tx1 = db.newReadWriteTransaction();
98                         copyHAPSConfigToChildPS(haPSCfg.get(), childNodePath, tx1);
99                         tx1.submit().checkedGet();
100                     } catch (TransactionCommitFailedException e) {
101                         LOG.error("Failed to process ", e);
102                     }
103                 });
104
105             }
106             copyHANodeConfigToChild(haGlobalCfg.get(), childNodePath, tx);
107         }
108         deleteChildPSConfigIfHAPSConfigIsMissing(haGlobalCfg, childNode, tx);
109     }
110
111     private void deleteChildPSConfigIfHAPSConfigIsMissing(Optional<Node> haPSCfg,
112                                                           Node childNode,
113                                                           ReadWriteTransaction tx) throws ReadFailedException {
114         if (haPSCfg.isPresent()) {
115             return;
116         }
117         LOG.info("HA ps node not present cleanup child {}" , childNode);
118         HwvtepGlobalAugmentation augmentation = childNode.augmentation(HwvtepGlobalAugmentation.class);
119         if (augmentation != null) {
120             List<Switches> switches = augmentation.getSwitches();
121             if (switches != null) {
122                 for (Switches ps : switches) {
123                     HwvtepHAUtil.deleteNodeIfPresent(tx, CONFIGURATION, ps.getSwitchRef().getValue());
124                 }
125             }
126         } else {
127             LOG.info("Global augumentation not present for connected ha child node {}" , childNode);
128         }
129     }
130
131     /**
132      * Merge data of child PS node to HA ps node .
133      *
134      * @param childGlobalNode Ha Global Child node
135      * @param haNodePath Ha node path
136      * @param tx  Transaction
137      * @throws ReadFailedException  Exception thrown if read fails
138      */
139     void readAndCopyChildPSOpToHAPS(Node childGlobalNode,
140                                     InstanceIdentifier<Node> haNodePath,
141                                     ReadWriteTransaction tx)
142             throws ReadFailedException {
143
144         if (childGlobalNode == null || childGlobalNode.augmentation(HwvtepGlobalAugmentation.class) == null) {
145             return;
146         }
147         List<Switches> switches = childGlobalNode.augmentation(HwvtepGlobalAugmentation.class).getSwitches();
148         if (switches == null) {
149             return;
150         }
151         for (Switches ps : switches) {
152             Node childPsNode = HwvtepHAUtil.readNode(tx, OPERATIONAL,
153                     (InstanceIdentifier<Node>) ps.getSwitchRef().getValue());
154             if (childPsNode != null) {
155                 InstanceIdentifier<Node> haPsPath = HwvtepHAUtil.convertPsPath(childPsNode, haNodePath);
156                 copyChildPSOpToHAPS(childPsNode, haNodePath, haPsPath, tx);
157             }
158         }
159     }
160
161     /**
162      * Copy HA global node data to Child HA node of config data tree .
163      *
164      * @param srcNode Node which to be transformed
165      * @param childPath Path to which source node will be transformed
166      * @param tx Transaction
167      */
168     private void copyHANodeConfigToChild(Node srcNode,
169                                          InstanceIdentifier<Node> childPath,
170                                          ReadWriteTransaction tx) {
171         if (srcNode == null) {
172             return;
173         }
174         HwvtepGlobalAugmentation src = srcNode.augmentation(HwvtepGlobalAugmentation.class);
175         if (src == null) {
176             return;
177         }
178         NodeBuilder nodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(childPath);
179         HwvtepGlobalAugmentationBuilder dstBuilder = new HwvtepGlobalAugmentationBuilder();
180
181         globalAugmentationMerger.mergeConfigData(dstBuilder, src, childPath);
182         globalNodeMerger.mergeConfigData(nodeBuilder, srcNode, childPath);
183         nodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, dstBuilder.build());
184         Node dstNode = nodeBuilder.build();
185         tx.put(CONFIGURATION, childPath, dstNode, WriteTransaction.CREATE_MISSING_PARENTS);
186     }
187
188     /**
189      * Copy HA child node to HA node of Operational data tree.
190      *
191      * @param childNode HA Child Node
192      * @param haNodePath HA node path
193      * @param tx Transaction
194      * @throws ReadFailedException  Exception thrown if read fails
195      */
196     private void copyChildOpToHA(Node childNode,
197                                  InstanceIdentifier<Node> haNodePath,
198                                  ReadWriteTransaction tx)
199             throws ReadFailedException {
200         if (childNode == null) {
201             return;
202         }
203         HwvtepGlobalAugmentation childData = childNode.augmentation(HwvtepGlobalAugmentation.class);
204         if (childData == null) {
205             return;
206         }
207         NodeBuilder haNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haNodePath);
208         HwvtepGlobalAugmentationBuilder haBuilder = new HwvtepGlobalAugmentationBuilder();
209
210         Optional<Node> existingHANodeOptional = tx.read(OPERATIONAL, haNodePath).checkedGet();
211         Node existingHANode = existingHANodeOptional.isPresent() ? existingHANodeOptional.get() : null;
212         HwvtepGlobalAugmentation existingHAData = HwvtepHAUtil.getGlobalAugmentationOfNode(existingHANode);
213
214         globalAugmentationMerger.mergeOperationalData(haBuilder, existingHAData, childData, haNodePath);
215         globalNodeMerger.mergeOperationalData(haNodeBuilder, existingHANode, childNode, haNodePath);
216
217         haBuilder.setManagers(HwvtepHAUtil.buildManagersForHANode(childNode, existingHANodeOptional));
218         haBuilder.setSwitches(HwvtepHAUtil.buildSwitchesForHANode(childNode, haNodePath, existingHANodeOptional));
219         haBuilder.setDbVersion(childData.getDbVersion());
220         haNodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, haBuilder.build());
221         Node haNode = haNodeBuilder.build();
222         tx.merge(OPERATIONAL, haNodePath, haNode, true);
223     }
224
225     /**
226      * Merge data to Physical switch from HA node path .
227      *
228      * @param psAugmentation  Physical Switch Augmation of Node
229      * @param builder Physical Switch Augmentation Builder
230      * @param haNodePath HA node Path
231      */
232     public void mergeOpManagedByAttributes(PhysicalSwitchAugmentation psAugmentation,
233                                            PhysicalSwitchAugmentationBuilder builder,
234                                            InstanceIdentifier<Node> haNodePath) {
235         builder.setManagedBy(new HwvtepGlobalRef(haNodePath));
236         builder.setHwvtepNodeName(psAugmentation.getHwvtepNodeName());
237         builder.setHwvtepNodeDescription(psAugmentation.getHwvtepNodeDescription());
238         builder.setTunnelIps(psAugmentation.getTunnelIps());
239         builder.setPhysicalSwitchUuid(HwvtepHAUtil.getUUid(psAugmentation.getHwvtepNodeName().getValue()));
240     }
241
242     /**
243      * Copy HA physical switch data to Child Physical switch node of config data tree.
244      *
245      * @param haPsNode HA physical Switch Node
246      * @param childPath HA Child Node path
247      * @param tx Transaction
248      */
249     public void copyHAPSConfigToChildPS(Node haPsNode,
250                                         InstanceIdentifier<Node> childPath,
251                                         ReadWriteTransaction tx) {
252         InstanceIdentifier<Node> childPsPath = HwvtepHAUtil.convertPsPath(haPsNode, childPath);
253
254         NodeBuilder childPsBuilder = HwvtepHAUtil.getNodeBuilderForPath(childPsPath);
255         PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
256         PhysicalSwitchAugmentation src = haPsNode.augmentation(PhysicalSwitchAugmentation.class);
257
258         psAugmentationMerger.mergeConfigData(dstBuilder, src, childPath);
259         psNodeMerger.mergeConfigData(childPsBuilder, haPsNode, childPath);
260
261         childPsBuilder.addAugmentation(PhysicalSwitchAugmentation.class, dstBuilder.build());
262         Node childPSNode = childPsBuilder.build();
263         tx.put(CONFIGURATION, childPsPath, childPSNode, WriteTransaction.CREATE_MISSING_PARENTS);
264     }
265
266     /**
267      * Copy child physical switch node data to HA physical switch data of Operational data tree.
268      *
269      * @param childPsNode HA child PS node
270      * @param haPath  HA node path
271      * @param haPspath Ha Physical Switch Node path
272      * @param tx Transaction
273      * @throws ReadFailedException  Exception thrown if read fails
274      */
275     public void copyChildPSOpToHAPS(Node childPsNode,
276                                     InstanceIdentifier<Node> haPath,
277                                     InstanceIdentifier<Node> haPspath,
278                                     ReadWriteTransaction tx)
279             throws ReadFailedException {
280
281         NodeBuilder haPSNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haPspath);
282         PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
283
284         PhysicalSwitchAugmentation src = childPsNode.augmentation(PhysicalSwitchAugmentation.class);
285
286         Node existingHAPSNode = HwvtepHAUtil.readNode(tx, OPERATIONAL, haPspath);
287         PhysicalSwitchAugmentation existingHAPSAugumentation =
288                 HwvtepHAUtil.getPhysicalSwitchAugmentationOfNode(existingHAPSNode);
289
290         psAugmentationMerger.mergeOperationalData(dstBuilder, existingHAPSAugumentation, src, haPath);
291         psNodeMerger.mergeOperationalData(haPSNodeBuilder, existingHAPSNode, childPsNode, haPath);
292         mergeOpManagedByAttributes(src, dstBuilder, haPath);
293
294         haPSNodeBuilder.addAugmentation(PhysicalSwitchAugmentation.class, dstBuilder.build());
295         Node haPsNode = haPSNodeBuilder.build();
296         tx.merge(OPERATIONAL, haPspath, haPsNode, true);
297     }
298
299 }