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.List;
13 import java.util.Objects;
14 import java.util.concurrent.atomic.AtomicInteger;
15 import javax.inject.Inject;
16 import javax.inject.Singleton;
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
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.serviceutils.srm.ServiceRecoveryInterface;
42 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Vteps;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.serviceutils.srm.types.rev180626.GeniusItmTep;
54 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
59 public class ItmTepInstanceRecoveryHandler implements ServiceRecoveryInterface {
61 private static final Logger LOG = LoggerFactory.getLogger(ItmTepInstanceRecoveryHandler.class);
63 private final JobCoordinator jobCoordinator;
64 private final ItmInternalTunnelAddWorker itmInternalTunnelAddWorker;
65 private final ItmExternalTunnelAddWorker itmExternalTunnelAddWorker;
66 private final DPNTEPsInfoCache dpntePsInfoCache;
67 private final DataBroker dataBroker;
68 private final ItmInternalTunnelDeleteWorker itmInternalTunnelDeleteWorker;
69 private final ItmConfig itmConfig;
70 private final EntityOwnershipUtils entityOwnershipUtils;
71 private final IMdsalApiManager imdsalApiManager;
72 private final DataTreeEventCallbackRegistrar eventCallbacks;
73 private final ManagedNewTransactionRunner txRunner;
76 public ItmTepInstanceRecoveryHandler(DataBroker dataBroker,
78 IMdsalApiManager imdsalApiMgr,
79 JobCoordinator jobCoordinator,
80 TunnelMonitoringConfig tunnelMonitoringConfig,
81 DPNTEPsInfoCache dpntePsInfoCache, TunnelStateCache tunnelStateCache,
82 DirectTunnelUtils directTunnelUtils, DpnTepStateCache dpnTepStateCache,
83 OvsBridgeEntryCache ovsBridgeEntryCache,
84 OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
85 IInterfaceManager interfaceManager,
86 ServiceRecoveryRegistry serviceRecoveryRegistry,
87 EntityOwnershipUtils entityOwnershipUtils,
88 OfEndPointCache ofEndPointCache,
89 DataTreeEventCallbackRegistrar eventCallbacks) {
90 this.dataBroker = dataBroker;
91 this.itmConfig = itmConfig;
92 this.imdsalApiManager = imdsalApiMgr;
93 this.jobCoordinator = jobCoordinator;
94 this.dpntePsInfoCache = dpntePsInfoCache;
95 this.entityOwnershipUtils = entityOwnershipUtils;
96 this.eventCallbacks = eventCallbacks;
97 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
98 this.itmInternalTunnelAddWorker = new ItmInternalTunnelAddWorker(dataBroker, jobCoordinator,
99 tunnelMonitoringConfig, itmConfig, directTunnelUtils, interfaceManager,
100 ovsBridgeRefEntryCache, ofEndPointCache, eventCallbacks);
101 this.itmExternalTunnelAddWorker = new ItmExternalTunnelAddWorker(itmConfig,
103 this.itmInternalTunnelDeleteWorker = new ItmInternalTunnelDeleteWorker(dataBroker, jobCoordinator,
104 tunnelMonitoringConfig, interfaceManager, dpnTepStateCache, ovsBridgeEntryCache,
105 ovsBridgeRefEntryCache, tunnelStateCache, directTunnelUtils);
106 serviceRecoveryRegistry.registerServiceRecoveryRegistry(getServiceRegistryKey(), this);
109 private String getServiceRegistryKey() {
110 return GeniusItmTep.class.toString();
114 public void recoverService(String entityId) {
115 if (!entityOwnershipUtils.isEntityOwner(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY)) {
118 LOG.info("Trigerred recovery of ITM Instance - Tep {}", entityId);
120 recoverTep(entityId);
121 } catch (InterruptedException e) {
122 LOG.error("ITM Instance tep has not been recovered.", e);
126 private void recoverTep(String entityId) throws InterruptedException {
127 List<DPNTEPsInfo> tepsToRecover = new ArrayList<>();
128 String[] params = entityId.split(":");
129 if (params.length < 2) {
130 LOG.error("Not enough arguments..Exiting...");
131 } else if (params.length > 2) {
132 LOG.info("Ignoring extra parameter and proceeding...");
134 String tzName = params[0];
135 String ipAddress = params[1];
136 TransportZone oldTz = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
137 DPNTEPsInfo dpnTepsToRecover = extractDPNTepsInfo(tzName, ipAddress, oldTz);
138 if (dpnTepsToRecover == null) {
139 LOG.error("Please Enter appropriate arguments for Tep Recovery.");
142 tepsToRecover.add(dpnTepsToRecover);
143 //List of Internel tunnels
144 List<InternalTunnel> tunnelList = ItmUtils.getInternalTunnelsFromCache(dataBroker);
145 List<String> interfaceListToRecover = new ArrayList<>();
146 LOG.debug("List of tunnel interfaces: {}" , tunnelList);
149 LOG.trace("Deleting transportzone {}", tzName);
150 ItmTepRemoveWorker tepRemoveWorker = new ItmTepRemoveWorker(tepsToRecover, null, oldTz,
151 imdsalApiManager, itmInternalTunnelDeleteWorker, dpntePsInfoCache, txRunner, itmConfig);
152 jobCoordinator.enqueueJob(tzName, tepRemoveWorker);
153 AtomicInteger eventCallbackCount = new AtomicInteger(0);
154 AtomicInteger eventRegistrationCount = new AtomicInteger(0);
155 tunnelList.stream().filter(internalTunnel -> Objects.equals(internalTunnel
156 .getDestinationDPN(), dpnTepsToRecover.getDPNID()) || Objects.equals(
157 internalTunnel.getSourceDPN(), dpnTepsToRecover.getDPNID())).forEach(internalTunnel -> {
158 eventRegistrationCount.incrementAndGet();
159 interfaceListToRecover.add(String.valueOf(internalTunnel.getTunnelInterfaceNames())); });
161 if (!interfaceListToRecover.isEmpty()) {
162 interfaceListToRecover.forEach(interfaceName -> {
163 StateTunnelListKey tlKey = new StateTunnelListKey(interfaceName);
164 LOG.trace("TunnelStateKey: {} for interface: {}", tlKey, interfaceName);
165 InstanceIdentifier<StateTunnelList> stListId = ItmUtils.buildStateTunnelListId(tlKey);
166 eventCallbacks.onRemove(LogicalDatastoreType.OPERATIONAL, stListId, (unused) -> {
167 LOG.trace("callback event for a delete {} interface instance....", stListId);
168 // recreating the transportZone
169 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
170 return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
171 }, Duration.ofMillis(5000), (id) -> {
172 LOG.trace("event callback timed out for {} tunnel interface ", interfaceName);
173 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
177 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
184 private void recreateTEP(String tzName, List tepts, AtomicInteger eventCallbackCount, int registeredEventSize) {
185 eventCallbackCount.incrementAndGet();
186 if (eventCallbackCount.intValue() == registeredEventSize || registeredEventSize == 0) {
187 LOG.info("Re-creating TEP {}", tzName);
188 ItmTepAddWorker tepAddWorker = new ItmTepAddWorker(tepts, null, dataBroker, imdsalApiManager,
189 itmInternalTunnelAddWorker, itmExternalTunnelAddWorker);
190 jobCoordinator.enqueueJob(tzName, tepAddWorker);
192 LOG.trace("{} call back events registered for {} tunnel interfaces",
193 registeredEventSize, eventCallbackCount);
197 private DPNTEPsInfo extractDPNTepsInfo(String tzName, String ipAddress, TransportZone transportZone) {
199 if (transportZone == null) {
200 LOG.error("Transportzone name {} is not valid.", tzName);
204 String portName = (itmConfig.getPortname() == null) ? ITMConstants.DUMMY_PORT : itmConfig.getPortname();
205 int vlanId = (itmConfig.getVlanId() != null) ? itmConfig.getVlanId() : ITMConstants.DUMMY_VLANID;
207 for (Vteps vtep : transportZone.getVteps()) {
208 if (ipAddress.equals(vtep.getIpAddress().stringValue())) {
210 List<TzMembership> zones = ItmUtils.createTransportZoneMembership(tzName);
211 LOG.trace("Transportzone {} found match for tep {} to be recovered", transportZone.getZoneName(),
214 //OfTunnels is false byDefault
215 TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(vtep.getDpnId(),
216 IpAddressBuilder.getDefaultInstance(ipAddress), portName, false,
217 vlanId, zones, transportZone.getTunnelType(),
218 itmConfig.getDefaultTunnelTos());
220 List<TunnelEndPoints> teps = new ArrayList<>();
221 teps.add(tunnelEndPoints);
222 return ItmUtils.createDPNTepInfo(vtep.getDpnId(), teps);