* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
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;
import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker;
import org.opendaylight.genius.itm.confighelpers.ItmInternalTunnelAddWorker;
import org.opendaylight.genius.itm.confighelpers.ItmInternalTunnelDeleteWorker;
import org.opendaylight.genius.itm.globals.ITMConstants;
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.mdsal.eos.binding.api.EntityOwnershipService;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+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;
private final ItmInternalTunnelDeleteWorker itmInternalTunnelDeleteWorker;
private final ItmConfig itmConfig;
private final EntityOwnershipUtils entityOwnershipUtils;
- private final EntityOwnershipService entityOwnershipService;
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,
IMdsalApiManager imdsalApiMgr,
JobCoordinator jobCoordinator,
TunnelMonitoringConfig tunnelMonitoringConfig,
- DPNTEPsInfoCache dpntePsInfoCache,
+ DPNTEPsInfoCache dpntePsInfoCache, TunnelStateCache tunnelStateCache,
+ DirectTunnelUtils directTunnelUtils, DpnTepStateCache dpnTepStateCache,
+ OvsBridgeEntryCache ovsBridgeEntryCache,
+ OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
+ IInterfaceManager interfaceManager,
ServiceRecoveryRegistry serviceRecoveryRegistry,
EntityOwnershipUtils entityOwnershipUtils,
- EntityOwnershipService entityOwnershipService) {
+ OfEndPointCache ofEndPointCache,
+ DataTreeEventCallbackRegistrar eventCallbacks) {
this.dataBroker = dataBroker;
this.itmConfig = itmConfig;
this.imdsalApiManager = imdsalApiMgr;
this.jobCoordinator = jobCoordinator;
this.dpntePsInfoCache = dpntePsInfoCache;
this.entityOwnershipUtils = entityOwnershipUtils;
- this.entityOwnershipService = entityOwnershipService;
+ this.eventCallbacks = eventCallbacks;
+ this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
this.itmInternalTunnelAddWorker = new ItmInternalTunnelAddWorker(dataBroker, jobCoordinator,
- tunnelMonitoringConfig, itmConfig);
- 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);
+ tunnelMonitoringConfig, interfaceManager, dpnTepStateCache, ovsBridgeEntryCache,
+ ovsBridgeRefEntryCache, tunnelStateCache, directTunnelUtils, ofEndPointCache, itmConfig);
serviceRecoveryRegistry.registerServiceRecoveryRegistry(getServiceRegistryKey(), this);
+ this.interfaceManager = interfaceManager;
+ this.dpnTepStateCache = dpnTepStateCache;
}
private String getServiceRegistryKey() {
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(vtep.getIpAddress().getIpv4Address().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(),
- new IpAddress(ipAddress.toCharArray()), 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
+}