2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.netvirt.elan.l2gw.ha.handlers;
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;
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;
40 public class NodeConnectedHandler {
42 static Logger LOG = LoggerFactory.getLogger(NodeConnectedHandler.class);
44 GlobalAugmentationMerger globalAugmentationMerger = GlobalAugmentationMerger.getInstance();
45 PSAugmentationMerger psAugmentationMerger = PSAugmentationMerger.getInstance();
46 GlobalNodeMerger globalNodeMerger = GlobalNodeMerger.getInstance();
47 PSNodeMerger psNodeMerger = PSNodeMerger.getInstance();
49 HwvtepHACache hwvtepHACache = HwvtepHACache.getInstance();
51 public NodeConnectedHandler(DataBroker db) {
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 .
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
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()) {
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)
93 HAJobScheduler.getInstance().submitJob(() -> {
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);
108 copyHANodeConfigToChild(haGlobalCfg.get(), childNodePath, tx);
110 deleteChildPSConfigIfHAPSConfigIsMissing(haGlobalCfg, childNode, tx);
113 private void deleteChildPSConfigIfHAPSConfigIsMissing(Optional<Node> haPSCfg,
115 ReadWriteTransaction tx) throws ReadFailedException {
116 if (haPSCfg.isPresent()) {
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());
129 LOG.info("Global augumentation not present for connected ha child node {}" , childNode);
134 * Merge data of child PS node to HA ps node .
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
143 void readAndCopyChildPSOpToHAPS(Node childGlobalNode,
144 InstanceIdentifier<Node> haNodePath,
145 ReadWriteTransaction tx)
146 throws ReadFailedException, ExecutionException, InterruptedException {
148 if (childGlobalNode == null || childGlobalNode.getAugmentation(HwvtepGlobalAugmentation.class) == null) {
151 List<Switches> switches = childGlobalNode.getAugmentation(HwvtepGlobalAugmentation.class).getSwitches();
152 if (switches == null) {
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);
166 * Copy HA global node data to Child HA node of config data tree .
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
175 private void copyHANodeConfigToChild(Node srcNode,
176 InstanceIdentifier<Node> childPath,
177 ReadWriteTransaction tx)
178 throws ReadFailedException, ExecutionException, InterruptedException {
179 if (srcNode == null) {
182 HwvtepGlobalAugmentation src = srcNode.getAugmentation(HwvtepGlobalAugmentation.class);
186 NodeBuilder nodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(childPath);
187 HwvtepGlobalAugmentationBuilder dstBuilder = new HwvtepGlobalAugmentationBuilder();
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);
197 * Copy HA child node to HA node of Operational data tree.
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
206 private void copyChildOpToHA(Node childNode,
207 InstanceIdentifier<Node> haNodePath,
208 ReadWriteTransaction tx)
209 throws ReadFailedException, ExecutionException, InterruptedException {
210 if (childNode == null) {
213 HwvtepGlobalAugmentation childData = childNode.getAugmentation(HwvtepGlobalAugmentation.class);
214 if (childData == null) {
217 NodeBuilder haNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haNodePath);
218 HwvtepGlobalAugmentationBuilder haBuilder = new HwvtepGlobalAugmentationBuilder();
220 Optional<Node> existingHANodeOptional = tx.read(OPERATIONAL, haNodePath).checkedGet();
221 Node existingHANode = existingHANodeOptional.isPresent() ? existingHANodeOptional.get() : null;
222 HwvtepGlobalAugmentation existingHAData = HwvtepHAUtil.getGlobalAugmentationOfNode(existingHANode);
224 globalAugmentationMerger.mergeOperationalData(haBuilder, existingHAData, childData, haNodePath);
225 globalNodeMerger.mergeOperationalData(haNodeBuilder, existingHANode, childNode, haNodePath);
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);
236 * Merge data to Physical switch from HA node path .
238 * @param psAugmentation Physical Switch Augmation of Node
239 * @param builder Physical Switch Augmentation Builder
240 * @param haNodePath HA node Path
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()));
253 * Copy HA physical switch data to Child Physical switch node of config data tree.
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
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);
268 NodeBuilder childPsBuilder = HwvtepHAUtil.getNodeBuilderForPath(childPsPath);
269 PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
270 PhysicalSwitchAugmentation src = haPsNode.getAugmentation(PhysicalSwitchAugmentation.class);
272 psAugmentationMerger.mergeConfigData(dstBuilder, src, childPath);
273 psNodeMerger.mergeConfigData(childPsBuilder, haPsNode, childPath);
275 childPsBuilder.addAugmentation(PhysicalSwitchAugmentation.class, dstBuilder.build());
276 Node childPSNode = childPsBuilder.build();
277 tx.put(CONFIGURATION, childPsPath, childPSNode, WriteTransaction.CREATE_MISSING_PARENTS);
281 * Copy child physical switch node data to HA physical switch data of Operational data tree.
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
291 public void copyChildPSOpToHAPS(Node childPsNode,
292 InstanceIdentifier<Node> haPath,
293 InstanceIdentifier<Node> haPspath,
294 ReadWriteTransaction tx)
295 throws InterruptedException, ExecutionException, ReadFailedException {
297 NodeBuilder haPSNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haPspath);
298 PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
300 PhysicalSwitchAugmentation src = childPsNode.getAugmentation(PhysicalSwitchAugmentation.class);
302 Node existingHAPSNode = HwvtepHAUtil.readNode(tx, OPERATIONAL, haPspath);
303 PhysicalSwitchAugmentation existingHAPSAugumentation =
304 HwvtepHAUtil.getPhysicalSwitchAugmentationOfNode(existingHAPSNode);
306 psAugmentationMerger.mergeOperationalData(dstBuilder, existingHAPSAugumentation, src, haPath);
307 psNodeMerger.mergeOperationalData(haPSNodeBuilder, existingHAPSNode, childPsNode, haPath);
308 mergeOpManagedByAttributes(src, dstBuilder, haPath);
310 haPSNodeBuilder.addAugmentation(PhysicalSwitchAugmentation.class, dstBuilder.build());
311 Node haPsNode = haPSNodeBuilder.build();
312 tx.merge(OPERATIONAL, haPspath, haPsNode, true);