2 * Copyright (c) 2017 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 com.google.common.util.concurrent.FutureCallback;
11 import com.google.common.util.concurrent.Futures;
12 import com.google.common.util.concurrent.MoreExecutors;
13 import java.util.Optional;
14 import java.util.concurrent.ExecutionException;
15 import javax.inject.Singleton;
16 import org.opendaylight.mdsal.binding.util.Datastore;
17 import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
18 import org.opendaylight.mdsal.binding.util.Datastore.Operational;
19 import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
20 import org.opendaylight.netvirt.elan.l2gw.ha.BatchedTransaction;
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.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
33 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
40 public class NodeCopier<D extends Datastore> implements INodeCopier<D> {
42 private static final Logger LOG = LoggerFactory.getLogger(NodeCopier.class);
44 GlobalAugmentationMerger globalAugmentationMerger = GlobalAugmentationMerger.getInstance();
45 PSAugmentationMerger psAugmentationMerger = PSAugmentationMerger.getInstance();
46 GlobalNodeMerger globalNodeMerger = GlobalNodeMerger.getInstance();
47 PSNodeMerger psNodeMerger = PSNodeMerger.getInstance();
50 public <D extends Datastore> void copyGlobalNode(Optional<Node> srcGlobalNodeOptional,
51 InstanceIdentifier<Node> srcPath,
52 InstanceIdentifier<Node> dstPath,
53 Class<D> logicalDatastoreType,
54 TypedReadWriteTransaction<D> tx) {
56 HwvtepGlobalAugmentation srcGlobalAugmentation =
57 srcGlobalNodeOptional.get().augmentation(HwvtepGlobalAugmentation.class);
58 if (srcGlobalAugmentation == null) {
59 if (Configuration.class.equals(logicalDatastoreType)) {
60 tx.put(srcPath, new NodeBuilder().setNodeId(srcPath
61 .firstKeyOf(Node.class).getNodeId()).build());
65 LOG.error("Operational child node information is not present");
69 NodeBuilder haNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(dstPath);
70 HwvtepGlobalAugmentationBuilder haBuilder = new HwvtepGlobalAugmentationBuilder();
71 Optional<Node> existingDstGlobalNodeOptional = Optional.empty();
73 existingDstGlobalNodeOptional = tx.read(dstPath).get();
74 } catch (ExecutionException | InterruptedException e) {
75 LOG.error("READ Failed for {} during copyGlobalNode", dstPath);
77 Node existingDstGlobalNode = existingDstGlobalNodeOptional.isPresent()
78 ? existingDstGlobalNodeOptional.get() : null;
79 HwvtepGlobalAugmentation existingHAGlobalData = HwvtepHAUtil
80 .getGlobalAugmentationOfNode(existingDstGlobalNode);
81 if (Operational.class.equals(logicalDatastoreType)) {
82 globalAugmentationMerger.mergeOperationalData(
83 haBuilder, existingHAGlobalData, srcGlobalAugmentation, dstPath);
84 globalNodeMerger.mergeOperationalData(haNodeBuilder,
85 existingDstGlobalNode, srcGlobalNodeOptional.get(), dstPath);
87 haBuilder.setManagers(HwvtepHAUtil.buildManagersForHANode(srcGlobalNodeOptional.get(),
88 existingDstGlobalNodeOptional));
91 globalAugmentationMerger.mergeConfigData(haBuilder, srcGlobalAugmentation, dstPath);
92 globalNodeMerger.mergeConfigData(haNodeBuilder, srcGlobalNodeOptional.get(), dstPath);
95 haBuilder.setDbVersion(srcGlobalAugmentation.getDbVersion());
96 haNodeBuilder.addAugmentation(haBuilder.build());
97 Node haNode = haNodeBuilder.build();
98 if (Operational.class.equals(logicalDatastoreType)) {
99 tx.mergeParentStructureMerge(dstPath, haNode);
101 tx.mergeParentStructurePut(dstPath, haNode);
106 public <D extends Datastore> void copyPSNode(Optional<Node> srcPsNodeOptional,
107 InstanceIdentifier<Node> srcPsPath,
108 InstanceIdentifier<Node> dstPsPath,
109 InstanceIdentifier<Node> dstGlobalPath,
110 Class<D> logicalDatastoreType,
111 TypedReadWriteTransaction<D> tx) {
112 if (!srcPsNodeOptional.isPresent() && Configuration.class.equals(logicalDatastoreType)) {
113 Futures.addCallback(tx.read(srcPsPath), new FutureCallback<Optional<Node>>() {
115 public void onSuccess(Optional<Node> nodeOptional) {
116 HAJobScheduler.getInstance().submitJob(() -> {
117 TypedReadWriteTransaction<D> tx1 = new BatchedTransaction(
118 logicalDatastoreType);
119 if (nodeOptional.isPresent()) {
120 copyPSNode(nodeOptional,
121 srcPsPath, dstPsPath, dstGlobalPath, logicalDatastoreType, tx1);
123 tx1.put(dstPsPath, new NodeBuilder().setNodeId(dstPsPath
124 .firstKeyOf(Node.class).getNodeId()).build());
131 public void onFailure(Throwable throwable) {
133 }, MoreExecutors.directExecutor());
136 NodeBuilder dstPsNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(dstPsPath);
137 PhysicalSwitchAugmentationBuilder dstPsAugmentationBuilder = new PhysicalSwitchAugmentationBuilder();
139 PhysicalSwitchAugmentation srcPsAugmenatation =
140 srcPsNodeOptional.get().augmentation(PhysicalSwitchAugmentation.class);
141 Node existingDstPsNode = null;
143 existingDstPsNode = HwvtepHAUtil.readNode(tx, dstPsPath);
144 } catch (ExecutionException | InterruptedException e) {
145 LOG.error("NodeCopier Read Failed for Node:{}", dstPsPath);
147 PhysicalSwitchAugmentation existingDstPsAugmentation =
148 HwvtepHAUtil.getPhysicalSwitchAugmentationOfNode(existingDstPsNode);
149 mergeOpManagedByAttributes(srcPsAugmenatation, dstPsAugmentationBuilder, dstGlobalPath);
150 if (Operational.class.equals(logicalDatastoreType)) {
151 psAugmentationMerger.mergeOperationalData(dstPsAugmentationBuilder, existingDstPsAugmentation,
152 srcPsAugmenatation, dstPsPath);
153 psNodeMerger.mergeOperationalData(dstPsNodeBuilder, existingDstPsNode, srcPsNodeOptional.get(), dstPsPath);
154 dstPsNodeBuilder.addAugmentation(dstPsAugmentationBuilder.build());
155 Node dstPsNode = dstPsNodeBuilder.build();
156 tx.mergeParentStructureMerge(dstPsPath, dstPsNode);
158 /* Below Change done to rerduce the side of tx.put() generated here.
159 1. Check if child node already exists in config-topo.
160 2. If not present, then construct Child ps-node with augmentation data only and do tx.put(node).
161 Followed by, then tx.put(termination-points) for each of termination-points present in parent ps-node.
162 3. If present, then construct augmentation data and do tx.put(augmentation) then followed by
163 tx.put(termination-points) for each of termination-points present in parent ps-node.
165 String dstNodeName = dstPsNodeBuilder.getNodeId().getValue();
166 psAugmentationMerger.mergeConfigData(dstPsAugmentationBuilder, srcPsAugmenatation, dstPsPath);
168 boolean isEntryExists = tx.exists(dstPsPath).get();
170 LOG.info("Destination PS Node: {} already exists in config-topo.", dstNodeName);
171 InstanceIdentifier<PhysicalSwitchAugmentation> dstPsAugPath =
172 dstPsPath.augmentation(PhysicalSwitchAugmentation.class);
173 tx.put(dstPsAugPath, dstPsAugmentationBuilder.build());
175 LOG.info("Destination PS Node: {} doesn't still exist in config-topo.",
177 dstPsNodeBuilder.addAugmentation(dstPsAugmentationBuilder.build());
178 Node dstPsNode = dstPsNodeBuilder.build();
179 tx.put(dstPsPath, dstPsNode);
181 } catch (InterruptedException | ExecutionException e) {
182 LOG.error("Error While checking Existing on Node {} in config-topo", dstPsPath);
184 psNodeMerger.mergeConfigData(dstPsNodeBuilder, srcPsNodeOptional.get(), dstPsPath);
186 if (dstPsNodeBuilder.getTerminationPoint() != null) {
187 dstPsNodeBuilder.getTerminationPoint().values().forEach(terminationPoint -> {
188 InstanceIdentifier<TerminationPoint> terminationPointPath =
189 dstPsPath.child(TerminationPoint.class, terminationPoint.key());
190 tx.put(terminationPointPath, terminationPoint);
191 LOG.trace("Destination PS Node: {} updated with termination-point : {}",
192 dstNodeName, terminationPoint.key());
196 LOG.debug("Copied {} physical switch node from {} to {}", logicalDatastoreType, srcPsPath, dstPsPath);
199 public void mergeOpManagedByAttributes(PhysicalSwitchAugmentation psAugmentation,
200 PhysicalSwitchAugmentationBuilder builder,
201 InstanceIdentifier<Node> haNodePath) {
202 builder.setManagedBy(new HwvtepGlobalRef(haNodePath));
203 if (psAugmentation != null) {
204 builder.setHwvtepNodeName(psAugmentation.getHwvtepNodeName());
205 builder.setHwvtepNodeDescription(psAugmentation.getHwvtepNodeDescription());
206 builder.setTunnelIps(psAugmentation.getTunnelIps());
207 if (psAugmentation.getHwvtepNodeName() != null) {
208 builder.setPhysicalSwitchUuid(HwvtepHAUtil.getUUid(psAugmentation.getHwvtepNodeName().getValue()));