Remove unused parameters
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / l2gw / ha / listeners / HAOpNodeListener.java
1 /*
2  * Copyright (c) 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.netvirt.elan.l2gw.ha.listeners;
9
10 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
11
12 import com.google.common.base.Optional;
13 import com.google.common.base.Strings;
14
15 import java.util.ArrayList;
16 import java.util.List;
17 import java.util.Set;
18 import java.util.function.BiPredicate;
19 import java.util.function.Predicate;
20 import java.util.stream.Collectors;
21 import javax.inject.Inject;
22 import javax.inject.Singleton;
23
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
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.LogicalDatastoreType;
28 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
29 import org.opendaylight.netvirt.elan.l2gw.ha.HwvtepHAUtil;
30 import org.opendaylight.netvirt.elan.l2gw.ha.handlers.HAEventHandler;
31 import org.opendaylight.netvirt.elan.l2gw.ha.handlers.IHAEventHandler;
32 import org.opendaylight.netvirt.elan.l2gw.ha.handlers.NodeCopier;
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.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36
37 @Singleton
38 public class HAOpNodeListener extends HwvtepNodeBaseListener {
39
40     static BiPredicate<String, InstanceIdentifier<Node>> IS_PS_CHILD_TO_GLOBAL_NODE = (globalNodeId, iid) -> {
41         String psNodeId = iid.firstKeyOf(Node.class).getNodeId().getValue();
42         return psNodeId.startsWith(globalNodeId) && psNodeId.contains("physicalswitch");
43     };
44
45     static Predicate<InstanceIdentifier<Node>> IS_NOT_HA_CHILD = (iid) -> hwvtepHACache.getParent(iid) == null;
46
47     private final IHAEventHandler haEventHandler;
48     private final HAOpClusteredListener haOpClusteredListener;
49     private final NodeCopier nodeCopier;
50
51     @Inject
52     public HAOpNodeListener(DataBroker db, HAEventHandler haEventHandler,
53                             HAOpClusteredListener haOpClusteredListener,
54                             NodeCopier nodeCopier) throws Exception {
55         super(OPERATIONAL, db);
56         this.haEventHandler = haEventHandler;
57         this.haOpClusteredListener = haOpClusteredListener;
58         this.nodeCopier = nodeCopier;
59     }
60
61     String getNodeId(InstanceIdentifier<Node> iid) {
62         return iid.firstKeyOf(Node.class).getNodeId().getValue();
63     }
64
65     @Override
66     public void onGlobalNodeAdd(InstanceIdentifier<Node> childGlobalPath,
67                                 Node childNode,
68                                 ReadWriteTransaction tx) {
69         //copy child global node to ha global node
70         //create ha global config node if not present
71         //copy ha global config node to child global config node
72         LOG.trace("Node connected {} - Checking if Ha or Non-Ha enabled ", childNode.getNodeId().getValue());
73         haOpClusteredListener.onGlobalNodeAdd(childGlobalPath, childNode, tx);
74         if (IS_NOT_HA_CHILD.test(childGlobalPath)) {
75             return;
76         }
77         InstanceIdentifier<Node> haNodePath = hwvtepHACache.getParent(childGlobalPath);
78         LOG.trace("Ha enabled child node connected {}", childNode.getNodeId().getValue());
79         try {
80             nodeCopier.copyGlobalNode(Optional.fromNullable(childNode),
81                     childGlobalPath, haNodePath, LogicalDatastoreType.OPERATIONAL, tx);
82             nodeCopier.copyGlobalNode(Optional.fromNullable(null),
83                     haNodePath, childGlobalPath, LogicalDatastoreType.CONFIGURATION, tx);
84         } catch (ReadFailedException e) {
85             LOG.error("Failed to read nodes {} , {} ", childGlobalPath, haNodePath);
86         }
87         readAndCopyChildPsOpToParent(childNode, tx);
88     }
89
90     //Update on global node has been taken care by HAListeners as per perf improvement
91     @Override
92     void onGlobalNodeUpdate(InstanceIdentifier<Node> childGlobalPath,
93                             Node updatedChildNode,
94                             Node originalChildNode,
95                             DataObjectModification<Node> mod,
96                             ReadWriteTransaction tx) throws ReadFailedException {
97
98         String oldHAId = HwvtepHAUtil.getHAIdFromManagerOtherConfig(originalChildNode);
99         if (!Strings.isNullOrEmpty(oldHAId)) { //was already ha child
100             InstanceIdentifier<Node> haPath = hwvtepHACache.getParent(childGlobalPath);
101             LOG.debug("Copy oper update from child {} to parent {}", childGlobalPath, haPath);
102             haEventHandler.copyChildGlobalOpUpdateToHAParent(haPath, mod, tx);
103             return;//TODO handle unha case
104         }
105
106         HAOpClusteredListener.addToHACacheIfBecameHAChild(childGlobalPath, updatedChildNode, originalChildNode);
107         if (IS_NOT_HA_CHILD.test(childGlobalPath)) {
108             return;
109         }
110         LOG.info("{} became ha child ", updatedChildNode.getNodeId().getValue());
111         onGlobalNodeAdd(childGlobalPath, updatedChildNode, tx);
112     }
113
114     @Override
115     void onGlobalNodeDelete(InstanceIdentifier<Node> childGlobalPath,
116                             Node childNode,
117                             ReadWriteTransaction tx) throws
118             ReadFailedException {
119         haOpClusteredListener.onGlobalNodeDelete(childGlobalPath, childNode, tx);
120         if (IS_NOT_HA_CHILD.test(childGlobalPath)) {
121             LOG.info("non ha child global delete {} ", getNodeId(childGlobalPath));
122             return;
123         }
124         LOG.info("ha child global delete {} ", getNodeId(childGlobalPath));
125         InstanceIdentifier<Node> haNodePath = hwvtepHACache.getParent(childGlobalPath);
126         Set<InstanceIdentifier<Node>> children = hwvtepHACache.getChildrenForHANode(haNodePath);
127         if (haOpClusteredListener.getConnected(children).isEmpty()) {
128             LOG.info("All child deleted for ha node {} ", HwvtepHAUtil.getNodeIdVal(haNodePath));
129             //ha ps delete is taken care by ps node delete
130             //HwvtepHAUtil.deleteSwitchesManagedBy-Node(haNodePath, tx);
131             HwvtepHAUtil.deleteNodeIfPresent(tx, OPERATIONAL, haNodePath);
132         } else {
133             LOG.info("not all child deleted {} connected {}", getNodeId(childGlobalPath),
134                     haOpClusteredListener.getConnected(children));
135         }
136     }
137
138     @Override
139     void onPsNodeAdd(InstanceIdentifier<Node> childPsPath,
140                      Node childPsNode,
141                      ReadWriteTransaction tx) {
142         //copy child ps oper node to ha ps oper node
143         //copy ha ps config node to child ps config
144         haOpClusteredListener.onPsNodeAdd(childPsPath, childPsNode, tx);
145         InstanceIdentifier<Node> childGlobalPath = HwvtepHAUtil.getGlobalNodePathFromPSNode(childPsNode);
146         if (!haOpClusteredListener.getConnectedNodes().contains(childGlobalPath)) {
147             return;
148         }
149         if (IS_NOT_HA_CHILD.test(childGlobalPath)) {
150             return;
151         }
152         LOG.info("ha ps child connected {} ", getNodeId(childPsPath));
153         InstanceIdentifier<Node> haGlobalPath = hwvtepHACache.getParent(childGlobalPath);
154         InstanceIdentifier<Node> haPsPath = HwvtepHAUtil.convertPsPath(childPsNode, haGlobalPath);
155         try {
156             nodeCopier.copyPSNode(Optional.fromNullable(childPsNode), childPsPath, haPsPath, haGlobalPath,
157                     LogicalDatastoreType.OPERATIONAL, tx);
158             nodeCopier.copyPSNode(Optional.fromNullable(null), haPsPath, childPsPath, childGlobalPath,
159                     LogicalDatastoreType.CONFIGURATION, tx);
160         } catch (ReadFailedException e) {
161             LOG.error("Failed to read nodes {} , {} ", childPsPath, haGlobalPath);
162         }
163     }
164
165     @Override
166     void onPsNodeUpdate(Node updatedChildPSNode,
167             Node originalChildPSNode,
168             DataObjectModification<Node> mod,
169             ReadWriteTransaction tx) throws ReadFailedException {
170         InstanceIdentifier<Node> childGlobalPath = HwvtepHAUtil.getGlobalNodePathFromPSNode(updatedChildPSNode);
171         if (IS_NOT_HA_CHILD.test(childGlobalPath)) {
172             return;
173         }
174         InstanceIdentifier<Node> haGlobalPath = hwvtepHACache.getParent(childGlobalPath);
175         haEventHandler.copyChildPsOpUpdateToHAParent(updatedChildPSNode, haGlobalPath, mod, tx);
176     }
177
178     @Override
179     void onPsNodeDelete(InstanceIdentifier<Node> childPsPath,
180                         Node childPsNode,
181                         ReadWriteTransaction tx) throws ReadFailedException {
182         //one child ps node disconnected
183         //find if all child ps nodes disconnected then delete parent ps node
184         haOpClusteredListener.onPsNodeDelete(childPsPath, childPsNode, tx);
185         InstanceIdentifier<Node> disconnectedChildGlobalPath = HwvtepHAUtil.getGlobalNodePathFromPSNode(childPsNode);
186         if (IS_NOT_HA_CHILD.test(disconnectedChildGlobalPath)) {
187             LOG.info("on non ha ps child delete {} ", getNodeId(childPsPath));
188             return;
189         }
190         InstanceIdentifier<Node> haGlobalPath = hwvtepHACache.getParent(disconnectedChildGlobalPath);
191         Set<InstanceIdentifier<Node>> childPsPaths = hwvtepHACache.getChildrenForHANode(haGlobalPath).stream()
192                 .map((childGlobalPath) -> HwvtepHAUtil.convertPsPath(childPsNode, childGlobalPath))
193                 .collect(Collectors.toSet());
194         //TODO validate what if this is null
195         if (haOpClusteredListener.getConnected(childPsPaths).isEmpty()) {
196             InstanceIdentifier<Node> haPsPath = HwvtepHAUtil.convertPsPath(childPsNode, haGlobalPath);
197             LOG.info("All child deleted for ha ps node {} ", HwvtepHAUtil.getNodeIdVal(haPsPath));
198             HwvtepHAUtil.deleteNodeIfPresent(tx, LogicalDatastoreType.OPERATIONAL, haPsPath);
199             //HwvtepHAUtil.deleteGlobalNodeSwitches(haGlobalPath, haPsPath, LogicalDatastoreType.OPERATIONAL, tx);
200         } else {
201             LOG.info("not all ha ps child deleted {} connected {}", getNodeId(childPsPath),
202                     haOpClusteredListener.getConnected(childPsPaths));
203         }
204     }
205
206     private void readAndCopyChildPsOpToParent(Node childNode, ReadWriteTransaction tx) {
207         String childGlobalNodeId = childNode.getNodeId().getValue();
208         List<InstanceIdentifier> childPsIids = new ArrayList<>();
209         HwvtepGlobalAugmentation hwvtepGlobalAugmentation = childNode.getAugmentation(HwvtepGlobalAugmentation.class);
210         if (hwvtepGlobalAugmentation == null || HwvtepHAUtil.isEmpty(hwvtepGlobalAugmentation.getSwitches())) {
211             haOpClusteredListener.getConnectedNodes()
212                     .stream()
213                     .filter((connectedIid) -> IS_PS_CHILD_TO_GLOBAL_NODE.test(childGlobalNodeId, connectedIid))
214                     .forEach((connectedIid) -> childPsIids.add(connectedIid));
215         } else {
216             hwvtepGlobalAugmentation.getSwitches().forEach(
217                 (switches) -> childPsIids.add(switches.getSwitchRef().getValue()));
218         }
219         if (childPsIids.isEmpty()) {
220             LOG.info("No child ps found for global {}", childGlobalNodeId);
221         }
222         childPsIids.forEach((psIid) -> {
223             try {
224                 InstanceIdentifier<Node> childPsIid = psIid;
225                 Optional<Node> childPsNode = tx.read(LogicalDatastoreType.OPERATIONAL, childPsIid).checkedGet();
226                 if (childPsNode.isPresent()) {
227                     LOG.debug("Child oper PS node found");
228                     onPsNodeAdd(childPsIid, childPsNode.get(), tx);
229                 } else {
230                     LOG.debug("Child oper ps node not found {}", childPsIid);
231                 }
232             } catch (ReadFailedException e) {
233                 LOG.error("Failed to read child ps node {}", psIid);
234             }
235         });
236     }
237 }