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.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
21 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
22 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
23 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
24 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
25 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
26 import org.opendaylight.genius.itm.cache.OfEndPointCache;
27 import org.opendaylight.genius.itm.cache.OvsBridgeEntryCache;
28 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
29 import org.opendaylight.genius.itm.cache.TunnelStateCache;
30 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker;
31 import org.opendaylight.genius.itm.confighelpers.ItmInternalTunnelAddWorker;
32 import org.opendaylight.genius.itm.confighelpers.ItmInternalTunnelDeleteWorker;
33 import org.opendaylight.genius.itm.confighelpers.ItmTepAddWorker;
34 import org.opendaylight.genius.itm.confighelpers.ItmTepRemoveWorker;
35 import org.opendaylight.genius.itm.globals.ITMConstants;
36 import org.opendaylight.genius.itm.impl.ItmUtils;
37 import org.opendaylight.genius.itm.impl.TunnelMonitoringConfig;
38 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
39 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
40 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
41 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
42 import org.opendaylight.serviceutils.srm.ServiceRecoveryInterface;
43 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTeps;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpns;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Vteps;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.serviceutils.srm.types.rev180626.GeniusItmTep;
57 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
62 public class ItmTepInstanceRecoveryHandler implements ServiceRecoveryInterface {
64 private static final Logger LOG = LoggerFactory.getLogger(ItmTepInstanceRecoveryHandler.class);
66 private final JobCoordinator jobCoordinator;
67 private final ItmInternalTunnelAddWorker itmInternalTunnelAddWorker;
68 private final ItmExternalTunnelAddWorker itmExternalTunnelAddWorker;
69 private final DPNTEPsInfoCache dpntePsInfoCache;
70 private final DataBroker dataBroker;
71 private final ItmInternalTunnelDeleteWorker itmInternalTunnelDeleteWorker;
72 private final ItmConfig itmConfig;
73 private final EntityOwnershipUtils entityOwnershipUtils;
74 private final IMdsalApiManager imdsalApiManager;
75 private final DataTreeEventCallbackRegistrar eventCallbacks;
76 private final ManagedNewTransactionRunner txRunner;
77 private final IInterfaceManager interfaceManager;
78 private final DpnTepStateCache dpnTepStateCache;
81 public ItmTepInstanceRecoveryHandler(DataBroker dataBroker,
83 IMdsalApiManager imdsalApiMgr,
84 JobCoordinator jobCoordinator,
85 TunnelMonitoringConfig tunnelMonitoringConfig,
86 DPNTEPsInfoCache dpntePsInfoCache, TunnelStateCache tunnelStateCache,
87 DirectTunnelUtils directTunnelUtils, DpnTepStateCache dpnTepStateCache,
88 OvsBridgeEntryCache ovsBridgeEntryCache,
89 OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
90 IInterfaceManager interfaceManager,
91 ServiceRecoveryRegistry serviceRecoveryRegistry,
92 EntityOwnershipUtils entityOwnershipUtils,
93 OfEndPointCache ofEndPointCache,
94 DataTreeEventCallbackRegistrar eventCallbacks) {
95 this.dataBroker = dataBroker;
96 this.itmConfig = itmConfig;
97 this.imdsalApiManager = imdsalApiMgr;
98 this.jobCoordinator = jobCoordinator;
99 this.dpntePsInfoCache = dpntePsInfoCache;
100 this.entityOwnershipUtils = entityOwnershipUtils;
101 this.eventCallbacks = eventCallbacks;
102 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
103 this.itmInternalTunnelAddWorker = new ItmInternalTunnelAddWorker(dataBroker, jobCoordinator,
104 tunnelMonitoringConfig, itmConfig, directTunnelUtils, interfaceManager,
105 ovsBridgeRefEntryCache, ofEndPointCache, eventCallbacks);
106 this.itmExternalTunnelAddWorker = new ItmExternalTunnelAddWorker(itmConfig,
108 this.itmInternalTunnelDeleteWorker = new ItmInternalTunnelDeleteWorker(dataBroker, jobCoordinator,
109 tunnelMonitoringConfig, interfaceManager, dpnTepStateCache, ovsBridgeEntryCache,
110 ovsBridgeRefEntryCache, tunnelStateCache, directTunnelUtils, ofEndPointCache, itmConfig);
111 serviceRecoveryRegistry.registerServiceRecoveryRegistry(getServiceRegistryKey(), this);
112 this.interfaceManager = interfaceManager;
113 this.dpnTepStateCache = dpnTepStateCache;
116 private String getServiceRegistryKey() {
117 return GeniusItmTep.class.toString();
121 public void recoverService(String entityId) {
122 if (!entityOwnershipUtils.isEntityOwner(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY)) {
125 LOG.info("Trigerred recovery of ITM Instance - Tep {}", entityId);
127 recoverTep(entityId);
128 } catch (InterruptedException e) {
129 LOG.error("ITM Instance tep has not been recovered.", e);
133 private void recoverTep(String entityId) throws InterruptedException {
134 List<DPNTEPsInfo> tepsToRecover = new ArrayList<>();
135 String[] params = entityId.split(":");
136 if (params.length < 2) {
137 LOG.error("Not enough arguments..Exiting...");
138 } else if (params.length > 2) {
139 LOG.info("Ignoring extra parameter and proceeding...");
141 String tzName = params[0];
142 String ipAddress = params[1];
143 TransportZone oldTz = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
144 DPNTEPsInfo dpnTepsToRecover = extractDPNTepsInfo(tzName, ipAddress, oldTz);
145 if (dpnTepsToRecover == null) {
146 LOG.error("Please Enter appropriate arguments for Tep Recovery.");
149 tepsToRecover.add(dpnTepsToRecover);
150 //List of Internel tunnels
151 List<InternalTunnel> tunnelList = ItmUtils.getInternalTunnelsFromCache(dataBroker);
152 List<String> interfaceListToRecover = new ArrayList<>();
153 LOG.debug("List of tunnel interfaces: {}" , tunnelList);
156 LOG.trace("Deleting transportzone {}", tzName);
157 ItmTepRemoveWorker tepRemoveWorker = new ItmTepRemoveWorker(tepsToRecover, null, oldTz,
158 imdsalApiManager, itmInternalTunnelDeleteWorker, dpntePsInfoCache, txRunner, itmConfig);
159 jobCoordinator.enqueueJob(tzName, tepRemoveWorker);
160 AtomicInteger eventCallbackCount = new AtomicInteger(0);
161 AtomicInteger eventRegistrationCount = new AtomicInteger(0);
162 if (interfaceManager.isItmDirectTunnelsEnabled()) {
163 Collection<DpnsTeps> dpnsTeps = dpnTepStateCache.getAllPresent();
164 for (DpnsTeps dpnTep : dpnsTeps) {
165 List<RemoteDpns> rmtdpns = dpnTep.getRemoteDpns();
166 for (RemoteDpns remoteDpn : rmtdpns) {
167 if (remoteDpn.getDestinationDpnId().equals(dpnTepsToRecover.getDPNID())
168 || dpnTep.getSourceDpnId().equals(dpnTepsToRecover.getDPNID())) {
169 eventRegistrationCount.incrementAndGet();
170 interfaceListToRecover.add(remoteDpn.getTunnelName());
174 LOG.trace("List of tunnels to be recovered : {}", interfaceListToRecover);
176 tunnelList.stream().filter(internalTunnel -> Objects.equals(internalTunnel
177 .getDestinationDPN(), dpnTepsToRecover.getDPNID()) || Objects.equals(
178 internalTunnel.getSourceDPN(), dpnTepsToRecover.getDPNID())).forEach(internalTunnel -> {
179 eventRegistrationCount.incrementAndGet();
180 interfaceListToRecover.add(String.valueOf(internalTunnel.getTunnelInterfaceNames()));
184 if (!interfaceListToRecover.isEmpty()) {
185 interfaceListToRecover.forEach(interfaceName -> {
186 StateTunnelListKey tlKey = new StateTunnelListKey(interfaceName);
187 LOG.trace("TunnelStateKey: {} for interface: {}", tlKey, interfaceName);
188 InstanceIdentifier<StateTunnelList> stListId = ItmUtils.buildStateTunnelListId(tlKey);
189 eventCallbacks.onRemove(LogicalDatastoreType.OPERATIONAL, stListId, (unused) -> {
190 LOG.trace("callback event for a delete {} interface instance....", stListId);
191 // recreating the transportZone
192 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
193 return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
194 }, Duration.ofMillis(5000), (id) -> {
195 LOG.trace("event callback timed out for {} tunnel interface ", interfaceName);
196 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
200 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
206 private void recreateTEP(String tzName, List tepts, AtomicInteger eventCallbackCount, int registeredEventSize) {
207 eventCallbackCount.incrementAndGet();
208 if (eventCallbackCount.intValue() == registeredEventSize || registeredEventSize == 0) {
209 LOG.info("Re-creating TEP {}", tzName);
210 ItmTepAddWorker tepAddWorker = new ItmTepAddWorker(tepts, null, dataBroker, imdsalApiManager,
211 itmInternalTunnelAddWorker, itmExternalTunnelAddWorker);
212 jobCoordinator.enqueueJob(tzName, tepAddWorker);
216 private DPNTEPsInfo extractDPNTepsInfo(String tzName, String ipAddress, TransportZone transportZone) {
218 if (transportZone == null) {
219 LOG.error("Transportzone name {} is not valid.", tzName);
223 String portName = itmConfig.getPortname() == null ? ITMConstants.DUMMY_PORT : itmConfig.getPortname();
224 int vlanId = itmConfig.getVlanId() != null ? itmConfig.getVlanId().toJava() : ITMConstants.DUMMY_VLANID;
226 for (Vteps vtep : transportZone.getVteps()) {
227 if (ipAddress.equals(vtep.getIpAddress().stringValue())) {
229 List<TzMembership> zones = ItmUtils.createTransportZoneMembership(tzName);
230 LOG.trace("Transportzone {} found match for tep {} to be recovered", transportZone.getZoneName(),
233 //OfTunnels is false byDefault
234 TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(vtep.getDpnId(),
235 IpAddressBuilder.getDefaultInstance(ipAddress), portName, false,
236 vlanId, zones, transportZone.getTunnelType(),
237 itmConfig.getDefaultTunnelTos());
239 List<TunnelEndPoints> teps = new ArrayList<>();
240 teps.add(tunnelEndPoints);
241 return ItmUtils.createDPNTepInfo(vtep.getDpnId(), teps);