ELAN: skip remote unicast MACs
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / l2gw / ha / HwvtepHAUtil.java
1 /*
2  * Copyright © 2016, 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;
9
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;
12
13 import com.google.common.base.Optional;
14 import java.nio.charset.StandardCharsets;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.List;
21 import java.util.Set;
22 import java.util.concurrent.ExecutionException;
23 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
24 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
27 import org.opendaylight.genius.utils.hwvtep.HwvtepHACache;
28 import org.opendaylight.netvirt.elan.l2gw.ha.commands.SwitchesCmd;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentationBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalRef;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentationBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitchesKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Managers;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.ManagersBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.ManagersKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Switches;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.managers.ManagerOtherConfigs;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.managers.ManagerOtherConfigsBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.managers.ManagerOtherConfigsKey;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
58 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
59 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63 public final class HwvtepHAUtil {
64
65     static Logger LOG = LoggerFactory.getLogger(HwvtepHAUtil.class);
66
67     //TODO reuse HWvtepSouthboundConstants
68     public static final String HA_ENABLED = "ha_enabled";
69     public static final String HWVTEP_ENTITY_TYPE = "hwvtep";
70     public static final String TEP_PREFIX = "vxlan_over_ipv4:";
71     public static final String HA_ID = "ha_id";
72     public static final String HA_CHILDREN = "ha_children";
73     public static final String PHYSICALSWITCH = "/physicalswitch/";
74     public static final TopologyId HWVTEP_TOPOLOGY_ID = new TopologyId(new Uri("hwvtep:1"));
75     public static final String UUID = "uuid";
76     public static final String HWVTEP_URI_PREFIX = "hwvtep";
77     public static final String MANAGER_KEY = "managerKey";
78     public static final String L2GW_JOB_KEY = ":l2gw";
79
80     static HwvtepHACache hwvtepHACache = HwvtepHACache.getInstance();
81
82     private HwvtepHAUtil() { }
83
84     public static HwvtepPhysicalLocatorRef buildLocatorRef(InstanceIdentifier<Node> nodeIid, String tepIp) {
85         InstanceIdentifier<TerminationPoint> tepId = buildTpId(nodeIid, tepIp);
86         return new HwvtepPhysicalLocatorRef(tepId);
87     }
88
89     public static String getNodeIdVal(InstanceIdentifier<?> iid) {
90         return iid.firstKeyOf(Node.class).getNodeId().getValue();
91     }
92
93     public static Uuid getUUid(String key) {
94         return new Uuid(java.util.UUID.nameUUIDFromBytes(key.getBytes(StandardCharsets.UTF_8)).toString());
95     }
96
97     public static InstanceIdentifier<TerminationPoint> buildTpId(InstanceIdentifier<Node> nodeIid,String tepIp) {
98         String tpKeyStr = TEP_PREFIX + tepIp;
99         TerminationPointKey tpKey = new TerminationPointKey(new TpId(tpKeyStr));
100         InstanceIdentifier<TerminationPoint> plIid = nodeIid.child(TerminationPoint.class, tpKey);
101         return plIid;
102     }
103
104     public static String getTepIpVal(HwvtepPhysicalLocatorRef locatorRef) {
105         InstanceIdentifier<TerminationPoint> tpId = (InstanceIdentifier<TerminationPoint>) locatorRef.getValue();
106         return tpId.firstKeyOf(TerminationPoint.class).getTpId().getValue().substring("vxlan_over_ipv4:".length());
107     }
108
109     public static String getLogicalSwitchSwitchName(HwvtepLogicalSwitchRef logicalSwitchRef) {
110         InstanceIdentifier<LogicalSwitches> id = (InstanceIdentifier<LogicalSwitches>) logicalSwitchRef.getValue();
111         return id.firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue();
112     }
113
114     public static String getNodeIdFromLocatorRef(HwvtepPhysicalLocatorRef locatorRef) {
115         InstanceIdentifier<TerminationPoint> tpId = (InstanceIdentifier<TerminationPoint>) locatorRef.getValue();
116         return tpId.firstKeyOf(Node.class).getNodeId().getValue();
117     }
118
119     public static String getNodeIdFromLogicalSwitches(HwvtepLogicalSwitchRef logicalSwitchRef) {
120         InstanceIdentifier<LogicalSwitches> id = (InstanceIdentifier<LogicalSwitches>) logicalSwitchRef.getValue();
121         return id.firstKeyOf(Node.class).getNodeId().getValue();
122     }
123
124     public static InstanceIdentifier<Node> createInstanceIdentifierFromHAId(String haUUidVal) {
125         String nodeString = HWVTEP_URI_PREFIX + "://"
126             + UUID + "/" + java.util.UUID.nameUUIDFromBytes(haUUidVal.getBytes(StandardCharsets.UTF_8)).toString();
127         NodeId nodeId = new NodeId(new Uri(nodeString));
128         NodeKey nodeKey = new NodeKey(nodeId);
129         TopologyKey topoKey = new TopologyKey(HWVTEP_TOPOLOGY_ID);
130         return InstanceIdentifier.builder(NetworkTopology.class)
131                 .child(Topology.class, topoKey)
132                 .child(Node.class, nodeKey)
133                 .build();
134     }
135
136     public static InstanceIdentifier<Node> convertToInstanceIdentifier(String nodeIdString) {
137         NodeId nodeId = new NodeId(new Uri(nodeIdString));
138         NodeKey nodeKey = new NodeKey(nodeId);
139         TopologyKey topoKey = new TopologyKey(HWVTEP_TOPOLOGY_ID);
140         return InstanceIdentifier.builder(NetworkTopology.class)
141                 .child(Topology.class, topoKey)
142                 .child(Node.class, nodeKey)
143                 .build();
144     }
145
146     /**
147      * Build other config data for HA node .
148      *
149      * @param key The key as in HA child device other config
150      * @param val The value as in HA child device other config
151      * @return return other config object
152      */
153     public static ManagerOtherConfigsBuilder getOtherConfigBuilder(String key, String val) {
154         ManagerOtherConfigsBuilder otherConfigsBuilder = new ManagerOtherConfigsBuilder();
155         ManagerOtherConfigsKey otherConfigsKey = new ManagerOtherConfigsKey(key);
156         otherConfigsBuilder.setKey(otherConfigsKey);
157         otherConfigsBuilder.setOtherConfigKey(key);
158         otherConfigsBuilder.setOtherConfigValue(val);
159         return otherConfigsBuilder;
160     }
161
162     public static Node readNode(ReadWriteTransaction tx, LogicalDatastoreType storeType,
163                                 InstanceIdentifier<Node> nodeId)
164             throws ReadFailedException {
165         Optional<Node> optional = tx.read(storeType, nodeId).checkedGet();
166         if (optional.isPresent()) {
167             return optional.get();
168         }
169         return null;
170     }
171
172     public static String convertToGlobalNodeId(String psNodeId) {
173         int idx = psNodeId.indexOf(PHYSICALSWITCH);
174         if (idx > 0) {
175             return psNodeId.substring(0, idx);
176         }
177         return psNodeId;
178     }
179
180     /**
181      * Trnaform logical switch to nodepath passed .
182      *
183      * @param src {@link HwvtepLogicalSwitchRef} Logical Switch Ref which needs to be transformed
184      * @param nodePath {@link InstanceIdentifier} src needs to be transformed to this path
185      * @return ref {@link HwvtepLogicalSwitchRef} the transforrmed result
186      */
187     public static HwvtepLogicalSwitchRef convertLogicalSwitchRef(HwvtepLogicalSwitchRef src,
188                                                                  InstanceIdentifier<Node> nodePath) {
189         InstanceIdentifier<LogicalSwitches> srcId = (InstanceIdentifier<LogicalSwitches>)src.getValue();
190         HwvtepNodeName switchName = srcId.firstKeyOf(LogicalSwitches.class).getHwvtepNodeName();
191         InstanceIdentifier<LogicalSwitches> iid = nodePath.augmentation(HwvtepGlobalAugmentation.class)
192                 .child(LogicalSwitches.class, new LogicalSwitchesKey(switchName));
193         HwvtepLogicalSwitchRef ref = new HwvtepLogicalSwitchRef(iid);
194         return ref;
195     }
196
197     /**
198      * Trnaform locator reference to nodepath passed .
199      *
200      * @param src {@link HwvtepPhysicalLocatorRef} Logical Switch Ref which needs to be transformed
201      * @param nodePath {@link InstanceIdentifier} src needs to be transformed to this path
202      * @return physicalLocatorRef {@link HwvtepPhysicalLocatorRef} the transforrmed result
203      */
204     public static HwvtepPhysicalLocatorRef convertLocatorRef(HwvtepPhysicalLocatorRef src,
205                                                              InstanceIdentifier<Node> nodePath) {
206         InstanceIdentifier<TerminationPoint> srcTepPath = (InstanceIdentifier<TerminationPoint>)src.getValue();
207         TpId tpId = srcTepPath.firstKeyOf(TerminationPoint.class).getTpId();
208         InstanceIdentifier<TerminationPoint> tpPath =
209                 nodePath.child(TerminationPoint.class, new TerminationPointKey(tpId));
210         HwvtepPhysicalLocatorRef physicalLocatorRef = new HwvtepPhysicalLocatorRef(tpPath);
211         return physicalLocatorRef;
212     }
213
214     public static boolean isEmptyList(List list) {
215         return list == null || list.isEmpty();
216     }
217
218     public static boolean isEmpty(Collection collection) {
219         if (collection == null || collection.isEmpty()) {
220             return true;
221         }
222         return false;
223     }
224
225     public static void mergeManagedByNode(Node psNode,
226                                           PhysicalSwitchAugmentationBuilder builder,
227                                           InstanceIdentifier<Node> haNodePath,
228                                           InstanceIdentifier<Node> haPsPath, NodeId haPSNodeId) {
229         PhysicalSwitchAugmentation psAugmentation = psNode.getAugmentation(PhysicalSwitchAugmentation.class);
230         builder.setManagedBy(new HwvtepGlobalRef(haNodePath));
231         builder.setHwvtepNodeName(psAugmentation.getHwvtepNodeName());
232         builder.setHwvtepNodeDescription(psAugmentation.getHwvtepNodeDescription());
233         builder.setTunnelIps(psAugmentation.getTunnelIps());
234         builder.setPhysicalSwitchUuid(getUUid(psAugmentation.getHwvtepNodeName().getValue()));
235     }
236
237     public static Node getOriginal(DataObjectModification<Node> mod) {
238         Node node = null;
239         switch (mod.getModificationType()) {
240             case SUBTREE_MODIFIED:
241             case DELETE:
242                 node = mod.getDataBefore();
243                 break;
244             case WRITE:
245                 if (mod.getDataBefore() !=  null) {
246                     node = mod.getDataBefore();
247                 }
248                 break;
249             default:
250                 break;
251         }
252         return node;
253     }
254
255     public static Node getUpdated(DataObjectModification<Node> mod) {
256         Node node = null;
257         switch (mod.getModificationType()) {
258             case SUBTREE_MODIFIED:
259                 node = mod.getDataAfter();
260                 break;
261             case WRITE:
262                 if (mod.getDataAfter() !=  null) {
263                     node = mod.getDataAfter();
264                 }
265                 break;
266             default:
267                 break;
268         }
269         return node;
270     }
271
272     public static Node getCreated(DataObjectModification<Node> mod) {
273         if (mod.getModificationType() == DataObjectModification.ModificationType.WRITE
274                 && mod.getDataBefore() == null) {
275             return mod.getDataAfter();
276         }
277         return null;
278     }
279
280     public static Node getRemoved(DataObjectModification<Node> mod) {
281         if (mod.getModificationType() == DataObjectModification.ModificationType.DELETE) {
282             return mod.getDataBefore();
283         }
284         return null;
285     }
286
287     public static InstanceIdentifier<Node> getGlobalNodePathFromPSNode(Node psNode) {
288         if (psNode == null
289                 || psNode.getAugmentation(PhysicalSwitchAugmentation.class) == null
290                 || psNode.getAugmentation(PhysicalSwitchAugmentation.class).getManagedBy() == null) {
291             return null;
292         }
293         return (InstanceIdentifier<Node>)psNode
294                 .getAugmentation(PhysicalSwitchAugmentation.class).getManagedBy().getValue();
295     }
296
297     public static InstanceIdentifier<Node> convertPsPath(Node psNode, InstanceIdentifier<Node> nodePath) {
298         String psNodeId = psNode.getNodeId().getValue();
299         String psName = psNodeId.substring(psNodeId.indexOf(PHYSICALSWITCH) + PHYSICALSWITCH.length());
300         String haPsNodeIdVal = nodePath.firstKeyOf(Node.class).getNodeId().getValue() + PHYSICALSWITCH + psName;
301         InstanceIdentifier<Node> haPsPath = convertToInstanceIdentifier(haPsNodeIdVal);
302         return haPsPath;
303     }
304
305     public static NodeBuilder getNodeBuilderForPath(InstanceIdentifier<Node> haPath) {
306         NodeBuilder nodeBuilder = new NodeBuilder();
307         nodeBuilder.setNodeId(haPath.firstKeyOf(Node.class).getNodeId());
308         return nodeBuilder;
309     }
310
311     public static String getHAIdFromManagerOtherConfig(Node node) {
312         if (node.getAugmentation(HwvtepGlobalAugmentation.class) == null) {
313             return null;
314         }
315         HwvtepGlobalAugmentation globalAugmentation = node.getAugmentation(HwvtepGlobalAugmentation.class);
316         if (globalAugmentation != null) {
317             List<Managers> managers = globalAugmentation.getManagers();
318             if (managers != null && managers.size() > 0 && managers.get(0).getManagerOtherConfigs() != null) {
319                 for (ManagerOtherConfigs configs : managers.get(0).getManagerOtherConfigs()) {
320                     if (configs.getOtherConfigKey().equals(HA_ID)) {
321                         return configs.getOtherConfigValue();
322                     }
323                 }
324             }
325         }
326         return null;
327     }
328
329     /**
330      * Returns ha child node path from ha node of config data tree.
331      *
332      * @param haGlobalConfigNodeOptional HA global node
333      * @return ha Child ids
334      */
335     public static  List<NodeId> getChildNodeIdsFromManagerOtherConfig(Optional<Node> haGlobalConfigNodeOptional) {
336         List<NodeId> childNodeIds = new ArrayList<>();
337         if (!haGlobalConfigNodeOptional.isPresent()) {
338             return childNodeIds;
339         }
340         HwvtepGlobalAugmentation augmentation =
341                 haGlobalConfigNodeOptional.get().getAugmentation(HwvtepGlobalAugmentation.class);
342         if (augmentation != null && augmentation.getManagers() != null
343                 && augmentation.getManagers().size() > 0) {
344             Managers managers = augmentation.getManagers().get(0);
345             if (null == managers.getManagerOtherConfigs()) {
346                 return childNodeIds;
347             }
348             for (ManagerOtherConfigs otherConfigs : managers.getManagerOtherConfigs()) {
349                 if (otherConfigs.getOtherConfigKey().equals(HA_CHILDREN)) {
350                     String nodeIdsVal = otherConfigs.getOtherConfigValue();
351                     if (nodeIdsVal != null) {
352                         String[] parts = nodeIdsVal.split(",");
353                         for (String part : parts) {
354                             childNodeIds.add(new NodeId(part));
355                         }
356                     }
357
358                 }
359             }
360         }
361         return childNodeIds;
362     }
363
364     /**
365      * Return PS children for passed PS node .
366      *
367      * @param psNodId PS node path
368      * @return child Switches
369      */
370     public static Set<InstanceIdentifier<Node>> getPSChildrenIdsForHAPSNode(String psNodId) {
371         if (!psNodId.contains(PHYSICALSWITCH)) {
372             return Collections.emptySet();
373         }
374         String nodeId = convertToGlobalNodeId(psNodId);
375         InstanceIdentifier<Node> iid = convertToInstanceIdentifier(nodeId);
376         if (hwvtepHACache.isHAParentNode(iid)) {
377             Set<InstanceIdentifier<Node>> childSwitchIds = new HashSet<>();
378             Set<InstanceIdentifier<Node>> childGlobalIds = hwvtepHACache.getChildrenForHANode(iid);
379             final String append = psNodId.substring(psNodId.indexOf(PHYSICALSWITCH));
380             for (InstanceIdentifier<Node> childId : childGlobalIds) {
381                 String childIdVal = childId.firstKeyOf(Node.class).getNodeId().getValue();
382                 childSwitchIds.add(convertToInstanceIdentifier(childIdVal + append));
383             }
384             return childSwitchIds;
385         }
386         return Collections.EMPTY_SET;
387     }
388
389     public static HwvtepGlobalAugmentation getGlobalAugmentationOfNode(Node node) {
390         HwvtepGlobalAugmentation result = null;
391         if (node != null) {
392             result = node.getAugmentation(HwvtepGlobalAugmentation.class);
393         }
394         if (result == null) {
395             result = new HwvtepGlobalAugmentationBuilder().build();
396         }
397         return result;
398     }
399
400     public static PhysicalSwitchAugmentation getPhysicalSwitchAugmentationOfNode(Node psNode) {
401         PhysicalSwitchAugmentation result = null;
402         if (psNode != null) {
403             result = psNode.getAugmentation(PhysicalSwitchAugmentation.class);
404         }
405         if (result == null) {
406             result = new PhysicalSwitchAugmentationBuilder().build();
407         }
408         return result;
409     }
410
411     /**
412      * Transform child managers (Source) to HA managers using HA node path.
413      *
414      * @param childNode Child Node
415      * @param haGlobalCfg HA global config node
416      * @return Transformed managers
417      */
418     public static List<Managers> buildManagersForHANode(Node childNode, Optional<Node> haGlobalCfg) {
419
420         Set<NodeId> nodeIds = new HashSet<>();
421         nodeIds.add(childNode.getNodeId());
422         List<NodeId> childNodeIds = getChildNodeIdsFromManagerOtherConfig(haGlobalCfg);
423         nodeIds.addAll(childNodeIds);
424
425         ManagersBuilder builder1 = new ManagersBuilder();
426
427         builder1.setKey(new ManagersKey(new Uri(MANAGER_KEY)));
428         List<ManagerOtherConfigs> otherConfigses = new ArrayList<>();
429         StringBuffer stringBuffer = new StringBuffer();
430         for (NodeId nodeId : nodeIds) {
431             stringBuffer.append(nodeId.getValue());
432             stringBuffer.append(",");
433         }
434
435         String children = stringBuffer.substring(0, stringBuffer.toString().length() - 1);
436
437         otherConfigses.add(getOtherConfigBuilder(HA_CHILDREN, children).build());
438         builder1.setManagerOtherConfigs(otherConfigses);
439         List<Managers> managers = new ArrayList<>();
440         managers.add(builder1.build());
441         return managers;
442     }
443
444     /**
445      * Transform child switch (Source) to HA swicthes using HA node path.
446      *
447      * @param childNode  HA child node
448      * @param haNodePath  HA node path
449      * @param haNode Ha node object
450      * @return Transformed switches
451      */
452     public static List<Switches> buildSwitchesForHANode(Node childNode,
453                                                         InstanceIdentifier<Node> haNodePath,
454                                                         Optional<Node> haNode) {
455         List<Switches> psList = new ArrayList<>();
456         boolean switchesAlreadyPresent = false;
457         if (haNode.isPresent()) {
458             Node node = haNode.get();
459             HwvtepGlobalAugmentation augmentation = node.getAugmentation(HwvtepGlobalAugmentation.class);
460             if (augmentation != null) {
461                 if (augmentation.getSwitches() != null) {
462                     if (augmentation.getSwitches().size() > 0) {
463                         switchesAlreadyPresent = true;
464                     }
465                 }
466             }
467         }
468         if (!switchesAlreadyPresent) {
469             HwvtepGlobalAugmentation augmentation = childNode.getAugmentation(HwvtepGlobalAugmentation.class);
470             if (augmentation != null && augmentation.getSwitches() != null) {
471                 List<Switches> src = augmentation.getSwitches();
472                 if (src != null && src.size() > 0) {
473                     psList.add(new SwitchesCmd().transform(haNodePath, src.get(0)));
474                 }
475             }
476         }
477         return psList;
478     }
479
480     /**
481      * Build HA Global node from child nodes in config data tress.
482      *
483      * @param tx Transaction
484      * @param childNode Child Node object
485      * @param haNodePath Ha node path
486      * @param haGlobalCfg HA global node object
487      */
488     public static void buildGlobalConfigForHANode(ReadWriteTransaction tx,
489                                                   Node childNode,
490                                                   InstanceIdentifier<Node> haNodePath,
491                                                   Optional<Node> haGlobalCfg) {
492
493         NodeBuilder nodeBuilder = new NodeBuilder();
494         HwvtepGlobalAugmentationBuilder hwvtepGlobalBuilder = new HwvtepGlobalAugmentationBuilder();
495         hwvtepGlobalBuilder.setSwitches(buildSwitchesForHANode(childNode, haNodePath, haGlobalCfg));
496         hwvtepGlobalBuilder.setManagers(buildManagersForHANode(childNode, haGlobalCfg));
497
498         nodeBuilder.setNodeId(haNodePath.firstKeyOf(Node.class).getNodeId());
499         nodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, hwvtepGlobalBuilder.build());
500         Node configHANode = nodeBuilder.build();
501         tx.merge(CONFIGURATION, haNodePath, configHANode,Boolean.TRUE);
502     }
503
504     public static void deleteNodeIfPresent(ReadWriteTransaction tx,
505                                            LogicalDatastoreType logicalDatastoreType,
506                                            InstanceIdentifier<?> iid) throws ReadFailedException {
507         if (tx.read(logicalDatastoreType, iid).checkedGet().isPresent()) {
508             LOG.info("Deleting child node {}", getNodeIdVal(iid));
509             tx.delete(logicalDatastoreType, iid);
510         }
511     }
512
513     /**
514      * Delete PS data of HA node of Config Data tree.
515      *
516      * @param key Node object
517      * @param haNode Ha Node from which to be deleted
518      * @param tx Transaction
519      * @throws ReadFailedException  Exception thrown if read fails
520      * @throws ExecutionException  Exception thrown if Execution fail
521      * @throws InterruptedException Thread interrupted Exception
522      */
523     public static void deletePSNodesOfNode(InstanceIdentifier<Node> key,
524                                            Node haNode,
525                                            ReadWriteTransaction tx)
526             throws InterruptedException, ExecutionException, ReadFailedException {
527         //read from switches attribute and clean up them
528         HwvtepGlobalAugmentation globalAugmentation = haNode.getAugmentation(HwvtepGlobalAugmentation.class);
529         if (globalAugmentation == null) {
530             return;
531         }
532         HashMap<InstanceIdentifier<Node>,Boolean> deleted = new HashMap<>();
533         List<Switches> switches = globalAugmentation.getSwitches();
534         if (switches != null) {
535             for (Switches switche : switches) {
536                 InstanceIdentifier<Node> psId = (InstanceIdentifier<Node>)switche.getSwitchRef().getValue();
537                 deleteNodeIfPresent(tx, CONFIGURATION, psId);
538                 deleted.put(psId, Boolean.TRUE);
539             }
540         }
541         //also read from managed by attribute of switches and cleanup them as a back up if the above cleanup fails
542         Optional<Topology> topologyOptional = tx
543                 .read(CONFIGURATION, key.firstIdentifierOf(Topology.class)).checkedGet();
544         String deletedNodeId = key.firstKeyOf(Node.class).getNodeId().getValue();
545         if (topologyOptional.isPresent()) {
546             Topology topology = topologyOptional.get();
547             if (topology.getNode() != null) {
548                 for (Node psNode : topology.getNode()) {
549                     PhysicalSwitchAugmentation ps = psNode.getAugmentation(PhysicalSwitchAugmentation.class);
550                     if (ps != null) {
551                         InstanceIdentifier<Node> iid = (InstanceIdentifier<Node>)ps.getManagedBy().getValue();
552                         String nodeIdVal = iid.firstKeyOf(Node.class).getNodeId().getValue();
553                         if (deletedNodeId.equals(nodeIdVal)) {
554                             InstanceIdentifier<Node> psNodeId =
555                                     convertToInstanceIdentifier(psNode.getNodeId().getValue());
556                             if (deleted.containsKey(psNodeId)) {
557                                 deleteNodeIfPresent(tx, CONFIGURATION, psNodeId);
558                             }
559                         }
560                     }
561                 }
562             }
563         }
564     }
565
566     /**
567      * Delete switches from Node in Operational Data Tree .
568      *
569      * @param haPath HA node path from whih switches will be deleted
570      * @param tx  Transaction object
571      * @throws ReadFailedException  Exception thrown if read fails
572      * @throws ExecutionException  Exception thrown if Execution fail
573      * @throws InterruptedException Thread interrupted Exception
574      */
575     public static void deleteSwitchesManagedByNode(InstanceIdentifier<Node> haPath,
576                                                    ReadWriteTransaction tx)
577             throws InterruptedException, ExecutionException, ReadFailedException {
578
579         Optional<Node> nodeOptional = tx.read(OPERATIONAL, haPath).checkedGet();
580         if (!nodeOptional.isPresent()) {
581             return;
582         }
583         Node node = nodeOptional.get();
584         HwvtepGlobalAugmentation globalAugmentation = node.getAugmentation(HwvtepGlobalAugmentation.class);
585         if (globalAugmentation == null) {
586             return;
587         }
588         List<Switches> switches = globalAugmentation.getSwitches();
589         if (switches != null) {
590             for (Switches switche : switches) {
591                 InstanceIdentifier<Node> id = (InstanceIdentifier<Node>)switche.getSwitchRef().getValue();
592                 deleteNodeIfPresent(tx, OPERATIONAL, id);
593             }
594         }
595     }
596
597     /**
598      * Returns true/false if all the childrens are deleted from Operational Data store.
599      *
600      * @param children IID for the child node to read from OP data tree
601      * @param tx Transaction
602      * @return true/false boolean
603      * @throws ReadFailedException Exception thrown if read fails
604      */
605     public static boolean areAllChildDeleted(Set<InstanceIdentifier<Node>> children,
606                                              ReadWriteTransaction tx) throws ReadFailedException {
607         for (InstanceIdentifier<Node> childId : children) {
608             if (tx.read(OPERATIONAL, childId).checkedGet().isPresent()) {
609                 return false;
610             }
611         }
612         return true;
613     }
614 }