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 org.opendaylight.controller.md.sal.binding.api.DataBroker;
12 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
13 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
14 import org.opendaylight.genius.interfacemanager.IfmConstants;
15 import org.opendaylight.genius.interfacemanager.IfmUtil;
16 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
17 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
18 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceStateAddHelper;
19 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceStateRemoveHelper;
20 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceStateUpdateHelper;
21 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.IfmClusterUtils;
22 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.AlivenessMonitorService;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntry;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
32 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 import java.util.ArrayList;
37 import java.util.List;
38 import java.util.concurrent.Callable;
42 * This Class is a Data Change Listener for FlowCapableNodeConnector updates.
43 * This creates an entry in the interface-state OperDS for every node-connector used.
45 * NOTE: This class just creates an ifstate entry whose interface-name will be the same as the node-connector portname.
46 * If PortName is not unique across DPNs, this implementation can have problems.
49 public class InterfaceInventoryStateListener extends AsyncClusteredDataTreeChangeListenerBase<FlowCapableNodeConnector, InterfaceInventoryStateListener> {
50 private static final Logger LOG = LoggerFactory.getLogger(InterfaceInventoryStateListener.class);
51 private DataBroker dataBroker;
52 private IdManagerService idManager;
53 private IMdsalApiManager mdsalApiManager;
54 private AlivenessMonitorService alivenessMonitorService;
56 public InterfaceInventoryStateListener(final DataBroker dataBroker, final IdManagerService idManager,
57 final IMdsalApiManager mdsalApiManager, final AlivenessMonitorService alivenessMonitorService) {
58 super(FlowCapableNodeConnector.class, InterfaceInventoryStateListener.class);
59 this.dataBroker = dataBroker;
60 this.idManager = idManager;
61 this.mdsalApiManager = mdsalApiManager;
62 this.alivenessMonitorService = alivenessMonitorService;
66 protected InstanceIdentifier<FlowCapableNodeConnector> getWildCardPath() {
67 return InstanceIdentifier.create(Nodes.class).child(Node.class).child(NodeConnector.class)
68 .augmentation(FlowCapableNodeConnector.class);
72 protected InterfaceInventoryStateListener getDataTreeChangeListener() {
73 return InterfaceInventoryStateListener.this;
77 protected void remove(InstanceIdentifier<FlowCapableNodeConnector> key,
78 FlowCapableNodeConnector flowCapableNodeConnectorOld) {
79 IfmClusterUtils.runOnlyInLeaderNode(() -> {
80 LOG.debug("Received NodeConnector Remove Event: {}, {}", key, flowCapableNodeConnectorOld);
81 String portName = flowCapableNodeConnectorOld.getName();
82 NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
84 if (!InterfaceManagerCommonUtils.isNovaOrTunnelPort(portName)) {
85 portName = getDpnPrefixedPortName(nodeConnectorId, portName);
87 remove(nodeConnectorId, null, flowCapableNodeConnectorOld, portName, true);
92 protected void update(InstanceIdentifier<FlowCapableNodeConnector> key, FlowCapableNodeConnector fcNodeConnectorOld,
93 FlowCapableNodeConnector fcNodeConnectorNew) {
94 IfmClusterUtils.runOnlyInLeaderNode(() -> {
95 LOG.debug("Received NodeConnector Update Event: {}, {}, {}", key, fcNodeConnectorOld, fcNodeConnectorNew);
96 String portName = fcNodeConnectorNew.getName();
97 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
99 InterfaceStateUpdateWorker portStateUpdateWorker = new InterfaceStateUpdateWorker(key, fcNodeConnectorOld,
100 fcNodeConnectorNew, portName);
101 coordinator.enqueueJob(portName, portStateUpdateWorker, IfmConstants.JOB_MAX_RETRIES);
106 protected void add(InstanceIdentifier<FlowCapableNodeConnector> key, FlowCapableNodeConnector fcNodeConnectorNew) {
107 IfmClusterUtils.runOnlyInLeaderNode(() -> {
108 LOG.debug("Received NodeConnector Add Event: {}, {}", key, fcNodeConnectorNew);
109 String portName = fcNodeConnectorNew.getName();
110 NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
112 //VM Migration: Delete existing interface entry for older DPN
113 if (InterfaceManagerCommonUtils.isNovaOrTunnelPort(portName)) {
114 NodeConnectorId nodeConnectorIdOld = IfmUtil.getNodeConnectorIdFromInterface(portName, dataBroker);
115 if (nodeConnectorIdOld != null && !nodeConnectorId.equals(nodeConnectorIdOld)) {
116 LOG.debug("Triggering NodeConnector Remove Event for the interface: {}, {}, {}", portName, nodeConnectorId, nodeConnectorIdOld);
117 remove(nodeConnectorId, nodeConnectorIdOld, fcNodeConnectorNew, portName, false);
118 //Adding a delay of 10sec for VM migration, so applications can process remove and add events
120 Thread.sleep(IfmConstants.DELAY_TIME_IN_MILLISECOND);
121 } catch (InterruptedException e) {
122 LOG.error("Error while waiting for the vm migration remove events to get processed");
126 portName = getDpnPrefixedPortName(nodeConnectorId, portName);
128 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
129 InterfaceStateAddWorker ifStateAddWorker = new InterfaceStateAddWorker(idManager, nodeConnectorId,
130 fcNodeConnectorNew, portName);
131 coordinator.enqueueJob(portName, ifStateAddWorker, IfmConstants.JOB_MAX_RETRIES);
135 private void remove(NodeConnectorId nodeConnectorIdNew, NodeConnectorId nodeConnectorIdOld,
136 FlowCapableNodeConnector fcNodeConnectorNew, String portName, boolean isNetworkEvent) {
137 boolean isNodePresent = InterfaceManagerCommonUtils.isNodePresent(dataBroker, nodeConnectorIdNew);
138 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
139 InterfaceStateRemoveWorker portStateRemoveWorker = new InterfaceStateRemoveWorker(idManager, nodeConnectorIdNew,
140 nodeConnectorIdOld, fcNodeConnectorNew, portName, portName, isNodePresent, isNetworkEvent, true);
141 coordinator.enqueueJob(portName, portStateRemoveWorker, IfmConstants.JOB_MAX_RETRIES);
144 private String getDpnPrefixedPortName(NodeConnectorId nodeConnectorId, String portName) {
145 portName = (IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId)).toString() +
146 IfmConstants.OF_URI_SEPARATOR +
150 private class InterfaceStateAddWorker implements Callable {
151 private final NodeConnectorId nodeConnectorId;
152 private final FlowCapableNodeConnector fcNodeConnectorNew;
153 private final String interfaceName;
154 private final IdManagerService idManager;
156 public InterfaceStateAddWorker(IdManagerService idManager, NodeConnectorId nodeConnectorId,
157 FlowCapableNodeConnector fcNodeConnectorNew,
159 this.nodeConnectorId = nodeConnectorId;
160 this.fcNodeConnectorNew = fcNodeConnectorNew;
161 this.interfaceName = portName;
162 this.idManager = idManager;
166 public Object call() throws Exception {
167 // If another renderer(for eg : CSS) needs to be supported, check can be performed here
168 // to call the respective helpers.
169 List<ListenableFuture<Void>> futures = OvsInterfaceStateAddHelper.addState(dataBroker, idManager, mdsalApiManager, alivenessMonitorService, nodeConnectorId,
170 interfaceName, fcNodeConnectorNew);
171 List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(dataBroker, interfaceName);
172 for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
173 InterfaceStateAddWorker interfaceStateAddWorker = new InterfaceStateAddWorker(idManager, nodeConnectorId,
174 fcNodeConnectorNew, interfaceChildEntry.getChildInterface());
175 DataStoreJobCoordinator.getInstance().enqueueJob(interfaceName, interfaceStateAddWorker);
181 public String toString() {
182 return "InterfaceStateAddWorker{" +
183 "nodeConnectorId=" + nodeConnectorId +
184 ", fcNodeConnectorNew=" + fcNodeConnectorNew +
185 ", interfaceName='" + interfaceName + '\'' +
190 private class InterfaceStateUpdateWorker implements Callable {
191 private InstanceIdentifier<FlowCapableNodeConnector> key;
192 private final FlowCapableNodeConnector fcNodeConnectorOld;
193 private final FlowCapableNodeConnector fcNodeConnectorNew;
194 private String interfaceName;
197 public InterfaceStateUpdateWorker(InstanceIdentifier<FlowCapableNodeConnector> key,
198 FlowCapableNodeConnector fcNodeConnectorOld,
199 FlowCapableNodeConnector fcNodeConnectorNew,
202 this.fcNodeConnectorOld = fcNodeConnectorOld;
203 this.fcNodeConnectorNew = fcNodeConnectorNew;
204 this.interfaceName = portName;
208 public Object call() throws Exception {
209 // If another renderer(for eg : CSS) needs to be supported, check can be performed here
210 // to call the respective helpers.
211 List<ListenableFuture<Void>> futures = OvsInterfaceStateUpdateHelper.updateState(key, alivenessMonitorService, dataBroker, interfaceName,
212 fcNodeConnectorNew, fcNodeConnectorOld);
213 List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(dataBroker, interfaceName);
214 for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
215 InterfaceStateUpdateWorker interfaceStateUpdateWorker = new InterfaceStateUpdateWorker(key, fcNodeConnectorOld,
216 fcNodeConnectorNew, interfaceChildEntry.getChildInterface());
217 DataStoreJobCoordinator.getInstance().enqueueJob(interfaceName, interfaceStateUpdateWorker);
223 public String toString() {
224 return "InterfaceStateUpdateWorker{" +
226 ", fcNodeConnectorOld=" + fcNodeConnectorOld +
227 ", fcNodeConnectorNew=" + fcNodeConnectorNew +
228 ", interfaceName='" + interfaceName + '\'' +
233 private class InterfaceStateRemoveWorker implements Callable {
234 private final NodeConnectorId nodeConnectorIdNew;
235 private NodeConnectorId nodeConnectorIdOld;
236 FlowCapableNodeConnector fcNodeConnectorOld;
237 private final String interfaceName;
238 private final String parentInterface;
239 private final IdManagerService idManager;
240 private final boolean isNodePresent;
241 private final boolean isNetworkEvent;
242 private final boolean isParentInterface;
244 public InterfaceStateRemoveWorker(IdManagerService idManager, NodeConnectorId nodeConnectorIdNew,
245 NodeConnectorId nodeConnectorIdOld,
246 FlowCapableNodeConnector fcNodeConnectorOld,
247 String interfaceName,
248 String parentInterface,
249 boolean isNodePresent,
250 boolean isNetworkEvent,
251 boolean isParentInterface) {
252 this.nodeConnectorIdNew = nodeConnectorIdNew;
253 this.nodeConnectorIdOld = nodeConnectorIdOld;
254 this.fcNodeConnectorOld = fcNodeConnectorOld;
255 this.interfaceName = interfaceName;
256 this.parentInterface = parentInterface;
257 this.idManager = idManager;
258 this.isNodePresent = isNodePresent;
259 this.isNetworkEvent = isNetworkEvent;
260 this.isParentInterface = isParentInterface;
264 public Object call() throws Exception {
265 // If another renderer(for eg : CSS) needs to be supported, check can be performed here
266 // to call the respective helpers.
268 List<ListenableFuture<Void>> futures = null;
269 //VM Migration: Skip OFPPR_DELETE event received after OFPPR_ADD for same interface from Older DPN
270 if (isParentInterface && isNetworkEvent) {
271 nodeConnectorIdOld = IfmUtil.getNodeConnectorIdFromInterface(interfaceName, dataBroker);
272 if(nodeConnectorIdOld != null && !nodeConnectorIdNew.equals(nodeConnectorIdOld)) {
273 LOG.debug("Dropping the NodeConnector Remove Event for the interface: {}, {}, {}", interfaceName, nodeConnectorIdNew, nodeConnectorIdOld);
278 futures = OvsInterfaceStateRemoveHelper.removeInterfaceStateConfiguration(idManager, mdsalApiManager, alivenessMonitorService,
279 nodeConnectorIdNew, nodeConnectorIdOld, dataBroker, interfaceName, fcNodeConnectorOld, isNodePresent, parentInterface);
281 List<InterfaceChildEntry> interfaceChildEntries = getInterfaceChildEntries(dataBroker, interfaceName);
282 for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
283 // Fetch all interfaces on this port and trigger remove worker for each of them
284 InterfaceStateRemoveWorker interfaceStateRemoveWorker = new InterfaceStateRemoveWorker(idManager, nodeConnectorIdNew,
285 nodeConnectorIdOld, fcNodeConnectorOld, interfaceChildEntry.getChildInterface(), interfaceName, isNodePresent, isNetworkEvent, false);
286 DataStoreJobCoordinator.getInstance().enqueueJob(interfaceName, interfaceStateRemoveWorker);
292 public String toString() {
293 return "InterfaceStateRemoveWorker{" +
294 "nodeConnectorIdNew=" + nodeConnectorIdNew +
295 ", nodeConnectorIdOld=" + nodeConnectorIdOld +
296 ", fcNodeConnectorOld=" + fcNodeConnectorOld +
297 ", interfaceName='" + interfaceName + '\'' +
302 public static List<InterfaceChildEntry> getInterfaceChildEntries(DataBroker dataBroker, String interfaceName) {
303 InterfaceParentEntry interfaceParentEntry =
304 InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceName, dataBroker);
305 if (interfaceParentEntry != null && interfaceParentEntry.getInterfaceChildEntry() != null) {
306 return interfaceParentEntry.getInterfaceChildEntry();
308 return new ArrayList<>();