2 * Copyright (c) 2018 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.itm.recovery.impl;
10 import java.time.Duration;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.List;
15 import java.util.Objects;
16 import java.util.concurrent.atomic.AtomicInteger;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.opendaylight.genius.cloudscaler.api.TombstonedNodeManager;
21 import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
22 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
23 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
24 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
25 import org.opendaylight.genius.itm.cache.OfEndPointCache;
26 import org.opendaylight.genius.itm.cache.OvsBridgeEntryCache;
27 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
28 import org.opendaylight.genius.itm.cache.TunnelStateCache;
29 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker;
30 import org.opendaylight.genius.itm.confighelpers.ItmInternalTunnelAddWorker;
31 import org.opendaylight.genius.itm.confighelpers.ItmInternalTunnelDeleteWorker;
32 import org.opendaylight.genius.itm.confighelpers.ItmTepAddWorker;
33 import org.opendaylight.genius.itm.confighelpers.ItmTepRemoveWorker;
34 import org.opendaylight.genius.itm.globals.ITMConstants;
35 import org.opendaylight.genius.itm.impl.ItmUtils;
36 import org.opendaylight.genius.itm.impl.TunnelMonitoringConfig;
37 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
38 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
39 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
40 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
41 import org.opendaylight.mdsal.binding.api.DataBroker;
42 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
43 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
44 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
45 import org.opendaylight.serviceutils.srm.ServiceRecoveryInterface;
46 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTeps;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpns;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpnsKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnelKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Vteps;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.serviceutils.srm.types.rev180626.GeniusItmTep;
62 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
67 public class ItmTepInstanceRecoveryHandler implements ServiceRecoveryInterface {
69 private static final Logger LOG = LoggerFactory.getLogger(ItmTepInstanceRecoveryHandler.class);
71 private final JobCoordinator jobCoordinator;
72 private final ItmInternalTunnelAddWorker itmInternalTunnelAddWorker;
73 private final ItmExternalTunnelAddWorker itmExternalTunnelAddWorker;
74 private final DPNTEPsInfoCache dpntePsInfoCache;
75 private final DataBroker dataBroker;
76 private final ItmInternalTunnelDeleteWorker itmInternalTunnelDeleteWorker;
77 private final ItmConfig itmConfig;
78 private final EntityOwnershipUtils entityOwnershipUtils;
79 private final IMdsalApiManager imdsalApiManager;
80 private final DataTreeEventCallbackRegistrar eventCallbacks;
81 private final ManagedNewTransactionRunner txRunner;
82 private final IInterfaceManager interfaceManager;
83 private final DpnTepStateCache dpnTepStateCache;
84 private final TombstonedNodeManager tombstonedNodeManager;
87 public ItmTepInstanceRecoveryHandler(DataBroker dataBroker,
89 IMdsalApiManager imdsalApiMgr,
90 JobCoordinator jobCoordinator,
91 TunnelMonitoringConfig tunnelMonitoringConfig,
92 DPNTEPsInfoCache dpntePsInfoCache, TunnelStateCache tunnelStateCache,
93 DirectTunnelUtils directTunnelUtils, DpnTepStateCache dpnTepStateCache,
94 OvsBridgeEntryCache ovsBridgeEntryCache,
95 OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
96 IInterfaceManager interfaceManager,
97 ServiceRecoveryRegistry serviceRecoveryRegistry,
98 EntityOwnershipUtils entityOwnershipUtils,
99 OfEndPointCache ofEndPointCache,
100 DataTreeEventCallbackRegistrar eventCallbacks,
101 TombstonedNodeManager tombstonedNodeManager) {
102 this.dataBroker = dataBroker;
103 this.itmConfig = itmConfig;
104 this.imdsalApiManager = imdsalApiMgr;
105 this.jobCoordinator = jobCoordinator;
106 this.dpntePsInfoCache = dpntePsInfoCache;
107 this.entityOwnershipUtils = entityOwnershipUtils;
108 this.eventCallbacks = eventCallbacks;
109 this.tombstonedNodeManager = tombstonedNodeManager;
110 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
111 this.itmInternalTunnelAddWorker = new ItmInternalTunnelAddWorker(dataBroker, jobCoordinator,
112 tunnelMonitoringConfig, itmConfig, directTunnelUtils, interfaceManager,
113 ovsBridgeRefEntryCache, ofEndPointCache, eventCallbacks);
114 this.itmExternalTunnelAddWorker = new ItmExternalTunnelAddWorker(itmConfig,
116 this.itmInternalTunnelDeleteWorker = new ItmInternalTunnelDeleteWorker(dataBroker, jobCoordinator,
117 tunnelMonitoringConfig, interfaceManager, dpnTepStateCache, ovsBridgeEntryCache,
118 ovsBridgeRefEntryCache, tunnelStateCache, directTunnelUtils, ofEndPointCache, itmConfig,
119 tombstonedNodeManager);
120 serviceRecoveryRegistry.registerServiceRecoveryRegistry(getServiceRegistryKey(), this);
121 this.interfaceManager = interfaceManager;
122 this.dpnTepStateCache = dpnTepStateCache;
125 private String getServiceRegistryKey() {
126 return GeniusItmTep.class.toString();
130 public void recoverService(String entityId) {
131 if (!entityOwnershipUtils.isEntityOwner(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY)) {
134 LOG.info("Trigerred recovery of ITM Instance - Tep {}", entityId);
136 recoverTep(entityId);
137 } catch (InterruptedException e) {
138 LOG.error("ITM Instance tep has not been recovered.", e);
142 private void recoverTep(String entityId) throws InterruptedException {
143 List<DPNTEPsInfo> tepsToRecover = new ArrayList<>();
144 String[] params = entityId.split(":");
145 if (params.length < 2) {
146 LOG.error("Not enough arguments..Exiting...");
147 } else if (params.length > 2) {
148 LOG.info("Ignoring extra parameter and proceeding...");
150 String tzName = params[0];
151 String ipAddress = params[1];
152 TransportZone oldTz = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
153 DPNTEPsInfo dpnTepsToRecover = extractDPNTepsInfo(tzName, ipAddress, oldTz);
154 if (dpnTepsToRecover == null) {
155 LOG.error("Please Enter appropriate arguments for Tep Recovery.");
158 tepsToRecover.add(dpnTepsToRecover);
159 //List of Internel tunnels
160 Map<InternalTunnelKey, InternalTunnel> tunnelList = ItmUtils.getInternalTunnelsFromCache(dataBroker);
161 List<String> interfaceListToRecover = new ArrayList<>();
162 LOG.debug("List of tunnel interfaces: {}" , tunnelList);
165 LOG.trace("Deleting transportzone {}", tzName);
166 ItmTepRemoveWorker tepRemoveWorker = new ItmTepRemoveWorker(tepsToRecover, null, oldTz,
167 imdsalApiManager, itmInternalTunnelDeleteWorker, dpntePsInfoCache, txRunner, itmConfig);
168 jobCoordinator.enqueueJob(tzName, tepRemoveWorker);
169 AtomicInteger eventCallbackCount = new AtomicInteger(0);
170 AtomicInteger eventRegistrationCount = new AtomicInteger(0);
171 if (interfaceManager.isItmDirectTunnelsEnabled()) {
172 Collection<DpnsTeps> dpnsTeps = dpnTepStateCache.getAllPresent();
173 for (DpnsTeps dpnTep : dpnsTeps) {
174 @Nullable Map<RemoteDpnsKey, RemoteDpns> rmtdpns = dpnTep.getRemoteDpns();
175 for (RemoteDpns remoteDpn : rmtdpns.values()) {
176 if (remoteDpn.getDestinationDpnId().equals(dpnTepsToRecover.getDPNID())
177 || dpnTep.getSourceDpnId().equals(dpnTepsToRecover.getDPNID())) {
178 eventRegistrationCount.incrementAndGet();
179 interfaceListToRecover.add(remoteDpn.getTunnelName());
183 LOG.trace("List of tunnels to be recovered : {}", interfaceListToRecover);
185 tunnelList.values().stream().filter(internalTunnel -> Objects.equals(internalTunnel
186 .getDestinationDPN(), dpnTepsToRecover.getDPNID()) || Objects.equals(
187 internalTunnel.getSourceDPN(), dpnTepsToRecover.getDPNID())).forEach(internalTunnel -> {
188 eventRegistrationCount.incrementAndGet();
189 interfaceListToRecover.add(String.valueOf(internalTunnel.getTunnelInterfaceNames()));
193 if (!interfaceListToRecover.isEmpty()) {
194 interfaceListToRecover.forEach(interfaceName -> {
195 StateTunnelListKey tlKey = new StateTunnelListKey(interfaceName);
196 LOG.trace("TunnelStateKey: {} for interface: {}", tlKey, interfaceName);
197 InstanceIdentifier<StateTunnelList> stListId = ItmUtils.buildStateTunnelListId(tlKey);
198 eventCallbacks.onRemove(LogicalDatastoreType.OPERATIONAL, stListId, (unused) -> {
199 LOG.trace("callback event for a delete {} interface instance....", stListId);
200 // recreating the transportZone
201 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
202 return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
203 }, Duration.ofMillis(5000), (id) -> {
204 LOG.trace("event callback timed out for {} tunnel interface ", interfaceName);
205 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
209 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
215 private void recreateTEP(String tzName, List tepts, AtomicInteger eventCallbackCount, int registeredEventSize) {
216 eventCallbackCount.incrementAndGet();
217 if (eventCallbackCount.intValue() == registeredEventSize || registeredEventSize == 0) {
218 LOG.info("Re-creating TEP {}", tzName);
219 ItmTepAddWorker tepAddWorker = new ItmTepAddWorker(tepts, null, dataBroker, imdsalApiManager,
220 itmInternalTunnelAddWorker, itmExternalTunnelAddWorker);
221 jobCoordinator.enqueueJob(tzName, tepAddWorker);
225 private DPNTEPsInfo extractDPNTepsInfo(String tzName, String ipAddress, TransportZone transportZone) {
227 if (transportZone == null) {
228 LOG.error("Transportzone name {} is not valid.", tzName);
232 String portName = itmConfig.getPortname() == null ? ITMConstants.DUMMY_PORT : itmConfig.getPortname();
233 int vlanId = itmConfig.getVlanId() != null ? itmConfig.getVlanId().toJava() : ITMConstants.DUMMY_VLANID;
235 for (Vteps vtep : transportZone.getVteps().values()) {
236 if (ipAddress.equals(vtep.getIpAddress().stringValue())) {
238 List<TzMembership> zones = ItmUtils.createTransportZoneMembership(tzName);
239 LOG.trace("Transportzone {} found match for tep {} to be recovered", transportZone.getZoneName(),
242 //OfTunnels is false byDefault
243 TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(vtep.getDpnId(),
244 IpAddressBuilder.getDefaultInstance(ipAddress), portName, false,
245 vlanId, zones, transportZone.getTunnelType(),
246 itmConfig.getDefaultTunnelTos());
248 List<TunnelEndPoints> teps = new ArrayList<>();
249 teps.add(tunnelEndPoints);
250 return ItmUtils.createDPNTepInfo(vtep.getDpnId(), teps);