Bump version odlparent->6.0.0,mdsal->5.0.3
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / recovery / impl / ItmTepInstanceRecoveryHandler.java
index 7be41f6c25e233e83e58c59d83a8733d8c75293d..8a9cdf236c3dc1ce021c419389644f68ae8104f9 100644 (file)
@@ -7,14 +7,23 @@
  */
 package org.opendaylight.genius.itm.recovery.impl;
 
+import java.time.Duration;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
+import org.opendaylight.genius.itm.cache.OfEndPointCache;
 import org.opendaylight.genius.itm.cache.OvsBridgeEntryCache;
 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
 import org.opendaylight.genius.itm.cache.TunnelStateCache;
@@ -28,19 +37,24 @@ import org.opendaylight.genius.itm.impl.ItmUtils;
 import org.opendaylight.genius.itm.impl.TunnelMonitoringConfig;
 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.genius.srm.ServiceRecoveryInterface;
-import org.opendaylight.genius.srm.ServiceRecoveryRegistry;
 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.serviceutils.srm.ServiceRecoveryInterface;
+import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTeps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpns;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.srm.types.rev170711.GeniusItmTep;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Vteps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.serviceutils.srm.types.rev180626.GeniusItmTep;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -58,8 +72,10 @@ public class ItmTepInstanceRecoveryHandler implements ServiceRecoveryInterface {
     private final ItmConfig itmConfig;
     private final EntityOwnershipUtils entityOwnershipUtils;
     private final IMdsalApiManager imdsalApiManager;
-    private String tzName;
-    private TransportZone transportZone;
+    private final DataTreeEventCallbackRegistrar eventCallbacks;
+    private final ManagedNewTransactionRunner txRunner;
+    private final IInterfaceManager interfaceManager;
+    private final DpnTepStateCache dpnTepStateCache;
 
     @Inject
     public ItmTepInstanceRecoveryHandler(DataBroker dataBroker,
@@ -73,22 +89,28 @@ public class ItmTepInstanceRecoveryHandler implements ServiceRecoveryInterface {
                                          OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
                                          IInterfaceManager interfaceManager,
                                          ServiceRecoveryRegistry serviceRecoveryRegistry,
-                                         EntityOwnershipUtils entityOwnershipUtils) {
+                                         EntityOwnershipUtils entityOwnershipUtils,
+                                         OfEndPointCache ofEndPointCache,
+                                         DataTreeEventCallbackRegistrar eventCallbacks) {
         this.dataBroker = dataBroker;
         this.itmConfig = itmConfig;
         this.imdsalApiManager = imdsalApiMgr;
         this.jobCoordinator = jobCoordinator;
         this.dpntePsInfoCache = dpntePsInfoCache;
         this.entityOwnershipUtils = entityOwnershipUtils;
+        this.eventCallbacks = eventCallbacks;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.itmInternalTunnelAddWorker = new ItmInternalTunnelAddWorker(dataBroker, jobCoordinator,
-                tunnelMonitoringConfig, itmConfig, directTunnelUtils, interfaceManager, ovsBridgeRefEntryCache);
-        this.itmExternalTunnelAddWorker = new ItmExternalTunnelAddWorker(dataBroker, itmConfig,
+                tunnelMonitoringConfig, itmConfig, directTunnelUtils, interfaceManager,
+                ovsBridgeRefEntryCache, ofEndPointCache, eventCallbacks);
+        this.itmExternalTunnelAddWorker = new ItmExternalTunnelAddWorker(itmConfig,
                 dpntePsInfoCache);
         this.itmInternalTunnelDeleteWorker = new ItmInternalTunnelDeleteWorker(dataBroker, jobCoordinator,
                 tunnelMonitoringConfig, interfaceManager, dpnTepStateCache, ovsBridgeEntryCache,
-                ovsBridgeRefEntryCache, tunnelStateCache,
-                directTunnelUtils);
+                ovsBridgeRefEntryCache, tunnelStateCache, directTunnelUtils, ofEndPointCache, itmConfig);
         serviceRecoveryRegistry.registerServiceRecoveryRegistry(getServiceRegistryKey(), this);
+        this.interfaceManager = interfaceManager;
+        this.dpnTepStateCache = dpnTepStateCache;
     }
 
     private String getServiceRegistryKey() {
@@ -110,72 +132,115 @@ public class ItmTepInstanceRecoveryHandler implements ServiceRecoveryInterface {
 
     private void recoverTep(String entityId) throws InterruptedException {
         List<DPNTEPsInfo> tepsToRecover = new ArrayList<>();
-        DPNTEPsInfo dpnTepsToRecover = extractDPNTepsInfo(entityId);
+        String[] params = entityId.split(":");
+        if (params.length < 2) {
+            LOG.error("Not enough arguments..Exiting...");
+        } else if (params.length > 2) {
+            LOG.info("Ignoring extra parameter and proceeding...");
+        }
+        String tzName = params[0];
+        String ipAddress = params[1];
+        TransportZone oldTz = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
+        DPNTEPsInfo dpnTepsToRecover = extractDPNTepsInfo(tzName, ipAddress, oldTz);
         if (dpnTepsToRecover == null) {
             LOG.error("Please Enter appropriate arguments for Tep Recovery.");
             return;
         } else {
             tepsToRecover.add(dpnTepsToRecover);
-            // Delete the transportZone and re create it
-            // Get the transport zone from the transport zone name
-            TransportZone oldTz = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
+            //List of Internel tunnels
+            List<InternalTunnel> tunnelList = ItmUtils.getInternalTunnelsFromCache(dataBroker);
+            List<String> interfaceListToRecover = new ArrayList<>();
+            LOG.debug("List of tunnel interfaces: {}" , tunnelList);
+
             if (oldTz != null) {
-                ItmTepRemoveWorker tepRemoveWorker = new ItmTepRemoveWorker(tepsToRecover, null, oldTz,
-                        dataBroker, imdsalApiManager, itmInternalTunnelDeleteWorker, dpntePsInfoCache);
                 LOG.trace("Deleting transportzone {}", tzName);
+                ItmTepRemoveWorker tepRemoveWorker = new ItmTepRemoveWorker(tepsToRecover, null, oldTz,
+                        imdsalApiManager, itmInternalTunnelDeleteWorker, dpntePsInfoCache, txRunner, itmConfig);
                 jobCoordinator.enqueueJob(tzName, tepRemoveWorker);
-                ItmTepAddWorker tepAddWorker = new ItmTepAddWorker(tepsToRecover, null, dataBroker,
-                        imdsalApiManager, itmConfig, itmInternalTunnelAddWorker, itmExternalTunnelAddWorker,
-                        dpntePsInfoCache);
-                LOG.trace("Re-creating transportzone {}", tzName);
-                jobCoordinator.enqueueJob(tzName, tepAddWorker);
+                AtomicInteger eventCallbackCount = new AtomicInteger(0);
+                AtomicInteger eventRegistrationCount = new AtomicInteger(0);
+                if (interfaceManager.isItmDirectTunnelsEnabled()) {
+                    Collection<DpnsTeps> dpnsTeps = dpnTepStateCache.getAllPresent();
+                    for (DpnsTeps dpnTep : dpnsTeps) {
+                        List<RemoteDpns> rmtdpns = dpnTep.getRemoteDpns();
+                        for (RemoteDpns remoteDpn : rmtdpns) {
+                            if (remoteDpn.getDestinationDpnId().equals(dpnTepsToRecover.getDPNID())
+                                    || dpnTep.getSourceDpnId().equals(dpnTepsToRecover.getDPNID())) {
+                                eventRegistrationCount.incrementAndGet();
+                                interfaceListToRecover.add(remoteDpn.getTunnelName());
+                            }
+                        }
+                    }
+                    LOG.trace("List of tunnels to be recovered : {}", interfaceListToRecover);
+                } else {
+                    tunnelList.stream().filter(internalTunnel -> Objects.equals(internalTunnel
+                            .getDestinationDPN(), dpnTepsToRecover.getDPNID()) || Objects.equals(
+                            internalTunnel.getSourceDPN(), dpnTepsToRecover.getDPNID())).forEach(internalTunnel -> {
+                                eventRegistrationCount.incrementAndGet();
+                                interfaceListToRecover.add(String.valueOf(internalTunnel.getTunnelInterfaceNames()));
+                            });
+                }
+
+                if (!interfaceListToRecover.isEmpty()) {
+                    interfaceListToRecover.forEach(interfaceName -> {
+                        StateTunnelListKey tlKey = new StateTunnelListKey(interfaceName);
+                        LOG.trace("TunnelStateKey: {} for interface: {}", tlKey, interfaceName);
+                        InstanceIdentifier<StateTunnelList> stListId = ItmUtils.buildStateTunnelListId(tlKey);
+                        eventCallbacks.onRemove(LogicalDatastoreType.OPERATIONAL, stListId, (unused) -> {
+                            LOG.trace("callback event for a delete {} interface instance....", stListId);
+                            // recreating the transportZone
+                            recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
+                            return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
+                        }, Duration.ofMillis(5000), (id) -> {
+                                LOG.trace("event callback timed out for {} tunnel interface ", interfaceName);
+                                recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
+                            });
+                    });
+                } else {
+                    recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
+                }
             }
         }
     }
 
-    private DPNTEPsInfo extractDPNTepsInfo(String entityId) {
-
-        String[] params = entityId.split(":");
-        if (params.length < 2) {
-            LOG.error("Not enough arguments..Exiting...");
-            return null;
-        } else if (params.length > 2) {
-            LOG.info("Ignoring extra parameter and proceeding...");
+    private void recreateTEP(String tzName, List tepts, AtomicInteger eventCallbackCount, int registeredEventSize) {
+        eventCallbackCount.incrementAndGet();
+        if (eventCallbackCount.intValue() == registeredEventSize || registeredEventSize == 0) {
+            LOG.info("Re-creating TEP {}", tzName);
+            ItmTepAddWorker tepAddWorker = new ItmTepAddWorker(tepts, null, dataBroker, imdsalApiManager,
+                    itmInternalTunnelAddWorker, itmExternalTunnelAddWorker);
+            jobCoordinator.enqueueJob(tzName, tepAddWorker);
         }
+    }
 
-        // ToDo:- Need to add more validations
-        this.tzName = params[0];
-        String ipAddress = params[1];
+    private DPNTEPsInfo extractDPNTepsInfo(String tzName, String ipAddress, TransportZone transportZone) {
 
-        transportZone = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
         if (transportZone == null) {
             LOG.error("Transportzone name {} is not valid.", tzName);
             return null;
         }
 
-        for (Subnets sub : transportZone.getSubnets()) {
-            if (sub.getVteps() == null || sub.getVteps().isEmpty()) {
-                LOG.error("Transport Zone {} subnet {} has no vteps", transportZone.getZoneName(), sub.getPrefix());
-            }
-            for (Vteps vtep : sub.getVteps()) {
-                if (ipAddress.equals(String.valueOf(vtep.getIpAddress().getValue()))) {
-
-                    List<TzMembership> zones = ItmUtils.createTransportZoneMembership(tzName);
-                    LOG.trace("Transportzone {} found match for tep {} to be recovered", transportZone.getZoneName(),
-                            ipAddress);
-
-                    //OfTunnels is false byDefault
-                    TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(vtep.getDpnId(),
-                        IpAddressBuilder.getDefaultInstance(ipAddress), vtep.getPortname(), false, sub.getVlanId(),
-                            sub.getPrefix(), sub.getGatewayIp(), zones,transportZone.getTunnelType(),
-                            itmConfig.getDefaultTunnelTos());
-
-                    List<TunnelEndPoints> teps = new ArrayList<>();
-                    teps.add(tunnelEndPoints);
-                    return ItmUtils.createDPNTepInfo(vtep.getDpnId(), teps);
-                }
+        String portName = itmConfig.getPortname() == null ? ITMConstants.DUMMY_PORT : itmConfig.getPortname();
+        int vlanId = itmConfig.getVlanId() != null ? itmConfig.getVlanId().toJava() : ITMConstants.DUMMY_VLANID;
+
+        for (Vteps vtep : transportZone.getVteps()) {
+            if (ipAddress.equals(vtep.getIpAddress().stringValue())) {
+
+                List<TzMembership> zones = ItmUtils.createTransportZoneMembership(tzName);
+                LOG.trace("Transportzone {} found match for tep {} to be recovered", transportZone.getZoneName(),
+                        ipAddress);
+
+                //OfTunnels is false byDefault
+                TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(vtep.getDpnId(),
+                        IpAddressBuilder.getDefaultInstance(ipAddress), portName, false,
+                        vlanId, zones, transportZone.getTunnelType(),
+                        itmConfig.getDefaultTunnelTos());
+
+                List<TunnelEndPoints> teps = new ArrayList<>();
+                teps.add(tunnelEndPoints);
+                return ItmUtils.createDPNTepInfo(vtep.getDpnId(), teps);
             }
         }
         return null;
     }
-}
\ No newline at end of file
+}