2 * Copyright (c) 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.netvirt.elan.l2gw.ha.listeners;
10 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
12 import com.google.common.base.Optional;
13 import com.google.common.base.Strings;
15 import java.util.ArrayList;
16 import java.util.List;
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;
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;
38 public class HAOpNodeListener extends HwvtepNodeBaseListener {
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");
45 static Predicate<InstanceIdentifier<Node>> IS_NOT_HA_CHILD = (iid) -> hwvtepHACache.getParent(iid) == null;
47 private final IHAEventHandler haEventHandler;
48 private final HAOpClusteredListener haOpClusteredListener;
49 private final NodeCopier nodeCopier;
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;
61 String getNodeId(InstanceIdentifier<Node> iid) {
62 return iid.firstKeyOf(Node.class).getNodeId().getValue();
66 public void onGlobalNodeAdd(InstanceIdentifier<Node> childGlobalPath,
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)) {
77 InstanceIdentifier<Node> haNodePath = hwvtepHACache.getParent(childGlobalPath);
78 LOG.trace("Ha enabled child node connected {}", childNode.getNodeId().getValue());
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);
87 readAndCopyChildPsOpToParent(childNode, tx);
90 //Update on global node has been taken care by HAListeners as per perf improvement
92 void onGlobalNodeUpdate(InstanceIdentifier<Node> childGlobalPath,
93 Node updatedChildNode,
94 Node originalChildNode,
95 DataObjectModification<Node> mod,
96 ReadWriteTransaction tx) throws ReadFailedException {
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
106 HAOpClusteredListener.addToHACacheIfBecameHAChild(childGlobalPath, updatedChildNode, originalChildNode);
107 if (IS_NOT_HA_CHILD.test(childGlobalPath)) {
110 LOG.info("{} became ha child ", updatedChildNode.getNodeId().getValue());
111 onGlobalNodeAdd(childGlobalPath, updatedChildNode, tx);
115 void onGlobalNodeDelete(InstanceIdentifier<Node> childGlobalPath,
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));
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);
133 LOG.info("not all child deleted {} connected {}", getNodeId(childGlobalPath),
134 haOpClusteredListener.getConnected(children));
139 void onPsNodeAdd(InstanceIdentifier<Node> childPsPath,
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)) {
149 if (IS_NOT_HA_CHILD.test(childGlobalPath)) {
152 LOG.info("ha ps child connected {} ", getNodeId(childPsPath));
153 InstanceIdentifier<Node> haGlobalPath = hwvtepHACache.getParent(childGlobalPath);
154 InstanceIdentifier<Node> haPsPath = HwvtepHAUtil.convertPsPath(childPsNode, haGlobalPath);
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);
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)) {
174 InstanceIdentifier<Node> haGlobalPath = hwvtepHACache.getParent(childGlobalPath);
175 haEventHandler.copyChildPsOpUpdateToHAParent(updatedChildPSNode, haGlobalPath, mod, tx);
179 void onPsNodeDelete(InstanceIdentifier<Node> childPsPath,
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));
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);
201 LOG.info("not all ha ps child deleted {} connected {}", getNodeId(childPsPath),
202 haOpClusteredListener.getConnected(childPsPaths));
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()
213 .filter((connectedIid) -> IS_PS_CHILD_TO_GLOBAL_NODE.test(childGlobalNodeId, connectedIid))
214 .forEach((connectedIid) -> childPsIids.add(connectedIid));
216 hwvtepGlobalAugmentation.getSwitches().forEach(
217 (switches) -> childPsIids.add(switches.getSwitchRef().getValue()));
219 if (childPsIids.isEmpty()) {
220 LOG.info("No child ps found for global {}", childGlobalNodeId);
222 childPsIids.forEach((psIid) -> {
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);
230 LOG.debug("Child oper ps node not found {}", childPsIid);
232 } catch (ReadFailedException e) {
233 LOG.error("Failed to read child ps node {}", psIid);