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 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;
39 public class NodeConnectedHandler {
41 private static final Logger LOG = LoggerFactory.getLogger(NodeConnectedHandler.class);
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;
50 public NodeConnectedHandler(final DataBroker db, final HwvtepNodeHACache hwvtepNodeHACache) {
52 this.hwvtepNodeHACache = hwvtepNodeHACache;
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
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()) {
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)
91 HAJobScheduler.getInstance().submitJob(() -> {
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);
105 copyHANodeConfigToChild(haGlobalCfg.get(), childNodePath, tx);
107 deleteChildPSConfigIfHAPSConfigIsMissing(haGlobalCfg, childNode, tx);
110 private void deleteChildPSConfigIfHAPSConfigIsMissing(Optional<Node> haPSCfg,
112 ReadWriteTransaction tx) throws ReadFailedException {
113 if (haPSCfg.isPresent()) {
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());
126 LOG.info("Global augumentation not present for connected ha child node {}" , childNode);
131 * Merge data of child PS node to HA ps node .
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
138 void readAndCopyChildPSOpToHAPS(Node childGlobalNode,
139 InstanceIdentifier<Node> haNodePath,
140 ReadWriteTransaction tx)
141 throws ReadFailedException {
143 if (childGlobalNode == null || childGlobalNode.getAugmentation(HwvtepGlobalAugmentation.class) == null) {
146 List<Switches> switches = childGlobalNode.getAugmentation(HwvtepGlobalAugmentation.class).getSwitches();
147 if (switches == null) {
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);
161 * Copy HA global node data to Child HA node of config data tree .
163 * @param srcNode Node which to be transformed
164 * @param childPath Path to which source node will be transformed
165 * @param tx Transaction
167 private void copyHANodeConfigToChild(Node srcNode,
168 InstanceIdentifier<Node> childPath,
169 ReadWriteTransaction tx) {
170 if (srcNode == null) {
173 HwvtepGlobalAugmentation src = srcNode.getAugmentation(HwvtepGlobalAugmentation.class);
177 NodeBuilder nodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(childPath);
178 HwvtepGlobalAugmentationBuilder dstBuilder = new HwvtepGlobalAugmentationBuilder();
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);
188 * Copy HA child node to HA node of Operational data tree.
190 * @param childNode HA Child Node
191 * @param haNodePath HA node path
192 * @param tx Transaction
193 * @throws ReadFailedException Exception thrown if read fails
195 private void copyChildOpToHA(Node childNode,
196 InstanceIdentifier<Node> haNodePath,
197 ReadWriteTransaction tx)
198 throws ReadFailedException {
199 if (childNode == null) {
202 HwvtepGlobalAugmentation childData = childNode.getAugmentation(HwvtepGlobalAugmentation.class);
203 if (childData == null) {
206 NodeBuilder haNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haNodePath);
207 HwvtepGlobalAugmentationBuilder haBuilder = new HwvtepGlobalAugmentationBuilder();
209 Optional<Node> existingHANodeOptional = tx.read(OPERATIONAL, haNodePath).checkedGet();
210 Node existingHANode = existingHANodeOptional.isPresent() ? existingHANodeOptional.get() : null;
211 HwvtepGlobalAugmentation existingHAData = HwvtepHAUtil.getGlobalAugmentationOfNode(existingHANode);
213 globalAugmentationMerger.mergeOperationalData(haBuilder, existingHAData, childData, haNodePath);
214 globalNodeMerger.mergeOperationalData(haNodeBuilder, existingHANode, childNode, haNodePath);
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);
225 * Merge data to Physical switch from HA node path .
227 * @param psAugmentation Physical Switch Augmation of Node
228 * @param builder Physical Switch Augmentation Builder
229 * @param haNodePath HA node Path
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()));
242 * Copy HA physical switch data to Child Physical switch node of config data tree.
244 * @param haPsNode HA physical Switch Node
245 * @param childPath HA Child Node path
246 * @param tx Transaction
248 public void copyHAPSConfigToChildPS(Node haPsNode,
249 InstanceIdentifier<Node> childPath,
250 ReadWriteTransaction tx) {
251 InstanceIdentifier<Node> childPsPath = HwvtepHAUtil.convertPsPath(haPsNode, childPath);
253 NodeBuilder childPsBuilder = HwvtepHAUtil.getNodeBuilderForPath(childPsPath);
254 PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
255 PhysicalSwitchAugmentation src = haPsNode.getAugmentation(PhysicalSwitchAugmentation.class);
257 psAugmentationMerger.mergeConfigData(dstBuilder, src, childPath);
258 psNodeMerger.mergeConfigData(childPsBuilder, haPsNode, childPath);
260 childPsBuilder.addAugmentation(PhysicalSwitchAugmentation.class, dstBuilder.build());
261 Node childPSNode = childPsBuilder.build();
262 tx.put(CONFIGURATION, childPsPath, childPSNode, WriteTransaction.CREATE_MISSING_PARENTS);
266 * Copy child physical switch node data to HA physical switch data of Operational data tree.
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
274 public void copyChildPSOpToHAPS(Node childPsNode,
275 InstanceIdentifier<Node> haPath,
276 InstanceIdentifier<Node> haPspath,
277 ReadWriteTransaction tx)
278 throws ReadFailedException {
280 NodeBuilder haPSNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haPspath);
281 PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
283 PhysicalSwitchAugmentation src = childPsNode.getAugmentation(PhysicalSwitchAugmentation.class);
285 Node existingHAPSNode = HwvtepHAUtil.readNode(tx, OPERATIONAL, haPspath);
286 PhysicalSwitchAugmentation existingHAPSAugumentation =
287 HwvtepHAUtil.getPhysicalSwitchAugmentationOfNode(existingHAPSNode);
289 psAugmentationMerger.mergeOperationalData(dstBuilder, existingHAPSAugumentation, src, haPath);
290 psNodeMerger.mergeOperationalData(haPSNodeBuilder, existingHAPSNode, childPsNode, haPath);
291 mergeOpManagedByAttributes(src, dstBuilder, haPath);
293 haPSNodeBuilder.addAugmentation(PhysicalSwitchAugmentation.class, dstBuilder.build());
294 Node haPsNode = haPSNodeBuilder.build();
295 tx.merge(OPERATIONAL, haPspath, haPsNode, true);