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