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