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.mdsal.binding.util.Datastore.CONFIGURATION;
13 import java.util.Optional;
14 import java.util.concurrent.ExecutionException;
15 import org.opendaylight.genius.utils.hwvtep.HwvtepNodeHACache;
16 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
17 import org.opendaylight.mdsal.binding.api.DataBroker;
18 import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
19 import org.opendaylight.mdsal.binding.util.Datastore.Operational;
20 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
21 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
22 import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
23 import org.opendaylight.netvirt.elan.l2gw.ha.HwvtepHAUtil;
24 import org.opendaylight.netvirt.elan.l2gw.ha.listeners.HAJobScheduler;
25 import org.opendaylight.netvirt.elan.l2gw.ha.merge.GlobalAugmentationMerger;
26 import org.opendaylight.netvirt.elan.l2gw.ha.merge.GlobalNodeMerger;
27 import org.opendaylight.netvirt.elan.l2gw.ha.merge.PSAugmentationMerger;
28 import org.opendaylight.netvirt.elan.l2gw.ha.merge.PSNodeMerger;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentationBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalRef;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentationBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Switches;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.SwitchesKey;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
42 public class NodeConnectedHandler {
44 private static final Logger LOG = LoggerFactory.getLogger(NodeConnectedHandler.class);
46 private final GlobalAugmentationMerger globalAugmentationMerger = GlobalAugmentationMerger.getInstance();
47 private final PSAugmentationMerger psAugmentationMerger = PSAugmentationMerger.getInstance();
48 private final GlobalNodeMerger globalNodeMerger = GlobalNodeMerger.getInstance();
49 private final PSNodeMerger psNodeMerger = PSNodeMerger.getInstance();
50 private final ManagedNewTransactionRunner txRunner;
51 private final HwvtepNodeHACache hwvtepNodeHACache;
53 public NodeConnectedHandler(final DataBroker db, final HwvtepNodeHACache hwvtepNodeHACache) {
54 this.txRunner = new ManagedNewTransactionRunnerImpl(db);
55 this.hwvtepNodeHACache = hwvtepNodeHACache;
59 * Takes care of merging the data when a node gets connected.
60 * When a ha child node gets connected , we perform the following.
61 * Merge the ha parent config data to child node.
62 * Merge the ha parent physical node config data to child physical node.
63 * Merge the child operational data to parent operational data.
64 * Merge the child physical switch node operational data to parent physical switch operational node .
66 * @param childNode Ha child node
67 * @param childNodePath Ha child Iid
68 * @param haNodePath Ha Iid
69 * @param haGlobalCfg Ha Global Config Node
70 * @param haPSCfg Ha Physical Config Node
71 * @param operTx Transaction
73 public void handleNodeConnected(Node childNode,
74 InstanceIdentifier<Node> childNodePath,
75 InstanceIdentifier<Node> haNodePath,
76 Optional<Node> haGlobalCfg,
77 Optional<Node> haPSCfg,
78 TypedReadWriteTransaction<Configuration> confTx,
79 TypedReadWriteTransaction<Operational> operTx)
80 throws ExecutionException, InterruptedException {
81 HwvtepHAUtil.buildGlobalConfigForHANode(confTx, childNode, haNodePath, haGlobalCfg);
82 copyChildOpToHA(childNode, haNodePath, operTx);
83 readAndCopyChildPSOpToHAPS(childNode, haNodePath, operTx);
84 if (haGlobalCfg.isPresent()) {
85 //copy ha config to newly connected child case of reconnected child
86 if (haPSCfg.isPresent()) {
88 copy task of physical switch node is done in the next transaction
89 The reason being if it is done in the same transaction,
90 hwvtep plugin is not able to proess this update and send vlanbindings to device
91 as it is expecting the logical switch to be already present in operational ds
92 (created in the device)
94 HAJobScheduler.getInstance().submitJob(() -> {
95 LoggingFutures.addErrorLogging(
96 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, jobTx -> {
97 hwvtepNodeHACache.updateConnectedNodeStatus(childNodePath);
98 LOG.info("HA child reconnected handleNodeReConnected {}",
99 childNode.getNodeId().getValue());
100 copyHAPSConfigToChildPS(haPSCfg.get(), childNodePath, jobTx);
101 }), LOG, "Failed to process");
105 copyHANodeConfigToChild(haGlobalCfg.get(), childNodePath, confTx);
107 deleteChildPSConfigIfHAPSConfigIsMissing(haGlobalCfg, childNode, confTx);
110 private static void deleteChildPSConfigIfHAPSConfigIsMissing(Optional<Node> haPSCfg,
112 TypedReadWriteTransaction<Configuration> tx)
113 throws ExecutionException, InterruptedException {
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 Map<SwitchesKey, Switches> switches = augmentation.nonnullSwitches();
121 if (switches != null) {
122 for (Switches ps : switches.values()) {
123 HwvtepHAUtil.deleteNodeIfPresent(tx, 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
138 void readAndCopyChildPSOpToHAPS(Node childGlobalNode,
139 InstanceIdentifier<Node> haNodePath,
140 TypedReadWriteTransaction<Operational> tx)
141 throws ExecutionException, InterruptedException {
143 if (childGlobalNode == null || childGlobalNode.augmentation(HwvtepGlobalAugmentation.class) == null) {
146 Map<SwitchesKey, Switches> keySwitchesMap
147 = childGlobalNode.augmentation(HwvtepGlobalAugmentation.class).nonnullSwitches();
148 if (keySwitchesMap == null) {
151 for (Switches ps : keySwitchesMap.values()) {
152 Node childPsNode = tx.read((InstanceIdentifier<Node>) ps.getSwitchRef().getValue()).get()
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 TypedReadWriteTransaction<Configuration> 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.mergeParentStructurePut(childPath, dstNode);
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
195 private void copyChildOpToHA(Node childNode,
196 InstanceIdentifier<Node> haNodePath,
197 TypedReadWriteTransaction<Operational> tx)
198 throws ExecutionException, InterruptedException {
199 if (childNode == null) {
202 HwvtepGlobalAugmentation childData = childNode.augmentation(HwvtepGlobalAugmentation.class);
203 if (childData == null) {
206 NodeBuilder haNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haNodePath);
207 HwvtepGlobalAugmentationBuilder haBuilder = new HwvtepGlobalAugmentationBuilder();
209 Optional<Node> existingHANodeOptional = tx.read(haNodePath).get();
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.mergeParentStructureMerge(haNodePath, haNode);
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 TypedReadWriteTransaction<Configuration> tx) {
251 InstanceIdentifier<Node> childPsPath = HwvtepHAUtil.convertPsPath(haPsNode, childPath);
253 NodeBuilder childPsBuilder = HwvtepHAUtil.getNodeBuilderForPath(childPsPath);
254 PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
255 PhysicalSwitchAugmentation src = haPsNode.augmentation(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.mergeParentStructurePut(childPsPath, childPSNode);
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
273 public void copyChildPSOpToHAPS(Node childPsNode,
274 InstanceIdentifier<Node> haPath,
275 InstanceIdentifier<Node> haPspath,
276 TypedReadWriteTransaction<Operational> tx)
277 throws ExecutionException, InterruptedException {
279 NodeBuilder haPSNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haPspath);
280 PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
282 PhysicalSwitchAugmentation src = childPsNode.augmentation(PhysicalSwitchAugmentation.class);
284 Node existingHAPSNode = tx.read(haPspath).get().orElse(null);
285 PhysicalSwitchAugmentation existingHAPSAugumentation =
286 HwvtepHAUtil.getPhysicalSwitchAugmentationOfNode(existingHAPSNode);
288 psAugmentationMerger.mergeOperationalData(dstBuilder, existingHAPSAugumentation, src, haPath);
289 psNodeMerger.mergeOperationalData(haPSNodeBuilder, existingHAPSNode, childPsNode, haPath);
290 mergeOpManagedByAttributes(src, dstBuilder, haPath);
292 haPSNodeBuilder.addAugmentation(PhysicalSwitchAugmentation.class, dstBuilder.build());
293 Node haPsNode = haPSNodeBuilder.build();
294 tx.mergeParentStructureMerge(haPspath, haPsNode);