df4b325621b907201fbe443da065ce7cf64bd06c
[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
11 import com.google.common.base.Strings;
12 import java.nio.charset.StandardCharsets;
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Optional;
20 import java.util.Set;
21 import java.util.concurrent.ExecutionException;
22 import java.util.stream.Collectors;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.opendaylight.genius.utils.hwvtep.HwvtepNodeHACache;
25 import org.opendaylight.mdsal.binding.api.DataObjectModification;
26 import org.opendaylight.mdsal.binding.util.Datastore;
27 import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
28 import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
29 import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
30 import org.opendaylight.netvirt.elan.l2gw.ha.commands.SwitchesCmd;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentationBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentationBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitchesKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Managers;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.ManagersBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.ManagersKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Switches;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.SwitchesKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.managers.ManagerOtherConfigs;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.managers.ManagerOtherConfigsBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.managers.ManagerOtherConfigsKey;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
58 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
59 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
60 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
61 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 public final class HwvtepHAUtil {
66
67     private static final Logger LOG = LoggerFactory.getLogger(HwvtepHAUtil.class);
68
69     //TODO reuse HWvtepSouthboundConstants
70     public static final String HA_ENABLED = "ha_enabled";
71     public static final String HWVTEP_ENTITY_TYPE = "hwvtep";
72     public static final String TEP_PREFIX = "vxlan_over_ipv4:";
73     public static final String HA_ID = "ha_id";
74     public static final String HA_CHILDREN = "ha_children";
75     public static final String PHYSICALSWITCH = "/physicalswitch/";
76     public static final TopologyId HWVTEP_TOPOLOGY_ID = new TopologyId(new Uri("hwvtep:1"));
77     public static final String UUID = "uuid";
78     public static final String HWVTEP_URI_PREFIX = "hwvtep";
79     public static final String MANAGER_KEY = "managerKey";
80     public static final String L2GW_JOB_KEY = ":l2gw";
81
82     private HwvtepHAUtil() {
83
84     }
85
86     public static HwvtepPhysicalLocatorRef buildLocatorRef(InstanceIdentifier<Node> nodeIid, String tepIp) {
87         InstanceIdentifier<TerminationPoint> tepId = buildTpId(nodeIid, tepIp);
88         return new HwvtepPhysicalLocatorRef(tepId);
89     }
90
91     public static String getNodeIdVal(InstanceIdentifier<?> iid) {
92         return iid.firstKeyOf(Node.class).getNodeId().getValue();
93     }
94
95     public static Uuid getUUid(String key) {
96         return new Uuid(java.util.UUID.nameUUIDFromBytes(key.getBytes(StandardCharsets.UTF_8)).toString());
97     }
98
99     public static InstanceIdentifier<TerminationPoint> buildTpId(InstanceIdentifier<Node> nodeIid,String tepIp) {
100         String tpKeyStr = TEP_PREFIX + tepIp;
101         TerminationPointKey tpKey = new TerminationPointKey(new TpId(tpKeyStr));
102         InstanceIdentifier<TerminationPoint> plIid = nodeIid.child(TerminationPoint.class, tpKey);
103         return plIid;
104     }
105
106     public static String getTepIpVal(HwvtepPhysicalLocatorRef locatorRef) {
107         InstanceIdentifier<TerminationPoint> tpId = (InstanceIdentifier<TerminationPoint>) locatorRef.getValue();
108         return tpId.firstKeyOf(TerminationPoint.class).getTpId().getValue().substring("vxlan_over_ipv4:".length());
109     }
110
111     public static InstanceIdentifier<Node> createInstanceIdentifierFromHAId(String haUUidVal) {
112         String nodeString = HWVTEP_URI_PREFIX + "://"
113             + UUID + "/" + java.util.UUID.nameUUIDFromBytes(haUUidVal.getBytes(StandardCharsets.UTF_8)).toString();
114         NodeId nodeId = new NodeId(new Uri(nodeString));
115         NodeKey nodeKey = new NodeKey(nodeId);
116         TopologyKey topoKey = new TopologyKey(HWVTEP_TOPOLOGY_ID);
117         return InstanceIdentifier.builder(NetworkTopology.class)
118                 .child(Topology.class, topoKey)
119                 .child(Node.class, nodeKey)
120                 .build();
121     }
122
123     public static InstanceIdentifier<Node> convertToInstanceIdentifier(String nodeIdString) {
124         NodeId nodeId = new NodeId(new Uri(nodeIdString));
125         NodeKey nodeKey = new NodeKey(nodeId);
126         TopologyKey topoKey = new TopologyKey(HWVTEP_TOPOLOGY_ID);
127         return InstanceIdentifier.builder(NetworkTopology.class)
128                 .child(Topology.class, topoKey)
129                 .child(Node.class, nodeKey)
130                 .build();
131     }
132
133     /**
134      * Build other config data for HA node .
135      *
136      * @param key The key as in HA child device other config
137      * @param val The value as in HA child device other config
138      * @return return other config object
139      */
140     public static ManagerOtherConfigsBuilder getOtherConfigBuilder(String key, String val) {
141         ManagerOtherConfigsBuilder otherConfigsBuilder = new ManagerOtherConfigsBuilder();
142         ManagerOtherConfigsKey otherConfigsKey = new ManagerOtherConfigsKey(key);
143         otherConfigsBuilder.withKey(otherConfigsKey);
144         otherConfigsBuilder.setOtherConfigKey(key);
145         otherConfigsBuilder.setOtherConfigValue(val);
146         return otherConfigsBuilder;
147     }
148
149     public static String convertToGlobalNodeId(String psNodeId) {
150         int idx = psNodeId.indexOf(PHYSICALSWITCH);
151         if (idx > 0) {
152             return psNodeId.substring(0, idx);
153         }
154         return psNodeId;
155     }
156
157     /**
158      * Trnaform logical switch to nodepath passed .
159      *
160      * @param src {@link HwvtepLogicalSwitchRef} Logical Switch Ref which needs to be transformed
161      * @param nodePath {@link InstanceIdentifier} src needs to be transformed to this path
162      * @return ref {@link HwvtepLogicalSwitchRef} the transforrmed result
163      */
164     public static HwvtepLogicalSwitchRef convertLogicalSwitchRef(HwvtepLogicalSwitchRef src,
165                                                                  InstanceIdentifier<Node> nodePath) {
166         InstanceIdentifier<LogicalSwitches> srcId = (InstanceIdentifier<LogicalSwitches>)src.getValue();
167         HwvtepNodeName switchName = srcId.firstKeyOf(LogicalSwitches.class).getHwvtepNodeName();
168         InstanceIdentifier<LogicalSwitches> iid = nodePath.augmentation(HwvtepGlobalAugmentation.class)
169                 .child(LogicalSwitches.class, new LogicalSwitchesKey(switchName));
170         HwvtepLogicalSwitchRef ref = new HwvtepLogicalSwitchRef(iid);
171         return ref;
172     }
173
174     /**
175      * Trnaform locator reference to nodepath passed .
176      *
177      * @param src {@link HwvtepPhysicalLocatorRef} Logical Switch Ref which needs to be transformed
178      * @param nodePath {@link InstanceIdentifier} src needs to be transformed to this path
179      * @return physicalLocatorRef {@link HwvtepPhysicalLocatorRef} the transforrmed result
180      */
181     public static HwvtepPhysicalLocatorRef convertLocatorRef(HwvtepPhysicalLocatorRef src,
182                                                              InstanceIdentifier<Node> nodePath) {
183         InstanceIdentifier<TerminationPoint> srcTepPath = (InstanceIdentifier<TerminationPoint>)src.getValue();
184         TpId tpId = srcTepPath.firstKeyOf(TerminationPoint.class).getTpId();
185         InstanceIdentifier<TerminationPoint> tpPath =
186                 nodePath.child(TerminationPoint.class, new TerminationPointKey(tpId));
187         HwvtepPhysicalLocatorRef physicalLocatorRef = new HwvtepPhysicalLocatorRef(tpPath);
188         return physicalLocatorRef;
189     }
190
191     public static boolean isEmptyList(@Nullable List list) {
192         return list == null || list.isEmpty();
193     }
194
195     public static boolean isEmpty(Collection collection) {
196         return collection == null || collection.isEmpty();
197     }
198
199     @Nullable
200     public static Node getOriginal(DataObjectModification<Node> mod) {
201         Node node = null;
202         switch (mod.getModificationType()) {
203             case SUBTREE_MODIFIED:
204             case DELETE:
205                 node = mod.getDataBefore();
206                 break;
207             case WRITE:
208                 if (mod.getDataBefore() !=  null) {
209                     node = mod.getDataBefore();
210                 }
211                 break;
212             default:
213                 break;
214         }
215         return node;
216     }
217
218     @Nullable
219     public static Node getUpdated(DataObjectModification<Node> mod) {
220         switch (mod.getModificationType()) {
221             case SUBTREE_MODIFIED:
222             case WRITE:
223                 return mod.getDataAfter();
224             default:
225                 return null;
226         }
227     }
228
229     @Nullable
230     public static Node getCreated(DataObjectModification<Node> mod) {
231         if (mod.getModificationType() == DataObjectModification.ModificationType.WRITE
232                 && mod.getDataBefore() == null) {
233             return mod.getDataAfter();
234         }
235         return null;
236     }
237
238     @Nullable
239     public static Node getRemoved(DataObjectModification<Node> mod) {
240         if (mod.getModificationType() == DataObjectModification.ModificationType.DELETE) {
241             return mod.getDataBefore();
242         }
243         return null;
244     }
245
246     @Nullable
247     public static String getPsName(InstanceIdentifier<Node> psNodeIid) {
248         String psNodeId = psNodeIid.firstKeyOf(Node.class).getNodeId().getValue();
249         if (psNodeId.contains(PHYSICALSWITCH)) {
250             return psNodeId.substring(psNodeId.indexOf(PHYSICALSWITCH) +  PHYSICALSWITCH.length());
251         }
252         return null;
253     }
254
255     @Nullable
256     public static String getPsName(String psNodeId) {
257         if (psNodeId.contains(PHYSICALSWITCH)) {
258             return psNodeId.substring(psNodeId.indexOf(PHYSICALSWITCH) + PHYSICALSWITCH.length());
259         }
260         return null;
261     }
262
263     public static InstanceIdentifier<Node> getGlobalNodePathFromPSNode(Node psNode) {
264         String psNodeId = psNode.getNodeId().getValue();
265         if (psNodeId.contains(PHYSICALSWITCH)) {
266             return convertToInstanceIdentifier(psNodeId.substring(0, psNodeId.indexOf(PHYSICALSWITCH)));
267         }
268         return convertToInstanceIdentifier(psNodeId);
269     }
270
271     @Nullable
272     public static InstanceIdentifier<Node> convertPsPath(Node psNode, InstanceIdentifier<Node> nodePath) {
273         String psNodeId = psNode.getNodeId().getValue();
274         if (psNodeId.contains(PHYSICALSWITCH)) {
275             String psName = psNodeId.substring(psNodeId.indexOf(PHYSICALSWITCH) + PHYSICALSWITCH.length());
276             String haPsNodeIdVal = nodePath.firstKeyOf(Node.class).getNodeId().getValue() + PHYSICALSWITCH + psName;
277             InstanceIdentifier<Node> haPsPath = convertToInstanceIdentifier(haPsNodeIdVal);
278             return haPsPath;
279         } else {
280             LOG.error("Failed to find ps path from node {}", psNode);
281             return null;
282         }
283     }
284
285     public static NodeBuilder getNodeBuilderForPath(InstanceIdentifier<Node> haPath) {
286         NodeBuilder nodeBuilder = new NodeBuilder();
287         nodeBuilder.setNodeId(haPath.firstKeyOf(Node.class).getNodeId());
288         return nodeBuilder;
289     }
290
291     @Nullable
292     public static String getHAIdFromManagerOtherConfig(Node node) {
293         if (node.augmentation(HwvtepGlobalAugmentation.class) == null) {
294             return null;
295         }
296         HwvtepGlobalAugmentation globalAugmentation = node.augmentation(HwvtepGlobalAugmentation.class);
297         if (globalAugmentation != null) {
298             List<Managers> managers = new ArrayList<Managers>(globalAugmentation.nonnullManagers().values());
299             if (managers != null && !managers.isEmpty() && managers.get(0).getManagerOtherConfigs() != null) {
300                 for (ManagerOtherConfigs configs : managers.get(0).nonnullManagerOtherConfigs().values()) {
301                     if (HA_ID.equals(configs.getOtherConfigKey())) {
302                         return configs.getOtherConfigValue();
303                     }
304                 }
305             }
306         }
307         return null;
308     }
309
310     /**
311      * Returns ha child node path from ha node of config data tree.
312      *
313      * @param haGlobalConfigNodeOptional HA global node
314      * @return ha Child ids
315      */
316     public static  List<NodeId> getChildNodeIdsFromManagerOtherConfig(Optional<Node> haGlobalConfigNodeOptional) {
317         List<NodeId> childNodeIds = new ArrayList<>();
318         if (!haGlobalConfigNodeOptional.isPresent()) {
319             return childNodeIds;
320         }
321         HwvtepGlobalAugmentation augmentation =
322                 haGlobalConfigNodeOptional.get().augmentation(HwvtepGlobalAugmentation.class);
323         if (augmentation != null && augmentation.getManagers() != null
324                 && augmentation.getManagers().size() > 0) {
325             Managers managers = new ArrayList<Managers>(augmentation.nonnullManagers().values()).get(0);
326             if (null == managers.getManagerOtherConfigs()) {
327                 return childNodeIds;
328             }
329             for (ManagerOtherConfigs otherConfigs : managers.nonnullManagerOtherConfigs().values()) {
330                 if (HA_CHILDREN.equals(otherConfigs.getOtherConfigKey())) {
331                     String nodeIdsVal = otherConfigs.getOtherConfigValue();
332                     if (nodeIdsVal != null) {
333                         String[] parts = nodeIdsVal.split(",");
334                         for (String part : parts) {
335                             childNodeIds.add(new NodeId(part));
336                         }
337                     }
338
339                 }
340             }
341         }
342         return childNodeIds;
343     }
344
345     public static HwvtepGlobalAugmentation getGlobalAugmentationOfNode(Node node) {
346         HwvtepGlobalAugmentation result = null;
347         if (node != null) {
348             result = node.augmentation(HwvtepGlobalAugmentation.class);
349         }
350         if (result == null) {
351             result = new HwvtepGlobalAugmentationBuilder().build();
352         }
353         return result;
354     }
355
356     public static PhysicalSwitchAugmentation getPhysicalSwitchAugmentationOfNode(Node psNode) {
357         PhysicalSwitchAugmentation result = null;
358         if (psNode != null) {
359             result = psNode.augmentation(PhysicalSwitchAugmentation.class);
360         }
361         if (result == null) {
362             result = new PhysicalSwitchAugmentationBuilder().build();
363         }
364         return result;
365     }
366
367     /**
368      * Transform child managers (Source) to HA managers using HA node path.
369      *
370      * @param childNode Child Node
371      * @param haGlobalCfg HA global config node
372      * @return Transformed managers
373      */
374     public static List<Managers> buildManagersForHANode(Node childNode, Optional<Node> haGlobalCfg) {
375
376         Set<NodeId> nodeIds = new HashSet<>();
377         nodeIds.add(childNode.getNodeId());
378         List<NodeId> childNodeIds = getChildNodeIdsFromManagerOtherConfig(haGlobalCfg);
379         nodeIds.addAll(childNodeIds);
380
381         ManagersBuilder builder1 = new ManagersBuilder();
382
383         builder1.withKey(new ManagersKey(new Uri(MANAGER_KEY)));
384         List<ManagerOtherConfigs> otherConfigses = new ArrayList<>();
385         String children = nodeIds.stream().map(NodeId::getValue).collect(Collectors.joining(","));
386         otherConfigses.add(getOtherConfigBuilder(HA_CHILDREN, children).build());
387         builder1.setManagerOtherConfigs(otherConfigses);
388         List<Managers> managers = new ArrayList<>();
389         managers.add(builder1.build());
390         return managers;
391     }
392
393     /**
394      * Transform child switch (Source) to HA swicthes using HA node path.
395      *
396      * @param childNode  HA child node
397      * @param haNodePath  HA node path
398      * @param haNode Ha node object
399      * @return Transformed switches
400      */
401     public static List<Switches> buildSwitchesForHANode(Node childNode,
402                                                         InstanceIdentifier<Node> haNodePath,
403                                                         Optional<Node> haNode) {
404         List<Switches> psList = new ArrayList<>();
405         boolean switchesAlreadyPresent = false;
406         if (haNode.isPresent()) {
407             Node node = haNode.get();
408             HwvtepGlobalAugmentation augmentation = node.augmentation(HwvtepGlobalAugmentation.class);
409             if (augmentation != null) {
410                 if (augmentation.getSwitches() != null) {
411                     if (augmentation.getSwitches().size() > 0) {
412                         switchesAlreadyPresent = true;
413                     }
414                 }
415             }
416         }
417         if (!switchesAlreadyPresent) {
418             HwvtepGlobalAugmentation augmentation = childNode.augmentation(HwvtepGlobalAugmentation.class);
419             if (augmentation != null && augmentation.getSwitches() != null) {
420                 List<Switches> src = new ArrayList<Switches>(augmentation.nonnullSwitches().values());
421                 if (src != null && src.size() > 0) {
422                     psList.add(new SwitchesCmd().transform(haNodePath, src.get(0)));
423                 }
424             }
425         }
426         return psList;
427     }
428
429     /**
430      * Build HA Global node from child nodes in config data tress.
431      *
432      * @param tx Transaction
433      * @param childNode Child Node object
434      * @param haNodePath Ha node path
435      * @param haGlobalCfg HA global node object
436      */
437     public static void buildGlobalConfigForHANode(TypedWriteTransaction<Configuration> tx,
438                                                   Node childNode,
439                                                   InstanceIdentifier<Node> haNodePath,
440                                                   Optional<Node> haGlobalCfg) {
441
442         NodeBuilder nodeBuilder = new NodeBuilder();
443         HwvtepGlobalAugmentationBuilder hwvtepGlobalBuilder = new HwvtepGlobalAugmentationBuilder();
444         hwvtepGlobalBuilder.setSwitches(buildSwitchesForHANode(childNode, haNodePath, haGlobalCfg));
445         hwvtepGlobalBuilder.setManagers(buildManagersForHANode(childNode, haGlobalCfg));
446
447         nodeBuilder.setNodeId(haNodePath.firstKeyOf(Node.class).getNodeId());
448         nodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, hwvtepGlobalBuilder.build());
449         Node configHANode = nodeBuilder.build();
450         tx.mergeParentStructureMerge(haNodePath, configHANode);
451     }
452
453     public static <D extends Datastore> void deleteNodeIfPresent(TypedReadWriteTransaction<D> tx,
454             InstanceIdentifier<?> iid) throws ExecutionException, InterruptedException {
455         if (tx.read(iid).get().isPresent()) {
456             LOG.info("Deleting child node {}", getNodeIdVal(iid));
457             tx.delete(iid);
458         }
459     }
460
461     /**
462      * Delete PS data of HA node of Config Data tree.
463      *
464      * @param key Node object
465      * @param haNode Ha Node from which to be deleted
466      * @param tx Transaction
467      */
468     public static void deletePSNodesOfNode(InstanceIdentifier<Node> key, Node haNode,
469             TypedReadWriteTransaction<Configuration> tx) throws ExecutionException, InterruptedException {
470         //read from switches attribute and clean up them
471         HwvtepGlobalAugmentation globalAugmentation = haNode.augmentation(HwvtepGlobalAugmentation.class);
472         if (globalAugmentation == null) {
473             return;
474         }
475         HashMap<InstanceIdentifier<Node>,Boolean> deleted = new HashMap<>();
476         Map<SwitchesKey, Switches> switches = globalAugmentation.nonnullSwitches();
477         if (switches != null) {
478             for (Switches switche : switches.values()) {
479                 InstanceIdentifier<Node> psId = (InstanceIdentifier<Node>)switche.getSwitchRef().getValue();
480                 deleteNodeIfPresent(tx, psId);
481                 deleted.put(psId, Boolean.TRUE);
482             }
483         }
484         //also read from managed by attribute of switches and cleanup them as a back up if the above cleanup fails
485         Optional<Topology> topologyOptional = tx .read(key.firstIdentifierOf(Topology.class)).get();
486         String deletedNodeId = key.firstKeyOf(Node.class).getNodeId().getValue();
487         if (topologyOptional.isPresent()) {
488             Topology topology = topologyOptional.get();
489             if (topology.getNode() != null) {
490                 for (Node psNode : topology.nonnullNode().values()) {
491                     PhysicalSwitchAugmentation ps = psNode.augmentation(PhysicalSwitchAugmentation.class);
492                     if (ps != null) {
493                         InstanceIdentifier<Node> iid = (InstanceIdentifier<Node>)ps.getManagedBy().getValue();
494                         String nodeIdVal = iid.firstKeyOf(Node.class).getNodeId().getValue();
495                         if (deletedNodeId.equals(nodeIdVal)) {
496                             InstanceIdentifier<Node> psNodeId =
497                                     convertToInstanceIdentifier(psNode.getNodeId().getValue());
498                             if (deleted.containsKey(psNodeId)) {
499                                 deleteNodeIfPresent(tx, psNodeId);
500                             }
501                         }
502                     }
503                 }
504             }
505         }
506     }
507
508     public static void addToCacheIfHAChildNode(InstanceIdentifier<Node> childPath, Node childNode,
509             HwvtepNodeHACache hwvtepNodeHACache) {
510         String haId = HwvtepHAUtil.getHAIdFromManagerOtherConfig(childNode);
511         if (!Strings.isNullOrEmpty(haId)) {
512             InstanceIdentifier<Node> parentId = HwvtepHAUtil.createInstanceIdentifierFromHAId(haId);
513             hwvtepNodeHACache.addChild(parentId, childPath/*child*/);
514         }
515     }
516 }