Migrate HwvtepHACache users to HwvtepNodeHACache
[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     public void handleNodeConnected(Node childNode,
72                                     InstanceIdentifier<Node> childNodePath,
73                                     InstanceIdentifier<Node> haNodePath,
74                                     Optional<Node> haGlobalCfg,
75                                     Optional<Node> haPSCfg,
76                                     ReadWriteTransaction tx)
77             throws ReadFailedException {
78         HwvtepHAUtil.buildGlobalConfigForHANode(tx, childNode, haNodePath, haGlobalCfg);
79         copyChildOpToHA(childNode, haNodePath, tx);
80         readAndCopyChildPSOpToHAPS(childNode, haNodePath, tx);
81         if (haGlobalCfg.isPresent()) {
82             //copy ha config to newly connected child case of reconnected child
83             if (haPSCfg.isPresent()) {
84                 /*
85                  copy task of physical switch node is done in the next transaction
86                  The reason being if it is done in the same transaction,
87                  hwvtep plugin is not able to proess this update and send vlanbindings to device
88                  as it is expecting the logical switch to be already present in operational ds
89                  (created in the device)
90                  */
91                 HAJobScheduler.getInstance().submitJob(() -> {
92                     try {
93                         hwvtepNodeHACache.updateConnectedNodeStatus(childNodePath);
94                         LOG.info("HA child reconnected handleNodeReConnected {}",
95                                 childNode.getNodeId().getValue());
96                         ReadWriteTransaction tx1 = db.newReadWriteTransaction();
97                         copyHAPSConfigToChildPS(haPSCfg.get(), childNodePath, tx1);
98                         tx1.submit().checkedGet();
99                     } catch (TransactionCommitFailedException e) {
100                         LOG.error("Failed to process ", e);
101                     }
102                 });
103
104             }
105             copyHANodeConfigToChild(haGlobalCfg.get(), childNodePath, tx);
106         }
107         deleteChildPSConfigIfHAPSConfigIsMissing(haGlobalCfg, childNode, tx);
108     }
109
110     private void deleteChildPSConfigIfHAPSConfigIsMissing(Optional<Node> haPSCfg,
111                                                           Node childNode,
112                                                           ReadWriteTransaction tx) throws ReadFailedException {
113         if (haPSCfg.isPresent()) {
114             return;
115         }
116         LOG.info("HA ps node not present cleanup child {}" , childNode);
117         HwvtepGlobalAugmentation augmentation = childNode.getAugmentation(HwvtepGlobalAugmentation.class);
118         if (augmentation != null) {
119             List<Switches> switches = augmentation.getSwitches();
120             if (switches != null) {
121                 for (Switches ps : switches) {
122                     HwvtepHAUtil.deleteNodeIfPresent(tx, CONFIGURATION, ps.getSwitchRef().getValue());
123                 }
124             }
125         } else {
126             LOG.info("Global augumentation not present for connected ha child node {}" , childNode);
127         }
128     }
129
130     /**
131      * Merge data of child PS node to HA ps node .
132      *
133      * @param childGlobalNode Ha Global Child node
134      * @param haNodePath Ha node path
135      * @param tx  Transaction
136      * @throws ReadFailedException  Exception thrown if read fails
137      */
138     void readAndCopyChildPSOpToHAPS(Node childGlobalNode,
139                                     InstanceIdentifier<Node> haNodePath,
140                                     ReadWriteTransaction tx)
141             throws ReadFailedException {
142
143         if (childGlobalNode == null || childGlobalNode.getAugmentation(HwvtepGlobalAugmentation.class) == null) {
144             return;
145         }
146         List<Switches> switches = childGlobalNode.getAugmentation(HwvtepGlobalAugmentation.class).getSwitches();
147         if (switches == null) {
148             return;
149         }
150         for (Switches ps : switches) {
151             Node childPsNode = HwvtepHAUtil.readNode(tx, OPERATIONAL,
152                     (InstanceIdentifier<Node>) ps.getSwitchRef().getValue());
153             if (childPsNode != null) {
154                 InstanceIdentifier<Node> haPsPath = HwvtepHAUtil.convertPsPath(childPsNode, haNodePath);
155                 copyChildPSOpToHAPS(childPsNode, haNodePath, haPsPath, tx);
156             }
157         }
158     }
159
160     /**
161      * Copy HA global node data to Child HA node of config data tree .
162      *
163      * @param srcNode Node which to be transformed
164      * @param childPath Path to which source node will be transformed
165      * @param tx Transaction
166      */
167     private void copyHANodeConfigToChild(Node srcNode,
168                                          InstanceIdentifier<Node> childPath,
169                                          ReadWriteTransaction tx) {
170         if (srcNode == null) {
171             return;
172         }
173         HwvtepGlobalAugmentation src = srcNode.getAugmentation(HwvtepGlobalAugmentation.class);
174         if (src == null) {
175             return;
176         }
177         NodeBuilder nodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(childPath);
178         HwvtepGlobalAugmentationBuilder dstBuilder = new HwvtepGlobalAugmentationBuilder();
179
180         globalAugmentationMerger.mergeConfigData(dstBuilder, src, childPath);
181         globalNodeMerger.mergeConfigData(nodeBuilder, srcNode, childPath);
182         nodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, dstBuilder.build());
183         Node dstNode = nodeBuilder.build();
184         tx.put(CONFIGURATION, childPath, dstNode, WriteTransaction.CREATE_MISSING_PARENTS);
185     }
186
187     /**
188      * Copy HA child node to HA node of Operational data tree.
189      *
190      * @param childNode HA Child Node
191      * @param haNodePath HA node path
192      * @param tx Transaction
193      * @throws ReadFailedException  Exception thrown if read fails
194      */
195     private void copyChildOpToHA(Node childNode,
196                                  InstanceIdentifier<Node> haNodePath,
197                                  ReadWriteTransaction tx)
198             throws ReadFailedException {
199         if (childNode == null) {
200             return;
201         }
202         HwvtepGlobalAugmentation childData = childNode.getAugmentation(HwvtepGlobalAugmentation.class);
203         if (childData == null) {
204             return;
205         }
206         NodeBuilder haNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haNodePath);
207         HwvtepGlobalAugmentationBuilder haBuilder = new HwvtepGlobalAugmentationBuilder();
208
209         Optional<Node> existingHANodeOptional = tx.read(OPERATIONAL, haNodePath).checkedGet();
210         Node existingHANode = existingHANodeOptional.isPresent() ? existingHANodeOptional.get() : null;
211         HwvtepGlobalAugmentation existingHAData = HwvtepHAUtil.getGlobalAugmentationOfNode(existingHANode);
212
213         globalAugmentationMerger.mergeOperationalData(haBuilder, existingHAData, childData, haNodePath);
214         globalNodeMerger.mergeOperationalData(haNodeBuilder, existingHANode, childNode, haNodePath);
215
216         haBuilder.setManagers(HwvtepHAUtil.buildManagersForHANode(childNode, existingHANodeOptional));
217         haBuilder.setSwitches(HwvtepHAUtil.buildSwitchesForHANode(childNode, haNodePath, existingHANodeOptional));
218         haBuilder.setDbVersion(childData.getDbVersion());
219         haNodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, haBuilder.build());
220         Node haNode = haNodeBuilder.build();
221         tx.merge(OPERATIONAL, haNodePath, haNode, true);
222     }
223
224     /**
225      * Merge data to Physical switch from HA node path .
226      *
227      * @param psAugmentation  Physical Switch Augmation of Node
228      * @param builder Physical Switch Augmentation Builder
229      * @param haNodePath HA node Path
230      */
231     public void mergeOpManagedByAttributes(PhysicalSwitchAugmentation psAugmentation,
232                                            PhysicalSwitchAugmentationBuilder builder,
233                                            InstanceIdentifier<Node> haNodePath) {
234         builder.setManagedBy(new HwvtepGlobalRef(haNodePath));
235         builder.setHwvtepNodeName(psAugmentation.getHwvtepNodeName());
236         builder.setHwvtepNodeDescription(psAugmentation.getHwvtepNodeDescription());
237         builder.setTunnelIps(psAugmentation.getTunnelIps());
238         builder.setPhysicalSwitchUuid(HwvtepHAUtil.getUUid(psAugmentation.getHwvtepNodeName().getValue()));
239     }
240
241     /**
242      * Copy HA physical switch data to Child Physical switch node of config data tree.
243      *
244      * @param haPsNode HA physical Switch Node
245      * @param childPath HA Child Node path
246      * @param tx Transaction
247      */
248     public void copyHAPSConfigToChildPS(Node haPsNode,
249                                         InstanceIdentifier<Node> childPath,
250                                         ReadWriteTransaction tx) {
251         InstanceIdentifier<Node> childPsPath = HwvtepHAUtil.convertPsPath(haPsNode, childPath);
252
253         NodeBuilder childPsBuilder = HwvtepHAUtil.getNodeBuilderForPath(childPsPath);
254         PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
255         PhysicalSwitchAugmentation src = haPsNode.getAugmentation(PhysicalSwitchAugmentation.class);
256
257         psAugmentationMerger.mergeConfigData(dstBuilder, src, childPath);
258         psNodeMerger.mergeConfigData(childPsBuilder, haPsNode, childPath);
259
260         childPsBuilder.addAugmentation(PhysicalSwitchAugmentation.class, dstBuilder.build());
261         Node childPSNode = childPsBuilder.build();
262         tx.put(CONFIGURATION, childPsPath, childPSNode, WriteTransaction.CREATE_MISSING_PARENTS);
263     }
264
265     /**
266      * Copy child physical switch node data to HA physical switch data of Operational data tree.
267      *
268      * @param childPsNode HA child PS node
269      * @param haPath  HA node path
270      * @param haPspath Ha Physical Switch Node path
271      * @param tx Transaction
272      * @throws ReadFailedException  Exception thrown if read fails
273      */
274     public void copyChildPSOpToHAPS(Node childPsNode,
275                                     InstanceIdentifier<Node> haPath,
276                                     InstanceIdentifier<Node> haPspath,
277                                     ReadWriteTransaction tx)
278             throws ReadFailedException {
279
280         NodeBuilder haPSNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haPspath);
281         PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
282
283         PhysicalSwitchAugmentation src = childPsNode.getAugmentation(PhysicalSwitchAugmentation.class);
284
285         Node existingHAPSNode = HwvtepHAUtil.readNode(tx, OPERATIONAL, haPspath);
286         PhysicalSwitchAugmentation existingHAPSAugumentation =
287                 HwvtepHAUtil.getPhysicalSwitchAugmentationOfNode(existingHAPSNode);
288
289         psAugmentationMerger.mergeOperationalData(dstBuilder, existingHAPSAugumentation, src, haPath);
290         psNodeMerger.mergeOperationalData(haPSNodeBuilder, existingHAPSNode, childPsNode, haPath);
291         mergeOpManagedByAttributes(src, dstBuilder, haPath);
292
293         haPSNodeBuilder.addAugmentation(PhysicalSwitchAugmentation.class, dstBuilder.build());
294         Node haPsNode = haPSNodeBuilder.build();
295         tx.merge(OPERATIONAL, haPspath, haPsNode, true);
296     }
297
298 }