Bulk merge of l2gw changes
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / l2gw / ha / handlers / NodeCopier.java
1 /*
2  * Copyright (c) 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.elan.l2gw.ha.handlers;
9
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;
38
39 @Singleton
40 public class NodeCopier<D extends Datastore> implements INodeCopier<D> {
41
42     private static final Logger LOG = LoggerFactory.getLogger(NodeCopier.class);
43
44     GlobalAugmentationMerger globalAugmentationMerger = GlobalAugmentationMerger.getInstance();
45     PSAugmentationMerger psAugmentationMerger = PSAugmentationMerger.getInstance();
46     GlobalNodeMerger globalNodeMerger = GlobalNodeMerger.getInstance();
47     PSNodeMerger psNodeMerger = PSNodeMerger.getInstance();
48
49     @Override
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) {
55
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());
62                 return;
63             }
64             else {
65                 LOG.error("Operational child node information is not present");
66                 return;
67             }
68         }
69         NodeBuilder haNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(dstPath);
70         HwvtepGlobalAugmentationBuilder haBuilder = new HwvtepGlobalAugmentationBuilder();
71         Optional<Node> existingDstGlobalNodeOptional = Optional.empty();
72         try {
73             existingDstGlobalNodeOptional = tx.read(dstPath).get();
74         } catch (ExecutionException | InterruptedException e) {
75             LOG.error("READ Failed for {} during copyGlobalNode", dstPath);
76         }
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);
86
87             haBuilder.setManagers(HwvtepHAUtil.buildManagersForHANode(srcGlobalNodeOptional.get(),
88                     existingDstGlobalNodeOptional));
89
90         } else {
91             globalAugmentationMerger.mergeConfigData(haBuilder, srcGlobalAugmentation, dstPath);
92             globalNodeMerger.mergeConfigData(haNodeBuilder, srcGlobalNodeOptional.get(), dstPath);
93         }
94
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);
100         } else {
101             tx.mergeParentStructurePut(dstPath, haNode);
102         }
103     }
104
105
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>>() {
114                 @Override
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);
122                         } else {
123                             tx1.put(dstPsPath, new NodeBuilder().setNodeId(dstPsPath
124                                 .firstKeyOf(Node.class).getNodeId()).build());
125                         }
126
127                     });
128                 }
129
130                 @Override
131                 public void onFailure(Throwable throwable) {
132                 }
133             }, MoreExecutors.directExecutor());
134             return;
135         }
136         NodeBuilder dstPsNodeBuilder = HwvtepHAUtil.getNodeBuilderForPath(dstPsPath);
137         PhysicalSwitchAugmentationBuilder dstPsAugmentationBuilder = new PhysicalSwitchAugmentationBuilder();
138
139         PhysicalSwitchAugmentation srcPsAugmenatation =
140                 srcPsNodeOptional.get().augmentation(PhysicalSwitchAugmentation.class);
141         Node existingDstPsNode = null;
142         try {
143             existingDstPsNode = HwvtepHAUtil.readNode(tx, dstPsPath);
144         } catch (ExecutionException | InterruptedException e) {
145             LOG.error("NodeCopier Read Failed for Node:{}", dstPsPath);
146         }
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);
157         } else {
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.
164              */
165             String dstNodeName = dstPsNodeBuilder.getNodeId().getValue();
166             psAugmentationMerger.mergeConfigData(dstPsAugmentationBuilder, srcPsAugmenatation, dstPsPath);
167             try {
168                 boolean isEntryExists = tx.exists(dstPsPath).get();
169                 if (isEntryExists) {
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());
174                 } else {
175                     LOG.info("Destination PS Node: {} doesn't still exist in config-topo.",
176                         dstNodeName);
177                     dstPsNodeBuilder.addAugmentation(dstPsAugmentationBuilder.build());
178                     Node dstPsNode = dstPsNodeBuilder.build();
179                     tx.put(dstPsPath, dstPsNode);
180                 }
181             } catch (InterruptedException | ExecutionException e) {
182                 LOG.error("Error While checking Existing on Node {} in config-topo", dstPsPath);
183             }
184             psNodeMerger.mergeConfigData(dstPsNodeBuilder, srcPsNodeOptional.get(), dstPsPath);
185
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());
193                 });
194             }
195         }
196         LOG.debug("Copied {} physical switch node from {} to {}", logicalDatastoreType, srcPsPath, dstPsPath);
197     }
198
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()));
209             }
210         }
211     }
212 }