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;
14 import java.util.Objects;
15 import java.util.concurrent.atomic.AtomicInteger;
16 import javax.inject.Inject;
17 import javax.inject.Singleton;
18 import org.opendaylight.genius.cloudscaler.api.TombstonedNodeManager;
19 import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
20 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
21 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
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.common.api.LogicalDatastoreType;
43 import org.opendaylight.serviceutils.srm.ServiceRecoveryInterface;
44 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTeps;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpns;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Vteps;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.serviceutils.srm.types.rev180626.GeniusItmTep;
58 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
63 public class ItmTepInstanceRecoveryHandler implements ServiceRecoveryInterface {
65 private static final Logger LOG = LoggerFactory.getLogger(ItmTepInstanceRecoveryHandler.class);
67 private final JobCoordinator jobCoordinator;
68 private final ItmInternalTunnelAddWorker itmInternalTunnelAddWorker;
69 private final ItmExternalTunnelAddWorker itmExternalTunnelAddWorker;
70 private final DPNTEPsInfoCache dpntePsInfoCache;
71 private final DataBroker dataBroker;
72 private final ItmInternalTunnelDeleteWorker itmInternalTunnelDeleteWorker;
73 private final ItmConfig itmConfig;
74 private final EntityOwnershipUtils entityOwnershipUtils;
75 private final IMdsalApiManager imdsalApiManager;
76 private final DataTreeEventCallbackRegistrar eventCallbacks;
77 private final ManagedNewTransactionRunner txRunner;
78 private final IInterfaceManager interfaceManager;
79 private final DpnTepStateCache dpnTepStateCache;
80 private final TombstonedNodeManager tombstonedNodeManager;
83 public ItmTepInstanceRecoveryHandler(DataBroker dataBroker,
85 IMdsalApiManager imdsalApiMgr,
86 JobCoordinator jobCoordinator,
87 TunnelMonitoringConfig tunnelMonitoringConfig,
88 DPNTEPsInfoCache dpntePsInfoCache, TunnelStateCache tunnelStateCache,
89 DirectTunnelUtils directTunnelUtils, DpnTepStateCache dpnTepStateCache,
90 OvsBridgeEntryCache ovsBridgeEntryCache,
91 OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
92 IInterfaceManager interfaceManager,
93 ServiceRecoveryRegistry serviceRecoveryRegistry,
94 EntityOwnershipUtils entityOwnershipUtils,
95 OfEndPointCache ofEndPointCache,
96 DataTreeEventCallbackRegistrar eventCallbacks,
97 TombstonedNodeManager tombstonedNodeManager) {
98 this.dataBroker = dataBroker;
99 this.itmConfig = itmConfig;
100 this.imdsalApiManager = imdsalApiMgr;
101 this.jobCoordinator = jobCoordinator;
102 this.dpntePsInfoCache = dpntePsInfoCache;
103 this.entityOwnershipUtils = entityOwnershipUtils;
104 this.eventCallbacks = eventCallbacks;
105 this.tombstonedNodeManager = tombstonedNodeManager;
106 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
107 this.itmInternalTunnelAddWorker = new ItmInternalTunnelAddWorker(dataBroker, jobCoordinator,
108 tunnelMonitoringConfig, itmConfig, directTunnelUtils, interfaceManager,
109 ovsBridgeRefEntryCache, ofEndPointCache, eventCallbacks);
110 this.itmExternalTunnelAddWorker = new ItmExternalTunnelAddWorker(itmConfig,
112 this.itmInternalTunnelDeleteWorker = new ItmInternalTunnelDeleteWorker(dataBroker, jobCoordinator,
113 tunnelMonitoringConfig, interfaceManager, dpnTepStateCache, ovsBridgeEntryCache,
114 ovsBridgeRefEntryCache, tunnelStateCache, directTunnelUtils, ofEndPointCache, itmConfig,
115 tombstonedNodeManager);
116 serviceRecoveryRegistry.registerServiceRecoveryRegistry(getServiceRegistryKey(), this);
117 this.interfaceManager = interfaceManager;
118 this.dpnTepStateCache = dpnTepStateCache;
121 private String getServiceRegistryKey() {
122 return GeniusItmTep.class.toString();
126 public void recoverService(String entityId) {
127 if (!entityOwnershipUtils.isEntityOwner(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY)) {
130 LOG.info("Trigerred recovery of ITM Instance - Tep {}", entityId);
132 recoverTep(entityId);
133 } catch (InterruptedException e) {
134 LOG.error("ITM Instance tep has not been recovered.", e);
138 private void recoverTep(String entityId) throws InterruptedException {
139 List<DPNTEPsInfo> tepsToRecover = new ArrayList<>();
140 String[] params = entityId.split(":");
141 if (params.length < 2) {
142 LOG.error("Not enough arguments..Exiting...");
143 } else if (params.length > 2) {
144 LOG.info("Ignoring extra parameter and proceeding...");
146 String tzName = params[0];
147 String ipAddress = params[1];
148 TransportZone oldTz = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
149 DPNTEPsInfo dpnTepsToRecover = extractDPNTepsInfo(tzName, ipAddress, oldTz);
150 if (dpnTepsToRecover == null) {
151 LOG.error("Please Enter appropriate arguments for Tep Recovery.");
154 tepsToRecover.add(dpnTepsToRecover);
155 //List of Internel tunnels
156 List<InternalTunnel> tunnelList = ItmUtils.getInternalTunnelsFromCache(dataBroker);
157 List<String> interfaceListToRecover = new ArrayList<>();
158 LOG.debug("List of tunnel interfaces: {}" , tunnelList);
161 LOG.trace("Deleting transportzone {}", tzName);
162 ItmTepRemoveWorker tepRemoveWorker = new ItmTepRemoveWorker(tepsToRecover, null, oldTz,
163 imdsalApiManager, itmInternalTunnelDeleteWorker, dpntePsInfoCache, txRunner, itmConfig);
164 jobCoordinator.enqueueJob(tzName, tepRemoveWorker);
165 AtomicInteger eventCallbackCount = new AtomicInteger(0);
166 AtomicInteger eventRegistrationCount = new AtomicInteger(0);
167 if (interfaceManager.isItmDirectTunnelsEnabled()) {
168 Collection<DpnsTeps> dpnsTeps = dpnTepStateCache.getAllPresent();
169 for (DpnsTeps dpnTep : dpnsTeps) {
170 List<RemoteDpns> rmtdpns = dpnTep.getRemoteDpns();
171 for (RemoteDpns remoteDpn : rmtdpns) {
172 if (remoteDpn.getDestinationDpnId().equals(dpnTepsToRecover.getDPNID())
173 || dpnTep.getSourceDpnId().equals(dpnTepsToRecover.getDPNID())) {
174 eventRegistrationCount.incrementAndGet();
175 interfaceListToRecover.add(remoteDpn.getTunnelName());
179 LOG.trace("List of tunnels to be recovered : {}", interfaceListToRecover);
181 tunnelList.stream().filter(internalTunnel -> Objects.equals(internalTunnel
182 .getDestinationDPN(), dpnTepsToRecover.getDPNID()) || Objects.equals(
183 internalTunnel.getSourceDPN(), dpnTepsToRecover.getDPNID())).forEach(internalTunnel -> {
184 eventRegistrationCount.incrementAndGet();
185 interfaceListToRecover.add(String.valueOf(internalTunnel.getTunnelInterfaceNames()));
189 if (!interfaceListToRecover.isEmpty()) {
190 interfaceListToRecover.forEach(interfaceName -> {
191 StateTunnelListKey tlKey = new StateTunnelListKey(interfaceName);
192 LOG.trace("TunnelStateKey: {} for interface: {}", tlKey, interfaceName);
193 InstanceIdentifier<StateTunnelList> stListId = ItmUtils.buildStateTunnelListId(tlKey);
194 eventCallbacks.onRemove(LogicalDatastoreType.OPERATIONAL, stListId, (unused) -> {
195 LOG.trace("callback event for a delete {} interface instance....", stListId);
196 // recreating the transportZone
197 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
198 return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
199 }, Duration.ofMillis(5000), (id) -> {
200 LOG.trace("event callback timed out for {} tunnel interface ", interfaceName);
201 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
205 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
211 private void recreateTEP(String tzName, List tepts, AtomicInteger eventCallbackCount, int registeredEventSize) {
212 eventCallbackCount.incrementAndGet();
213 if (eventCallbackCount.intValue() == registeredEventSize || registeredEventSize == 0) {
214 LOG.info("Re-creating TEP {}", tzName);
215 ItmTepAddWorker tepAddWorker = new ItmTepAddWorker(tepts, null, dataBroker, imdsalApiManager,
216 itmInternalTunnelAddWorker, itmExternalTunnelAddWorker);
217 jobCoordinator.enqueueJob(tzName, tepAddWorker);
221 private DPNTEPsInfo extractDPNTepsInfo(String tzName, String ipAddress, TransportZone transportZone) {
223 if (transportZone == null) {
224 LOG.error("Transportzone name {} is not valid.", tzName);
228 String portName = itmConfig.getPortname() == null ? ITMConstants.DUMMY_PORT : itmConfig.getPortname();
229 int vlanId = itmConfig.getVlanId() != null ? itmConfig.getVlanId().toJava() : ITMConstants.DUMMY_VLANID;
231 for (Vteps vtep : transportZone.getVteps()) {
232 if (ipAddress.equals(vtep.getIpAddress().stringValue())) {
234 List<TzMembership> zones = ItmUtils.createTransportZoneMembership(tzName);
235 LOG.trace("Transportzone {} found match for tep {} to be recovered", transportZone.getZoneName(),
238 //OfTunnels is false byDefault
239 TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(vtep.getDpnId(),
240 IpAddressBuilder.getDefaultInstance(ipAddress), portName, false,
241 vlanId, zones, transportZone.getTunnelType(),
242 itmConfig.getDefaultTunnelTos());
244 List<TunnelEndPoints> teps = new ArrayList<>();
245 teps.add(tunnelEndPoints);
246 return ItmUtils.createDPNTepInfo(vtep.getDpnId(), teps);