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 @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()) {
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)
92 HAJobScheduler.getInstance().submitJob(() -> {
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);
106 copyHANodeConfigToChild(haGlobalCfg.get(), childNodePath, tx);
108 deleteChildPSConfigIfHAPSConfigIsMissing(haGlobalCfg, childNode, tx);
111 private void deleteChildPSConfigIfHAPSConfigIsMissing(Optional<Node> haPSCfg,
113 ReadWriteTransaction tx) throws ReadFailedException {
114 if (haPSCfg.isPresent()) {
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());
127 LOG.info("Global augumentation not present for connected ha child node {}" , childNode);
132 * Merge data of child PS node to HA ps node .
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
139 void readAndCopyChildPSOpToHAPS(Node childGlobalNode,
140 InstanceIdentifier<Node> haNodePath,
141 ReadWriteTransaction tx)
142 throws ReadFailedException {
144 if (childGlobalNode == null || childGlobalNode.augmentation(HwvtepGlobalAugmentation.class) == null) {
147 List<Switches> switches = childGlobalNode.augmentation(HwvtepGlobalAugmentation.class).getSwitches();
148 if (switches == null) {
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);
162 * Copy HA global node data to Child HA node of config data tree .
164 * @param srcNode Node which to be transformed
165 * @param childPath Path to which source node will be transformed
166 * @param tx Transaction
168 private void copyHANodeConfigToChild(Node srcNode,
169 InstanceIdentifier<Node> childPath,
170 ReadWriteTransaction tx) {
171 if (srcNode == null) {
174 HwvtepGlobalAugmentation src = srcNode.augmentation(HwvtepGlobalAugmentation.class);
178 NodeBuilder nodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(childPath);
179 HwvtepGlobalAugmentationBuilder dstBuilder = new HwvtepGlobalAugmentationBuilder();
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);
189 * Copy HA child node to HA node of Operational data tree.
191 * @param childNode HA Child Node
192 * @param haNodePath HA node path
193 * @param tx Transaction
194 * @throws ReadFailedException Exception thrown if read fails
196 private void copyChildOpToHA(Node childNode,
197 InstanceIdentifier<Node> haNodePath,
198 ReadWriteTransaction tx)
199 throws ReadFailedException {
200 if (childNode == null) {
203 HwvtepGlobalAugmentation childData = childNode.augmentation(HwvtepGlobalAugmentation.class);
204 if (childData == null) {
207 NodeBuilder haNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haNodePath);
208 HwvtepGlobalAugmentationBuilder haBuilder = new HwvtepGlobalAugmentationBuilder();
210 Optional<Node> existingHANodeOptional = tx.read(OPERATIONAL, haNodePath).checkedGet();
211 Node existingHANode = existingHANodeOptional.isPresent() ? existingHANodeOptional.get() : null;
212 HwvtepGlobalAugmentation existingHAData = HwvtepHAUtil.getGlobalAugmentationOfNode(existingHANode);
214 globalAugmentationMerger.mergeOperationalData(haBuilder, existingHAData, childData, haNodePath);
215 globalNodeMerger.mergeOperationalData(haNodeBuilder, existingHANode, childNode, haNodePath);
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);
226 * Merge data to Physical switch from HA node path .
228 * @param psAugmentation Physical Switch Augmation of Node
229 * @param builder Physical Switch Augmentation Builder
230 * @param haNodePath HA node Path
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()));
243 * Copy HA physical switch data to Child Physical switch node of config data tree.
245 * @param haPsNode HA physical Switch Node
246 * @param childPath HA Child Node path
247 * @param tx Transaction
249 public void copyHAPSConfigToChildPS(Node haPsNode,
250 InstanceIdentifier<Node> childPath,
251 ReadWriteTransaction tx) {
252 InstanceIdentifier<Node> childPsPath = HwvtepHAUtil.convertPsPath(haPsNode, childPath);
254 NodeBuilder childPsBuilder = HwvtepHAUtil.getNodeBuilderForPath(childPsPath);
255 PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
256 PhysicalSwitchAugmentation src = haPsNode.augmentation(PhysicalSwitchAugmentation.class);
258 psAugmentationMerger.mergeConfigData(dstBuilder, src, childPath);
259 psNodeMerger.mergeConfigData(childPsBuilder, haPsNode, childPath);
261 childPsBuilder.addAugmentation(PhysicalSwitchAugmentation.class, dstBuilder.build());
262 Node childPSNode = childPsBuilder.build();
263 tx.put(CONFIGURATION, childPsPath, childPSNode, WriteTransaction.CREATE_MISSING_PARENTS);
267 * Copy child physical switch node data to HA physical switch data of Operational data tree.
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
275 public void copyChildPSOpToHAPS(Node childPsNode,
276 InstanceIdentifier<Node> haPath,
277 InstanceIdentifier<Node> haPspath,
278 ReadWriteTransaction tx)
279 throws ReadFailedException {
281 NodeBuilder haPSNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haPspath);
282 PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
284 PhysicalSwitchAugmentation src = childPsNode.augmentation(PhysicalSwitchAugmentation.class);
286 Node existingHAPSNode = HwvtepHAUtil.readNode(tx, OPERATIONAL, haPspath);
287 PhysicalSwitchAugmentation existingHAPSAugumentation =
288 HwvtepHAUtil.getPhysicalSwitchAugmentationOfNode(existingHAPSNode);
290 psAugmentationMerger.mergeOperationalData(dstBuilder, existingHAPSAugumentation, src, haPath);
291 psNodeMerger.mergeOperationalData(haPSNodeBuilder, existingHAPSNode, childPsNode, haPath);
292 mergeOpManagedByAttributes(src, dstBuilder, haPath);
294 haPSNodeBuilder.addAugmentation(PhysicalSwitchAugmentation.class, dstBuilder.build());
295 Node haPsNode = haPSNodeBuilder.build();
296 tx.merge(OPERATIONAL, haPspath, haPsNode, true);