30f8c34596e2f96a9d882bcae9c87f6747bdab46
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / listeners / InterfaceInventoryStateListener.java
1 /*
2  * Copyright (c) 2016, 2018 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.genius.interfacemanager.listeners;
9
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
12
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.MoreExecutors;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Objects;
21 import java.util.Optional;
22 import java.util.concurrent.Callable;
23 import java.util.concurrent.ExecutionException;
24 import javax.inject.Inject;
25 import javax.inject.Singleton;
26 import org.apache.aries.blueprint.annotation.service.Reference;
27 import org.checkerframework.checker.nullness.qual.Nullable;
28 import org.opendaylight.genius.infra.Datastore.Configuration;
29 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
30 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
31 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
32 import org.opendaylight.genius.interfacemanager.IfmConstants;
33 import org.opendaylight.genius.interfacemanager.IfmUtil;
34 import org.opendaylight.genius.interfacemanager.InterfacemgrProvider;
35 import org.opendaylight.genius.interfacemanager.commons.AlivenessMonitorUtils;
36 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
37 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
38 import org.opendaylight.genius.interfacemanager.recovery.impl.InterfaceServiceRecoveryHandler;
39 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceStateAddHelper;
40 import org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers.OvsInterfaceStateUpdateHelper;
41 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
42 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
43 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
44 import org.opendaylight.infrautils.utils.concurrent.Executors;
45 import org.opendaylight.infrautils.utils.function.InterruptibleCheckedConsumer;
46 import org.opendaylight.mdsal.binding.api.DataBroker;
47 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
48 import org.opendaylight.serviceutils.srm.RecoverableListener;
49 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
50 import org.opendaylight.serviceutils.tools.listener.AbstractClusteredAsyncDataTreeChangeListener;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortReason;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntry;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
63 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
64 import org.opendaylight.yangtools.yang.common.Uint64;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
67
68
69 /**
70  * This Class is a Data Change Listener for FlowCapableNodeConnector updates.
71  * This creates an entry in the interface-state OperDS for every node-connector
72  * used.
73  *
74  * <p>
75  * NOTE: This class just creates an ifstate entry whose interface-name will be
76  * the same as the node-connector portname. If PortName is not unique across
77  * DPNs, this implementation can have problems.
78  */
79 @Singleton
80 public class InterfaceInventoryStateListener
81         extends AbstractClusteredAsyncDataTreeChangeListener<FlowCapableNodeConnector>
82         implements RecoverableListener {
83
84     private static final Logger LOG = LoggerFactory.getLogger(InterfaceInventoryStateListener.class);
85     private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
86
87     private final DataBroker dataBroker;
88     private final ManagedNewTransactionRunner txRunner;
89     private final IdManagerService idManager;
90     private final EntityOwnershipUtils entityOwnershipUtils;
91     private final JobCoordinator coordinator;
92     private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
93     private final AlivenessMonitorUtils alivenessMonitorUtils;
94     private final OvsInterfaceStateUpdateHelper ovsInterfaceStateUpdateHelper;
95     private final OvsInterfaceStateAddHelper ovsInterfaceStateAddHelper;
96     private final InterfaceMetaUtils interfaceMetaUtils;
97     private final PortNameCache portNameCache;
98     private final InterfacemgrProvider interfacemgrProvider;
99
100     @Inject
101     public InterfaceInventoryStateListener(@Reference final DataBroker dataBroker,
102                                            final IdManagerService idManagerService,
103                                            final EntityOwnershipUtils entityOwnershipUtils,
104                                            @Reference final JobCoordinator coordinator,
105                                            final InterfaceManagerCommonUtils interfaceManagerCommonUtils,
106                                            final OvsInterfaceStateAddHelper ovsInterfaceStateAddHelper,
107                                            final OvsInterfaceStateUpdateHelper ovsInterfaceStateUpdateHelper,
108                                            final AlivenessMonitorUtils alivenessMonitorUtils,
109                                            final InterfaceMetaUtils interfaceMetaUtils,
110                                            final PortNameCache portNameCache,
111                                            final InterfaceServiceRecoveryHandler interfaceServiceRecoveryHandler,
112                                            @Reference final ServiceRecoveryRegistry serviceRecoveryRegistry,
113                                            final InterfacemgrProvider interfacemgrProvider) {
114         super(dataBroker, LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class)
115                         .child(Node.class).child(NodeConnector.class)
116                         .augmentation(FlowCapableNodeConnector.class),
117                 Executors.newSingleThreadExecutor("InterfaceInventoryStateListener", LOG));
118         this.dataBroker = dataBroker;
119         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
120         this.idManager = idManagerService;
121         this.entityOwnershipUtils = entityOwnershipUtils;
122         this.coordinator = coordinator;
123         this.interfaceManagerCommonUtils = interfaceManagerCommonUtils;
124         this.alivenessMonitorUtils = alivenessMonitorUtils;
125         this.ovsInterfaceStateUpdateHelper = ovsInterfaceStateUpdateHelper;
126         this.ovsInterfaceStateAddHelper = ovsInterfaceStateAddHelper;
127         this.interfaceMetaUtils = interfaceMetaUtils;
128         this.portNameCache = portNameCache;
129         this.interfacemgrProvider = interfacemgrProvider;
130         serviceRecoveryRegistry.addRecoverableListener(interfaceServiceRecoveryHandler.buildServiceRegistryKey(),
131                 this);
132     }
133
134     @Override
135     public void registerListener() {
136         super.register();
137     }
138
139     @Override
140     public void deregisterListener() {
141         close();
142     }
143
144     @Override
145     public void remove(InstanceIdentifier<FlowCapableNodeConnector> key,
146                           FlowCapableNodeConnector flowCapableNodeConnectorOld) {
147         String interfaceName = flowCapableNodeConnectorOld.getName();
148         EVENT_LOGGER.debug("IFM-InterfaceInventoryState,REMOVE {}", interfaceName);
149         if (interfacemgrProvider.isItmDirectTunnelsEnabled()
150             && InterfaceManagerCommonUtils.isTunnelPort(interfaceName)
151             && interfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName) == null) {
152             LOG.debug("ITM Direct Tunnels is enabled, node connector removed event for"
153                     + " internal tunnel {}", interfaceName);
154             return;
155         }
156
157         NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class))
158                 .getId();
159         LOG.trace("Removing entry for port id {} from map",nodeConnectorId.getValue());
160         portNameCache.remove(nodeConnectorId.getValue());
161
162
163         if (!entityOwnershipUtils.isEntityOwner(IfmConstants.INTERFACE_CONFIG_ENTITY,
164                 IfmConstants.INTERFACE_CONFIG_ENTITY)) {
165             return;
166         }
167
168         LOG.debug("Received NodeConnector Remove Event: {}, {}", key, flowCapableNodeConnectorOld);
169         String portName = InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId,
170             flowCapableNodeConnectorOld.getName());
171         EVENT_LOGGER.debug("IFM-InterfaceInventoryState Entity Owner,REMOVE {},{}", portName,
172                 nodeConnectorId.getValue());
173
174         remove(nodeConnectorId, null, flowCapableNodeConnectorOld, portName, true);
175     }
176
177     private void remove(NodeConnectorId nodeConnectorIdNew, NodeConnectorId nodeConnectorIdOld,
178                         FlowCapableNodeConnector fcNodeConnectorNew, String portName, boolean isNetworkEvent) {
179         InterfaceStateRemoveWorker portStateRemoveWorker = new InterfaceStateRemoveWorker(idManager,
180                 nodeConnectorIdNew, nodeConnectorIdOld, fcNodeConnectorNew, portName,
181                 isNetworkEvent, true);
182         coordinator.enqueueJob(portName, portStateRemoveWorker, IfmConstants.JOB_MAX_RETRIES);
183     }
184
185     @Override
186     public void update(InstanceIdentifier<FlowCapableNodeConnector> key, FlowCapableNodeConnector fcNodeConnectorOld,
187         FlowCapableNodeConnector fcNodeConnectorNew) {
188         String interfaceName = fcNodeConnectorNew.getName();
189         EVENT_LOGGER.debug("IFM-InterfaceInventoryState,UPDATE {},{}", fcNodeConnectorNew.getName(),
190                 fcNodeConnectorNew.getReason());
191         if (interfacemgrProvider.isItmDirectTunnelsEnabled()
192             && InterfaceManagerCommonUtils.isTunnelPort(interfaceName)
193             && interfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName) == null) {
194             LOG.debug("ITM Direct Tunnels is enabled, hence ignoring node connector Update event for"
195                     + " internal tunnel {}", interfaceName);
196             return;
197         }
198
199
200         if (fcNodeConnectorNew.getReason() == PortReason.Delete
201                 || !entityOwnershipUtils.isEntityOwner(IfmConstants.INTERFACE_CONFIG_ENTITY,
202                 IfmConstants.INTERFACE_CONFIG_ENTITY)) {
203             return;
204         }
205
206         LOG.debug("Received NodeConnector Update Event: {}, {}, {}", key, fcNodeConnectorOld, fcNodeConnectorNew);
207         NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
208         String portName = InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId,
209                 fcNodeConnectorNew.getName());
210         EVENT_LOGGER.debug("IFM-InterfaceInventoryState Entity Owner,UPDATE {},{}", portName,
211                 nodeConnectorId.getValue());
212
213         InterfaceStateUpdateWorker portStateUpdateWorker = new InterfaceStateUpdateWorker(key, fcNodeConnectorOld,
214             fcNodeConnectorNew, portName);
215         coordinator.enqueueJob(portName, portStateUpdateWorker, IfmConstants.JOB_MAX_RETRIES);
216     }
217
218     @Override
219     public void add(InstanceIdentifier<FlowCapableNodeConnector> key, FlowCapableNodeConnector fcNodeConnectorNew) {
220         String interfaceName = fcNodeConnectorNew.getName();
221         EVENT_LOGGER.debug("IFM-InterfaceInventoryState,ADD {}", interfaceName);
222         if (interfacemgrProvider.isItmDirectTunnelsEnabled()
223             && InterfaceManagerCommonUtils.isTunnelPort(interfaceName)
224             && interfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName) == null) {
225             LOG.debug("ITM Direct Tunnels is enabled, ignoring node connector add for"
226                     + " internal tunnel {}", interfaceName);
227             return;
228         }
229
230         NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class))
231                 .getId();
232         LOG.trace("Adding entry for portid {} portname {} in map", nodeConnectorId.getValue(),
233                 fcNodeConnectorNew.getName());
234         portNameCache.put(nodeConnectorId.getValue(),fcNodeConnectorNew.getName());
235         if (!entityOwnershipUtils.isEntityOwner(IfmConstants.INTERFACE_CONFIG_ENTITY,
236                 IfmConstants.INTERFACE_CONFIG_ENTITY)) {
237             return;
238         }
239
240         LOG.debug("Received NodeConnector Add Event: {}, {}", key, fcNodeConnectorNew);
241         String portName = InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId,
242             fcNodeConnectorNew.getName());
243         EVENT_LOGGER.debug("IFM-InterfaceInventoryState Entity Owner,ADD {},{}", portName, nodeConnectorId.getValue());
244
245         if (InterfaceManagerCommonUtils.isNovaPort(portName) || InterfaceManagerCommonUtils.isK8SPort(portName)) {
246             NodeConnectorId nodeConnectorIdOld = null;
247             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
248                     .ietf.interfaces.rev140508.interfaces.state.Interface interfaceState = interfaceManagerCommonUtils
249                     .getInterfaceState(interfaceName);
250             if (interfaceState != null) {
251                 List<String> ofportIds = interfaceState.getLowerLayerIf();
252                 nodeConnectorIdOld = new NodeConnectorId(ofportIds.get(0));
253             }
254             if (nodeConnectorIdOld != null && !nodeConnectorId.equals(nodeConnectorIdOld)) {
255                 Uint64 dpnIdOld = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorIdOld);
256                 Uint64 dpnIdNew = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
257                 if (!Objects.equals(dpnIdOld, dpnIdNew)) {
258                     if (fcNodeConnectorNew.getReason() != PortReason.Add
259                             && interfaceState.getOperStatus()
260                             != Interface.OperStatus.Unknown) {
261                         LOG.error("Dropping Port update event for {}, as DPN id is changed from {} to {}",
262                             fcNodeConnectorNew.getName(), dpnIdOld, dpnIdNew);
263                         return;
264                     }
265                 } else {
266                     LOG.warn("Port number update detected for {}", fcNodeConnectorNew.getName());
267                 }
268                 //VM Migration or Port Number Update: Delete existing interface entry for older DPN
269                 LOG.trace("Removing entry for port id {} from map",nodeConnectorIdOld.getValue());
270                 portNameCache.remove(nodeConnectorIdOld.getValue());
271                 EVENT_LOGGER.debug("IFM-VMMigration,{}", portName);
272                 LOG.debug("Triggering NodeConnector Remove Event for the interface: {}, {}, {}", portName,
273                     nodeConnectorId, nodeConnectorIdOld);
274                 remove(nodeConnectorId, nodeConnectorIdOld, fcNodeConnectorNew, portName, false);
275                 // Adding a delay of 10sec for VM migration, so applications will have sufficient time
276                 // for processing remove before add
277                 try {
278                     Thread.sleep(IfmConstants.DELAY_TIME_IN_MILLISECOND);
279                 } catch (final InterruptedException e) {
280                     LOG.error("Error while waiting for the vm migration remove events to get processed");
281                 }
282             }
283         }
284
285         InterfaceStateAddWorker ifStateAddWorker = new InterfaceStateAddWorker(idManager, nodeConnectorId,
286             fcNodeConnectorNew, portName);
287         coordinator.enqueueJob(portName, ifStateAddWorker, IfmConstants.JOB_MAX_RETRIES);
288     }
289
290
291     private class InterfaceStateAddWorker implements Callable {
292         private final NodeConnectorId nodeConnectorId;
293         private final FlowCapableNodeConnector fcNodeConnectorNew;
294         private final String interfaceName;
295         private final IdManagerService idManager;
296
297         InterfaceStateAddWorker(IdManagerService idManager, NodeConnectorId nodeConnectorId,
298                                 FlowCapableNodeConnector fcNodeConnectorNew, String portName) {
299             this.nodeConnectorId = nodeConnectorId;
300             this.fcNodeConnectorNew = fcNodeConnectorNew;
301             this.interfaceName = portName;
302             this.idManager = idManager;
303         }
304
305         @Override
306         public Object call() {
307             List<ListenableFuture<Void>> futures = ovsInterfaceStateAddHelper.addState(nodeConnectorId,
308                     interfaceName, fcNodeConnectorNew);
309             Map<InterfaceChildEntryKey, InterfaceChildEntry> interfaceChildEntries =
310                     getInterfaceChildEntries(interfaceName);
311             for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries.values()) {
312                 InterfaceStateAddWorker interfaceStateAddWorker = new InterfaceStateAddWorker(idManager,
313                         nodeConnectorId, fcNodeConnectorNew, interfaceChildEntry.getChildInterface());
314                 coordinator.enqueueJob(interfaceName, interfaceStateAddWorker);
315             }
316             return futures;
317         }
318
319         @Override
320         public String toString() {
321             return "InterfaceStateAddWorker{" + "nodeConnectorId=" + nodeConnectorId + ", fcNodeConnectorNew="
322                     + fcNodeConnectorNew + ", interfaceName='" + interfaceName + '\'' + '}';
323         }
324     }
325
326     private class InterfaceStateUpdateWorker implements Callable<List<? extends ListenableFuture<?>>> {
327         private final InstanceIdentifier<FlowCapableNodeConnector> key;
328         private final FlowCapableNodeConnector fcNodeConnectorOld;
329         private final FlowCapableNodeConnector fcNodeConnectorNew;
330         private final String interfaceName;
331
332         InterfaceStateUpdateWorker(InstanceIdentifier<FlowCapableNodeConnector> key,
333                                    FlowCapableNodeConnector fcNodeConnectorOld,
334                                    FlowCapableNodeConnector fcNodeConnectorNew,
335                                    String portName) {
336             this.key = key;
337             this.fcNodeConnectorOld = fcNodeConnectorOld;
338             this.fcNodeConnectorNew = fcNodeConnectorNew;
339             this.interfaceName = portName;
340         }
341
342         @Override
343         public List<ListenableFuture<Void>> call() {
344             List<ListenableFuture<Void>> futures = ovsInterfaceStateUpdateHelper.updateState(
345                     interfaceName, fcNodeConnectorNew, fcNodeConnectorOld);
346             Map<InterfaceChildEntryKey, InterfaceChildEntry> interfaceChildEntries =
347                     getInterfaceChildEntries(interfaceName);
348             for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries.values()) {
349                 InterfaceStateUpdateWorker interfaceStateUpdateWorker = new InterfaceStateUpdateWorker(key,
350                         fcNodeConnectorOld, fcNodeConnectorNew, interfaceChildEntry.getChildInterface());
351                 coordinator.enqueueJob(interfaceName, interfaceStateUpdateWorker);
352             }
353             return futures;
354         }
355
356         @Override
357         public String toString() {
358             return "InterfaceStateUpdateWorker{" + "key=" + key + ", fcNodeConnectorOld=" + fcNodeConnectorOld
359                     + ", fcNodeConnectorNew=" + fcNodeConnectorNew + ", interfaceName='" + interfaceName + '\'' + '}';
360         }
361     }
362
363     private class InterfaceStateRemoveWorker implements Callable<List<? extends ListenableFuture<?>>> {
364         private final NodeConnectorId nodeConnectorIdNew;
365         private NodeConnectorId nodeConnectorIdOld;
366         private final FlowCapableNodeConnector fcNodeConnectorOld;
367         private final String interfaceName;
368         private final IdManagerService idManager;
369         private final boolean isNetworkEvent;
370         private final boolean isParentInterface;
371
372         InterfaceStateRemoveWorker(IdManagerService idManager, NodeConnectorId nodeConnectorIdNew,
373                                    NodeConnectorId nodeConnectorIdOld,
374                                    FlowCapableNodeConnector fcNodeConnectorOld, String interfaceName,
375                                    boolean isNetworkEvent,
376                                    boolean isParentInterface) {
377             this.nodeConnectorIdNew = nodeConnectorIdNew;
378             this.nodeConnectorIdOld = nodeConnectorIdOld;
379             this.fcNodeConnectorOld = fcNodeConnectorOld;
380             this.interfaceName = interfaceName;
381             this.idManager = idManager;
382             this.isNetworkEvent = isNetworkEvent;
383             this.isParentInterface = isParentInterface;
384         }
385
386         @Override
387         public List<ListenableFuture<Void>> call() {
388             // VM Migration: Skip OFPPR_DELETE event received after OFPPR_ADD
389             // for same interface from Older DPN
390             if (isParentInterface && isNetworkEvent) {
391                 nodeConnectorIdOld = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(interfaceName,
392                         interfaceManagerCommonUtils);
393                 if (nodeConnectorIdOld != null && !nodeConnectorIdNew.equals(nodeConnectorIdOld)) {
394                     LOG.debug("Dropping the NodeConnector Remove Event for the interface: {}, {}, {}", interfaceName,
395                             nodeConnectorIdNew, nodeConnectorIdOld);
396                     return Collections.emptyList();
397                 }
398             }
399
400             List<ListenableFuture<Void>> futures = removeInterfaceStateConfiguration();
401
402             Map<InterfaceChildEntryKey, InterfaceChildEntry> interfaceChildEntries =
403                     getInterfaceChildEntries(interfaceName);
404             for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries.values()) {
405                 // Fetch all interfaces on this port and trigger remove worker
406                 // for each of them
407                 InterfaceStateRemoveWorker interfaceStateRemoveWorker = new InterfaceStateRemoveWorker(idManager,
408                         nodeConnectorIdNew, nodeConnectorIdOld, fcNodeConnectorOld,
409                         interfaceChildEntry.getChildInterface(), isNetworkEvent, false);
410                 coordinator.enqueueJob(interfaceName, interfaceStateRemoveWorker);
411             }
412             return futures;
413         }
414
415         private List<ListenableFuture<Void>> removeInterfaceStateConfiguration() {
416             List<ListenableFuture<Void>> futures = new ArrayList<>();
417
418             //VM Migration: Use old nodeConnectorId to delete the interface entry
419             NodeConnectorId nodeConnectorId = nodeConnectorIdOld != null
420                     && !nodeConnectorIdNew.equals(nodeConnectorIdOld) ? nodeConnectorIdOld : nodeConnectorIdNew;
421             // delete the port entry from interface operational DS
422             Uint64 dpId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
423
424             futures.add(txRunner.applyWithNewTransactionChainAndClose(txChain ->
425                 txChain.applyWithNewReadWriteTransactionAndSubmit(OPERATIONAL, operTx -> {
426                     // In a genuine port delete scenario, the reason will be there in the incoming event, for all
427                     // remaining
428                     // cases treat the event as DPN disconnect, if old and new ports are same. Else, this is a VM
429                     // migration
430                     // scenario, and should be treated as port removal.
431                     LOG.debug("Removing interface state information for interface: {}", interfaceName);
432                     if (fcNodeConnectorOld.getReason() != PortReason.Delete
433                         && nodeConnectorIdNew.equals(nodeConnectorIdOld)) {
434                         //Remove event is because of connection lost between controller and switch, or switch shutdown.
435                         // Hence, don't remove the interface but set the status as "unknown"
436                         ovsInterfaceStateUpdateHelper.updateInterfaceStateOnNodeRemove(interfaceName,
437                             fcNodeConnectorOld,
438                             operTx);
439                     } else {
440                         EVENT_LOGGER.debug("IFM-OvsInterfaceState,REMOVE {}", interfaceName);
441                         InterfaceManagerCommonUtils.deleteStateEntry(operTx, interfaceName);
442                         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
443                             .Interface iface = interfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName);
444
445                         if (InterfaceManagerCommonUtils.isTunnelInterface(iface)) {
446                             // If this interface is a tunnel interface, remove the tunnel ingress flow and stop LLDP
447                             // monitoring
448                             interfaceMetaUtils.removeLportTagInterfaceMap(operTx, interfaceName);
449                             return Optional.of((InterruptibleCheckedConsumer<TypedReadWriteTransaction<Configuration>,
450                                 ExecutionException>) confTx -> handleTunnelMonitoringRemoval(confTx, dpId,
451                                 iface.getName(),
452                                 iface.augmentation(IfTunnel.class)));
453                         }
454                         // remove ingress flow only for northbound configured interfaces
455                         // skip this check for non-unique ports(Ex: br-int,br-ex)
456
457                         if (iface != null) {
458                             FlowBasedServicesUtils.removeIngressFlow(interfaceName, dpId, txRunner, futures);
459                             IfmUtil.unbindService(txRunner, coordinator, iface.getName(),
460                                     FlowBasedServicesUtils.buildDefaultServiceId(iface.getName()));
461                             EVENT_LOGGER.debug("IFM-InterfaceState, REMOVE, IngressFlow {}", interfaceName);
462                         }
463                         // Delete the Vpn Interface from DpnToInterface Op DS.
464                         InterfaceManagerCommonUtils.deleteDpnToInterface(dpId, interfaceName, operTx);
465                     }
466                     return Optional.empty();
467                 }).transform((@Nullable Optional<?> optionalJob) -> {
468                     if (optionalJob != null && optionalJob.isPresent()) {
469                         txChain.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
470                             (InterruptibleCheckedConsumer<TypedReadWriteTransaction<Configuration>, ?
471                                 extends Exception>) optionalJob.get());
472                     }
473                     return null;
474                 }, MoreExecutors.directExecutor())));
475             return futures;
476         }
477
478         private void handleTunnelMonitoringRemoval(TypedReadWriteTransaction<Configuration> tx, Uint64 dpId,
479             String removedInterfaceName, IfTunnel ifTunnel) throws ExecutionException, InterruptedException {
480             interfaceManagerCommonUtils.removeTunnelIngressFlow(tx, ifTunnel, dpId, removedInterfaceName);
481
482             IfmUtil.unbindService(txRunner, coordinator, removedInterfaceName,
483                     FlowBasedServicesUtils.buildDefaultServiceId(removedInterfaceName));
484
485             alivenessMonitorUtils.stopLLDPMonitoring(ifTunnel, removedInterfaceName);
486         }
487
488         @Override
489         public String toString() {
490             return "InterfaceStateRemoveWorker{" + "nodeConnectorIdNew=" + nodeConnectorIdNew + ", nodeConnectorIdOld="
491                     + nodeConnectorIdOld + ", fcNodeConnectorOld=" + fcNodeConnectorOld + ", interfaceName='"
492                     + interfaceName + '\'' + '}';
493         }
494     }
495
496     public Map<InterfaceChildEntryKey, InterfaceChildEntry> getInterfaceChildEntries(String interfaceName) {
497         InterfaceParentEntry interfaceParentEntry =
498                 interfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceName);
499         if (interfaceParentEntry != null && interfaceParentEntry.getInterfaceChildEntry() != null) {
500             return interfaceParentEntry.getInterfaceChildEntry();
501         }
502         return new HashMap<>();
503     }
504 }