2 * Copyright (c) 2016 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.genius.interfacemanager.listeners;
10 import com.google.common.util.concurrent.ListenableFuture;
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.concurrent.Callable;
14 import javax.inject.Inject;
15 import javax.inject.Singleton;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
19 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
20 import org.opendaylight.genius.interfacemanager.IfmConstants;
21 import org.opendaylight.genius.interfacemanager.IfmUtil;
22 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
23 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
24 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceStateAddHelper;
25 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceStateRemoveHelper;
26 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceStateUpdateHelper;
27 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.IfmClusterUtils;
28 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.AlivenessMonitorService;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntry;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
44 * This Class is a Data Change Listener for FlowCapableNodeConnector updates.
45 * This creates an entry in the interface-state OperDS for every node-connector used.
47 * NOTE: This class just creates an ifstate entry whose interface-name will be the same as the node-connector portname.
48 * If PortName is not unique across DPNs, this implementation can have problems.
51 public class InterfaceInventoryStateListener extends AsyncClusteredDataTreeChangeListenerBase<FlowCapableNodeConnector, InterfaceInventoryStateListener> {
52 private static final Logger LOG = LoggerFactory.getLogger(InterfaceInventoryStateListener.class);
53 private final DataBroker dataBroker;
54 private final IdManagerService idManager;
55 private final IMdsalApiManager mdsalApiManager;
56 private final AlivenessMonitorService alivenessMonitorService;
59 public InterfaceInventoryStateListener(final DataBroker dataBroker,
60 final IdManagerService idManagerService,
61 final IMdsalApiManager iMdsalApiManager,
62 final AlivenessMonitorService alivenessMonitorService) {
63 super(FlowCapableNodeConnector.class, InterfaceInventoryStateListener.class);
64 this.dataBroker = dataBroker;
65 this.idManager = idManagerService;
66 this.mdsalApiManager = iMdsalApiManager;
67 this.alivenessMonitorService = alivenessMonitorService;
68 this.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
72 protected InstanceIdentifier<FlowCapableNodeConnector> getWildCardPath() {
73 return InstanceIdentifier.create(Nodes.class).child(Node.class).child(NodeConnector.class)
74 .augmentation(FlowCapableNodeConnector.class);
78 protected InterfaceInventoryStateListener getDataTreeChangeListener() {
79 return InterfaceInventoryStateListener.this;
83 protected void remove(InstanceIdentifier<FlowCapableNodeConnector> key,
84 FlowCapableNodeConnector flowCapableNodeConnectorOld) {
85 IfmClusterUtils.runOnlyInLeaderNode(() -> {
86 LOG.debug("Received NodeConnector Remove Event: {}, {}", key, flowCapableNodeConnectorOld);
87 NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
88 String portName = InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId, flowCapableNodeConnectorOld.getName());
90 remove(nodeConnectorId, null, flowCapableNodeConnectorOld, portName, true);
95 protected void update(InstanceIdentifier<FlowCapableNodeConnector> key, FlowCapableNodeConnector fcNodeConnectorOld,
96 FlowCapableNodeConnector fcNodeConnectorNew) {
97 IfmClusterUtils.runOnlyInLeaderNode(() -> {
98 LOG.debug("Received NodeConnector Update Event: {}, {}, {}", key, fcNodeConnectorOld, fcNodeConnectorNew);
99 NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
100 String portName = InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId, fcNodeConnectorNew.getName());
101 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
103 InterfaceStateUpdateWorker portStateUpdateWorker = new InterfaceStateUpdateWorker(key, fcNodeConnectorOld,
104 fcNodeConnectorNew, portName);
105 coordinator.enqueueJob(portName, portStateUpdateWorker, IfmConstants.JOB_MAX_RETRIES);
110 protected void add(InstanceIdentifier<FlowCapableNodeConnector> key, FlowCapableNodeConnector fcNodeConnectorNew) {
111 IfmClusterUtils.runOnlyInLeaderNode(() -> {
112 LOG.debug("Received NodeConnector Add Event: {}, {}", key, fcNodeConnectorNew);
113 NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
114 String portName = InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId, fcNodeConnectorNew.getName());
116 //VM Migration: Delete existing interface entry for older DPN
117 if (InterfaceManagerCommonUtils.isNovaPort(portName)) {
118 NodeConnectorId nodeConnectorIdOld = IfmUtil.getNodeConnectorIdFromInterface(portName, dataBroker);
119 if (nodeConnectorIdOld != null && !nodeConnectorId.equals(nodeConnectorIdOld)) {
120 LOG.debug("Triggering NodeConnector Remove Event for the interface: {}, {}, {}", portName, nodeConnectorId, nodeConnectorIdOld);
121 remove(nodeConnectorId, nodeConnectorIdOld, fcNodeConnectorNew, portName, false);
122 //Adding a delay of 10sec for VM migration, so applications can process remove and add events
124 Thread.sleep(IfmConstants.DELAY_TIME_IN_MILLISECOND);
125 } catch (InterruptedException e) {
126 LOG.error("Error while waiting for the vm migration remove events to get processed");
130 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
131 InterfaceStateAddWorker ifStateAddWorker = new InterfaceStateAddWorker(idManager, nodeConnectorId,
132 fcNodeConnectorNew, portName);
133 coordinator.enqueueJob(portName, ifStateAddWorker, IfmConstants.JOB_MAX_RETRIES);
137 private void remove(NodeConnectorId nodeConnectorIdNew, NodeConnectorId nodeConnectorIdOld,
138 FlowCapableNodeConnector fcNodeConnectorNew, String portName, boolean isNetworkEvent) {
139 boolean isNodePresent = InterfaceManagerCommonUtils.isNodePresent(dataBroker, nodeConnectorIdNew);
140 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
141 InterfaceStateRemoveWorker portStateRemoveWorker = new InterfaceStateRemoveWorker(idManager, nodeConnectorIdNew,
142 nodeConnectorIdOld, fcNodeConnectorNew, portName, portName, isNodePresent, isNetworkEvent, true);
143 coordinator.enqueueJob(portName, portStateRemoveWorker, IfmConstants.JOB_MAX_RETRIES);
146 private class InterfaceStateAddWorker implements Callable {
147 private final NodeConnectorId nodeConnectorId;
148 private final FlowCapableNodeConnector fcNodeConnectorNew;
149 private final String interfaceName;
150 private final IdManagerService idManager;
152 public InterfaceStateAddWorker(IdManagerService idManager, NodeConnectorId nodeConnectorId,
153 FlowCapableNodeConnector fcNodeConnectorNew,
155 this.nodeConnectorId = nodeConnectorId;
156 this.fcNodeConnectorNew = fcNodeConnectorNew;
157 this.interfaceName = portName;
158 this.idManager = idManager;
162 public Object call() {
163 // If another renderer(for eg : CSS) needs to be supported, check can be performed here
164 // to call the respective helpers.
165 List<ListenableFuture<Void>> futures = OvsInterfaceStateAddHelper.addState(dataBroker, idManager, mdsalApiManager, alivenessMonitorService, nodeConnectorId,
166 interfaceName, fcNodeConnectorNew);
167 List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(dataBroker, interfaceName);
168 for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
169 InterfaceStateAddWorker interfaceStateAddWorker = new InterfaceStateAddWorker(idManager, nodeConnectorId,
170 fcNodeConnectorNew, interfaceChildEntry.getChildInterface());
171 DataStoreJobCoordinator.getInstance().enqueueJob(interfaceName, interfaceStateAddWorker);
177 public String toString() {
178 return "InterfaceStateAddWorker{" +
179 "nodeConnectorId=" + nodeConnectorId +
180 ", fcNodeConnectorNew=" + fcNodeConnectorNew +
181 ", interfaceName='" + interfaceName + '\'' +
186 private class InterfaceStateUpdateWorker implements Callable {
187 private final InstanceIdentifier<FlowCapableNodeConnector> key;
188 private final FlowCapableNodeConnector fcNodeConnectorOld;
189 private final FlowCapableNodeConnector fcNodeConnectorNew;
190 private final String interfaceName;
193 public InterfaceStateUpdateWorker(InstanceIdentifier<FlowCapableNodeConnector> key,
194 FlowCapableNodeConnector fcNodeConnectorOld,
195 FlowCapableNodeConnector fcNodeConnectorNew,
198 this.fcNodeConnectorOld = fcNodeConnectorOld;
199 this.fcNodeConnectorNew = fcNodeConnectorNew;
200 this.interfaceName = portName;
204 public Object call() {
205 // If another renderer(for eg : CSS) needs to be supported, check can be performed here
206 // to call the respective helpers.
207 List<ListenableFuture<Void>> futures = OvsInterfaceStateUpdateHelper.updateState(key, alivenessMonitorService, dataBroker, interfaceName,
208 fcNodeConnectorNew, fcNodeConnectorOld);
209 List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(dataBroker, interfaceName);
210 for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
211 InterfaceStateUpdateWorker interfaceStateUpdateWorker = new InterfaceStateUpdateWorker(key, fcNodeConnectorOld,
212 fcNodeConnectorNew, interfaceChildEntry.getChildInterface());
213 DataStoreJobCoordinator.getInstance().enqueueJob(interfaceName, interfaceStateUpdateWorker);
219 public String toString() {
220 return "InterfaceStateUpdateWorker{" +
222 ", fcNodeConnectorOld=" + fcNodeConnectorOld +
223 ", fcNodeConnectorNew=" + fcNodeConnectorNew +
224 ", interfaceName='" + interfaceName + '\'' +
229 private class InterfaceStateRemoveWorker implements Callable {
230 private final NodeConnectorId nodeConnectorIdNew;
231 private NodeConnectorId nodeConnectorIdOld;
232 FlowCapableNodeConnector fcNodeConnectorOld;
233 private final String interfaceName;
234 private final String parentInterface;
235 private final IdManagerService idManager;
236 private final boolean isNodePresent;
237 private final boolean isNetworkEvent;
238 private final boolean isParentInterface;
240 public InterfaceStateRemoveWorker(IdManagerService idManager, NodeConnectorId nodeConnectorIdNew,
241 NodeConnectorId nodeConnectorIdOld,
242 FlowCapableNodeConnector fcNodeConnectorOld,
243 String interfaceName,
244 String parentInterface,
245 boolean isNodePresent,
246 boolean isNetworkEvent,
247 boolean isParentInterface) {
248 this.nodeConnectorIdNew = nodeConnectorIdNew;
249 this.nodeConnectorIdOld = nodeConnectorIdOld;
250 this.fcNodeConnectorOld = fcNodeConnectorOld;
251 this.interfaceName = interfaceName;
252 this.parentInterface = parentInterface;
253 this.idManager = idManager;
254 this.isNodePresent = isNodePresent;
255 this.isNetworkEvent = isNetworkEvent;
256 this.isParentInterface = isParentInterface;
260 public Object call() {
261 // If another renderer(for eg : CSS) needs to be supported, check can be performed here
262 // to call the respective helpers.
264 List<ListenableFuture<Void>> futures = null;
265 //VM Migration: Skip OFPPR_DELETE event received after OFPPR_ADD for same interface from Older DPN
266 if (isParentInterface && isNetworkEvent) {
267 nodeConnectorIdOld = IfmUtil.getNodeConnectorIdFromInterface(interfaceName, dataBroker);
268 if(nodeConnectorIdOld != null && !nodeConnectorIdNew.equals(nodeConnectorIdOld)) {
269 LOG.debug("Dropping the NodeConnector Remove Event for the interface: {}, {}, {}", interfaceName, nodeConnectorIdNew, nodeConnectorIdOld);
274 futures = OvsInterfaceStateRemoveHelper.removeInterfaceStateConfiguration(idManager, mdsalApiManager, alivenessMonitorService,
275 nodeConnectorIdNew, nodeConnectorIdOld, dataBroker, interfaceName, fcNodeConnectorOld, isNodePresent, parentInterface);
277 List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(dataBroker, interfaceName);
278 for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
279 // Fetch all interfaces on this port and trigger remove worker for each of them
280 InterfaceStateRemoveWorker interfaceStateRemoveWorker = new InterfaceStateRemoveWorker(idManager, nodeConnectorIdNew,
281 nodeConnectorIdOld, fcNodeConnectorOld, interfaceChildEntry.getChildInterface(), interfaceName, isNodePresent, isNetworkEvent, false);
282 DataStoreJobCoordinator.getInstance().enqueueJob(interfaceName, interfaceStateRemoveWorker);
288 public String toString() {
289 return "InterfaceStateRemoveWorker{" +
290 "nodeConnectorIdNew=" + nodeConnectorIdNew +
291 ", nodeConnectorIdOld=" + nodeConnectorIdOld +
292 ", fcNodeConnectorOld=" + fcNodeConnectorOld +
293 ", interfaceName='" + interfaceName + '\'' +
298 public static List<InterfaceChildEntry> getInterfaceChildEntries(DataBroker dataBroker, String interfaceName) {
299 InterfaceParentEntry interfaceParentEntry =
300 InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceName, dataBroker);
301 if (interfaceParentEntry != null && interfaceParentEntry.getInterfaceChildEntry() != null) {
302 return interfaceParentEntry.getInterfaceChildEntry();
304 return new ArrayList<>();