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.genius.infra.Datastore.CONFIGURATION;
11 import static org.opendaylight.mdsal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
13 import java.util.List;
14 import java.util.Optional;
15 import java.util.concurrent.ExecutionException;
16 import org.opendaylight.genius.infra.Datastore.Configuration;
17 import org.opendaylight.genius.infra.Datastore.Operational;
18 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
19 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
20 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
21 import org.opendaylight.genius.utils.hwvtep.HwvtepNodeHACache;
22 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
23 import org.opendaylight.mdsal.binding.api.DataBroker;
24 import org.opendaylight.netvirt.elan.l2gw.ha.HwvtepHAUtil;
25 import org.opendaylight.netvirt.elan.l2gw.ha.listeners.HAJobScheduler;
26 import org.opendaylight.netvirt.elan.l2gw.ha.merge.GlobalAugmentationMerger;
27 import org.opendaylight.netvirt.elan.l2gw.ha.merge.GlobalNodeMerger;
28 import org.opendaylight.netvirt.elan.l2gw.ha.merge.PSAugmentationMerger;
29 import org.opendaylight.netvirt.elan.l2gw.ha.merge.PSNodeMerger;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentationBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalRef;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentationBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Switches;
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 List<Switches> switches = augmentation.getSwitches();
121 if (switches != null) {
122 for (Switches ps : switches) {
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 List<Switches> switches = childGlobalNode.augmentation(HwvtepGlobalAugmentation.class).getSwitches();
147 if (switches == null) {
150 for (Switches ps : switches) {
151 Node childPsNode = tx.read((InstanceIdentifier<Node>) ps.getSwitchRef().getValue()).get().orElse(null);
152 if (childPsNode != null) {
153 InstanceIdentifier<Node> haPsPath = HwvtepHAUtil.convertPsPath(childPsNode, haNodePath);
154 copyChildPSOpToHAPS(childPsNode, haNodePath, haPsPath, tx);
160 * Copy HA global node data to Child HA node of config data tree .
162 * @param srcNode Node which to be transformed
163 * @param childPath Path to which source node will be transformed
164 * @param tx Transaction
166 private void copyHANodeConfigToChild(Node srcNode,
167 InstanceIdentifier<Node> childPath,
168 TypedReadWriteTransaction<Configuration> tx) {
169 if (srcNode == null) {
172 HwvtepGlobalAugmentation src = srcNode.augmentation(HwvtepGlobalAugmentation.class);
176 NodeBuilder nodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(childPath);
177 HwvtepGlobalAugmentationBuilder dstBuilder = new HwvtepGlobalAugmentationBuilder();
179 globalAugmentationMerger.mergeConfigData(dstBuilder, src, childPath);
180 globalNodeMerger.mergeConfigData(nodeBuilder, srcNode, childPath);
181 nodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, dstBuilder.build());
182 Node dstNode = nodeBuilder.build();
183 tx.put(childPath, dstNode, CREATE_MISSING_PARENTS);
187 * Copy HA child node to HA node of Operational data tree.
189 * @param childNode HA Child Node
190 * @param haNodePath HA node path
191 * @param tx Transaction
193 private void copyChildOpToHA(Node childNode,
194 InstanceIdentifier<Node> haNodePath,
195 TypedReadWriteTransaction<Operational> tx)
196 throws ExecutionException, InterruptedException {
197 if (childNode == null) {
200 HwvtepGlobalAugmentation childData = childNode.augmentation(HwvtepGlobalAugmentation.class);
201 if (childData == null) {
204 NodeBuilder haNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haNodePath);
205 HwvtepGlobalAugmentationBuilder haBuilder = new HwvtepGlobalAugmentationBuilder();
207 Optional<Node> existingHANodeOptional = tx.read(haNodePath).get();
208 Node existingHANode = existingHANodeOptional.isPresent() ? existingHANodeOptional.get() : null;
209 HwvtepGlobalAugmentation existingHAData = HwvtepHAUtil.getGlobalAugmentationOfNode(existingHANode);
211 globalAugmentationMerger.mergeOperationalData(haBuilder, existingHAData, childData, haNodePath);
212 globalNodeMerger.mergeOperationalData(haNodeBuilder, existingHANode, childNode, haNodePath);
214 haBuilder.setManagers(HwvtepHAUtil.buildManagersForHANode(childNode, existingHANodeOptional));
215 haBuilder.setSwitches(HwvtepHAUtil.buildSwitchesForHANode(childNode, haNodePath, existingHANodeOptional));
216 haBuilder.setDbVersion(childData.getDbVersion());
217 haNodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, haBuilder.build());
218 Node haNode = haNodeBuilder.build();
219 tx.merge(haNodePath, haNode, CREATE_MISSING_PARENTS);
223 * Merge data to Physical switch from HA node path .
225 * @param psAugmentation Physical Switch Augmation of Node
226 * @param builder Physical Switch Augmentation Builder
227 * @param haNodePath HA node Path
229 public void mergeOpManagedByAttributes(PhysicalSwitchAugmentation psAugmentation,
230 PhysicalSwitchAugmentationBuilder builder,
231 InstanceIdentifier<Node> haNodePath) {
232 builder.setManagedBy(new HwvtepGlobalRef(haNodePath));
233 builder.setHwvtepNodeName(psAugmentation.getHwvtepNodeName());
234 builder.setHwvtepNodeDescription(psAugmentation.getHwvtepNodeDescription());
235 builder.setTunnelIps(psAugmentation.getTunnelIps());
236 builder.setPhysicalSwitchUuid(HwvtepHAUtil.getUUid(psAugmentation.getHwvtepNodeName().getValue()));
240 * Copy HA physical switch data to Child Physical switch node of config data tree.
242 * @param haPsNode HA physical Switch Node
243 * @param childPath HA Child Node path
244 * @param tx Transaction
246 public void copyHAPSConfigToChildPS(Node haPsNode,
247 InstanceIdentifier<Node> childPath,
248 TypedReadWriteTransaction<Configuration> tx) {
249 InstanceIdentifier<Node> childPsPath = HwvtepHAUtil.convertPsPath(haPsNode, childPath);
251 NodeBuilder childPsBuilder = HwvtepHAUtil.getNodeBuilderForPath(childPsPath);
252 PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
253 PhysicalSwitchAugmentation src = haPsNode.augmentation(PhysicalSwitchAugmentation.class);
255 psAugmentationMerger.mergeConfigData(dstBuilder, src, childPath);
256 psNodeMerger.mergeConfigData(childPsBuilder, haPsNode, childPath);
258 childPsBuilder.addAugmentation(PhysicalSwitchAugmentation.class, dstBuilder.build());
259 Node childPSNode = childPsBuilder.build();
260 tx.put(childPsPath, childPSNode, CREATE_MISSING_PARENTS);
264 * Copy child physical switch node data to HA physical switch data of Operational data tree.
266 * @param childPsNode HA child PS node
267 * @param haPath HA node path
268 * @param haPspath Ha Physical Switch Node path
269 * @param tx Transaction
271 public void copyChildPSOpToHAPS(Node childPsNode,
272 InstanceIdentifier<Node> haPath,
273 InstanceIdentifier<Node> haPspath,
274 TypedReadWriteTransaction<Operational> tx)
275 throws ExecutionException, InterruptedException {
277 NodeBuilder haPSNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(haPspath);
278 PhysicalSwitchAugmentationBuilder dstBuilder = new PhysicalSwitchAugmentationBuilder();
280 PhysicalSwitchAugmentation src = childPsNode.augmentation(PhysicalSwitchAugmentation.class);
282 Node existingHAPSNode = tx.read(haPspath).get().orElse(null);
283 PhysicalSwitchAugmentation existingHAPSAugumentation =
284 HwvtepHAUtil.getPhysicalSwitchAugmentationOfNode(existingHAPSNode);
286 psAugmentationMerger.mergeOperationalData(dstBuilder, existingHAPSAugumentation, src, haPath);
287 psNodeMerger.mergeOperationalData(haPSNodeBuilder, existingHAPSNode, childPsNode, haPath);
288 mergeOpManagedByAttributes(src, dstBuilder, haPath);
290 haPSNodeBuilder.addAugmentation(PhysicalSwitchAugmentation.class, dstBuilder.build());
291 Node haPsNode = haPSNodeBuilder.build();
292 tx.merge(haPspath, haPsNode, CREATE_MISSING_PARENTS);