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, tombstonedNodeManager);
119 serviceRecoveryRegistry.registerServiceRecoveryRegistry(getServiceRegistryKey(), this);
120 this.interfaceManager = interfaceManager;
121 this.dpnTepStateCache = dpnTepStateCache;
124 private String getServiceRegistryKey() {
125 return GeniusItmTep.class.toString();
129 public void recoverService(String entityId) {
130 if (!entityOwnershipUtils.isEntityOwner(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY)) {
133 LOG.info("Trigerred recovery of ITM Instance - Tep {}", entityId);
135 recoverTep(entityId);
136 } catch (InterruptedException e) {
137 LOG.error("ITM Instance tep has not been recovered.", e);
141 private void recoverTep(String entityId) throws InterruptedException {
142 List<DPNTEPsInfo> tepsToRecover = new ArrayList<>();
143 String[] params = entityId.split(":");
144 if (params.length < 2) {
145 LOG.error("Not enough arguments..Exiting...");
146 } else if (params.length > 2) {
147 LOG.info("Ignoring extra parameter and proceeding...");
149 String tzName = params[0];
150 String ipAddress = params[1];
151 TransportZone oldTz = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
152 DPNTEPsInfo dpnTepsToRecover = extractDPNTepsInfo(tzName, ipAddress, oldTz);
153 if (dpnTepsToRecover == null) {
154 LOG.error("Please Enter appropriate arguments for Tep Recovery.");
157 tepsToRecover.add(dpnTepsToRecover);
158 //List of Internel tunnels
159 Map<InternalTunnelKey, InternalTunnel> tunnelList = ItmUtils.getInternalTunnelsFromCache(dataBroker);
160 List<String> interfaceListToRecover = new ArrayList<>();
161 LOG.debug("List of tunnel interfaces: {}" , tunnelList);
164 LOG.trace("Deleting transportzone {}", tzName);
165 ItmTepRemoveWorker tepRemoveWorker = new ItmTepRemoveWorker(tepsToRecover, null, oldTz,
166 imdsalApiManager, itmInternalTunnelDeleteWorker, dpntePsInfoCache, txRunner, itmConfig);
167 jobCoordinator.enqueueJob(tzName, tepRemoveWorker);
168 AtomicInteger eventCallbackCount = new AtomicInteger(0);
169 AtomicInteger eventRegistrationCount = new AtomicInteger(0);
170 if (interfaceManager.isItmDirectTunnelsEnabled()) {
171 Collection<DpnsTeps> dpnsTeps = dpnTepStateCache.getAllPresent();
172 for (DpnsTeps dpnTep : dpnsTeps) {
173 @Nullable Map<RemoteDpnsKey, RemoteDpns> rmtdpns = dpnTep.getRemoteDpns();
174 for (RemoteDpns remoteDpn : rmtdpns.values()) {
175 if (remoteDpn.getDestinationDpnId().equals(dpnTepsToRecover.getDPNID())
176 || dpnTep.getSourceDpnId().equals(dpnTepsToRecover.getDPNID())) {
177 eventRegistrationCount.incrementAndGet();
178 interfaceListToRecover.add(remoteDpn.getTunnelName());
182 LOG.trace("List of tunnels to be recovered : {}", interfaceListToRecover);
184 tunnelList.values().stream().filter(internalTunnel -> Objects.equals(internalTunnel
185 .getDestinationDPN(), dpnTepsToRecover.getDPNID()) || Objects.equals(
186 internalTunnel.getSourceDPN(), dpnTepsToRecover.getDPNID())).forEach(internalTunnel -> {
187 eventRegistrationCount.incrementAndGet();
188 interfaceListToRecover.add(String.valueOf(internalTunnel.getTunnelInterfaceNames()));
192 if (!interfaceListToRecover.isEmpty()) {
193 interfaceListToRecover.forEach(interfaceName -> {
194 StateTunnelListKey tlKey = new StateTunnelListKey(interfaceName);
195 LOG.trace("TunnelStateKey: {} for interface: {}", tlKey, interfaceName);
196 InstanceIdentifier<StateTunnelList> stListId = ItmUtils.buildStateTunnelListId(tlKey);
197 eventCallbacks.onRemove(LogicalDatastoreType.OPERATIONAL, stListId, (unused) -> {
198 LOG.trace("callback event for a delete {} interface instance....", stListId);
199 // recreating the transportZone
200 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
201 return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
202 }, Duration.ofMillis(5000), (id) -> {
203 LOG.trace("event callback timed out for {} tunnel interface ", interfaceName);
204 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
208 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
214 private void recreateTEP(String tzName, List tepts, AtomicInteger eventCallbackCount, int registeredEventSize) {
215 eventCallbackCount.incrementAndGet();
216 if (eventCallbackCount.intValue() == registeredEventSize || registeredEventSize == 0) {
217 LOG.info("Re-creating TEP {}", tzName);
218 ItmTepAddWorker tepAddWorker = new ItmTepAddWorker(tepts, null, dataBroker, imdsalApiManager,
219 itmInternalTunnelAddWorker, itmExternalTunnelAddWorker);
220 jobCoordinator.enqueueJob(tzName, tepAddWorker);
224 private DPNTEPsInfo extractDPNTepsInfo(String tzName, String ipAddress, TransportZone transportZone) {
226 if (transportZone == null) {
227 LOG.error("Transportzone name {} is not valid.", tzName);
231 String portName = itmConfig.getPortname() == null ? ITMConstants.DUMMY_PORT : itmConfig.getPortname();
232 int vlanId = itmConfig.getVlanId() != null ? itmConfig.getVlanId().toJava() : ITMConstants.DUMMY_VLANID;
234 for (Vteps vtep : transportZone.getVteps().values()) {
235 if (ipAddress.equals(vtep.getIpAddress().stringValue())) {
237 List<TzMembership> zones = ItmUtils.createTransportZoneMembership(tzName);
238 LOG.trace("Transportzone {} found match for tep {} to be recovered", transportZone.getZoneName(),
241 //OfTunnels is false byDefault
242 TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(vtep.getDpnId(),
243 IpAddressBuilder.getDefaultInstance(ipAddress), portName, false,
244 vlanId, zones, transportZone.getTunnelType(),
245 itmConfig.getDefaultTunnelTos());
247 List<TunnelEndPoints> teps = new ArrayList<>();
248 teps.add(tunnelEndPoints);
249 return ItmUtils.createDPNTepInfo(vtep.getDpnId(), teps);