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.Subnets;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.serviceutils.srm.types.rev180626.GeniusItmTep;
55 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
60 public class ItmTepInstanceRecoveryHandler implements ServiceRecoveryInterface {
62 private static final Logger LOG = LoggerFactory.getLogger(ItmTepInstanceRecoveryHandler.class);
64 private final JobCoordinator jobCoordinator;
65 private final ItmInternalTunnelAddWorker itmInternalTunnelAddWorker;
66 private final ItmExternalTunnelAddWorker itmExternalTunnelAddWorker;
67 private final DPNTEPsInfoCache dpntePsInfoCache;
68 private final DataBroker dataBroker;
69 private final ItmInternalTunnelDeleteWorker itmInternalTunnelDeleteWorker;
70 private final ItmConfig itmConfig;
71 private final EntityOwnershipUtils entityOwnershipUtils;
72 private final IMdsalApiManager imdsalApiManager;
73 private final DataTreeEventCallbackRegistrar eventCallbacks;
74 private final ManagedNewTransactionRunner txRunner;
77 public ItmTepInstanceRecoveryHandler(DataBroker dataBroker,
79 IMdsalApiManager imdsalApiMgr,
80 JobCoordinator jobCoordinator,
81 TunnelMonitoringConfig tunnelMonitoringConfig,
82 DPNTEPsInfoCache dpntePsInfoCache, TunnelStateCache tunnelStateCache,
83 DirectTunnelUtils directTunnelUtils, DpnTepStateCache dpnTepStateCache,
84 OvsBridgeEntryCache ovsBridgeEntryCache,
85 OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
86 IInterfaceManager interfaceManager,
87 ServiceRecoveryRegistry serviceRecoveryRegistry,
88 EntityOwnershipUtils entityOwnershipUtils,
89 OfEndPointCache ofEndPointCache,
90 DataTreeEventCallbackRegistrar eventCallbacks) {
91 this.dataBroker = dataBroker;
92 this.itmConfig = itmConfig;
93 this.imdsalApiManager = imdsalApiMgr;
94 this.jobCoordinator = jobCoordinator;
95 this.dpntePsInfoCache = dpntePsInfoCache;
96 this.entityOwnershipUtils = entityOwnershipUtils;
97 this.eventCallbacks = eventCallbacks;
98 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
99 this.itmInternalTunnelAddWorker = new ItmInternalTunnelAddWorker(dataBroker, jobCoordinator,
100 tunnelMonitoringConfig, itmConfig, directTunnelUtils, interfaceManager,
101 ovsBridgeRefEntryCache, ofEndPointCache);
102 this.itmExternalTunnelAddWorker = new ItmExternalTunnelAddWorker(itmConfig,
104 this.itmInternalTunnelDeleteWorker = new ItmInternalTunnelDeleteWorker(dataBroker, jobCoordinator,
105 tunnelMonitoringConfig, interfaceManager, dpnTepStateCache, ovsBridgeEntryCache,
106 ovsBridgeRefEntryCache, tunnelStateCache, directTunnelUtils);
107 serviceRecoveryRegistry.registerServiceRecoveryRegistry(getServiceRegistryKey(), this);
110 private String getServiceRegistryKey() {
111 return GeniusItmTep.class.toString();
115 public void recoverService(String entityId) {
116 if (!entityOwnershipUtils.isEntityOwner(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY)) {
119 LOG.info("Trigerred recovery of ITM Instance - Tep {}", entityId);
121 recoverTep(entityId);
122 } catch (InterruptedException e) {
123 LOG.error("ITM Instance tep has not been recovered.", e);
127 private void recoverTep(String entityId) throws InterruptedException {
128 List<DPNTEPsInfo> tepsToRecover = new ArrayList<>();
129 String[] params = entityId.split(":");
130 if (params.length < 2) {
131 LOG.error("Not enough arguments..Exiting...");
132 } else if (params.length > 2) {
133 LOG.info("Ignoring extra parameter and proceeding...");
135 String tzName = params[0];
136 String ipAddress = params[1];
137 TransportZone oldTz = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
138 DPNTEPsInfo dpnTepsToRecover = extractDPNTepsInfo(tzName, ipAddress, oldTz);
139 if (dpnTepsToRecover == null) {
140 LOG.error("Please Enter appropriate arguments for Tep Recovery.");
143 tepsToRecover.add(dpnTepsToRecover);
144 //List of Internel tunnels
145 List<InternalTunnel> tunnelList = ItmUtils.getInternalTunnelsFromCache(dataBroker);
146 List<String> interfaceListToRecover = new ArrayList<>();
147 LOG.debug("List of tunnel interfaces: {}" , tunnelList);
150 LOG.trace("Deleting transportzone {}", tzName);
151 ItmTepRemoveWorker tepRemoveWorker = new ItmTepRemoveWorker(tepsToRecover, null, oldTz,
152 imdsalApiManager, itmInternalTunnelDeleteWorker, dpntePsInfoCache, txRunner);
153 jobCoordinator.enqueueJob(tzName, tepRemoveWorker);
154 AtomicInteger eventCallbackCount = new AtomicInteger(0);
155 AtomicInteger eventRegistrationCount = new AtomicInteger(0);
156 tunnelList.stream().filter(internalTunnel -> Objects.equals(internalTunnel
157 .getDestinationDPN(), dpnTepsToRecover.getDPNID()) || Objects.equals(
158 internalTunnel.getSourceDPN(), dpnTepsToRecover.getDPNID())).forEach(internalTunnel -> {
159 eventRegistrationCount.incrementAndGet();
160 interfaceListToRecover.add(String.valueOf(internalTunnel.getTunnelInterfaceNames())); });
162 if (!interfaceListToRecover.isEmpty()) {
163 interfaceListToRecover.forEach(interfaceName -> {
164 StateTunnelListKey tlKey = new StateTunnelListKey(interfaceName);
165 LOG.trace("TunnelStateKey: {} for interface: {}", tlKey, interfaceName);
166 InstanceIdentifier<StateTunnelList> stListId = ItmUtils.buildStateTunnelListId(tlKey);
167 eventCallbacks.onRemove(LogicalDatastoreType.OPERATIONAL, stListId, (unused) -> {
168 LOG.trace("callback event for a delete {} interface instance....", stListId);
169 // recreating the transportZone
170 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
171 return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
172 }, Duration.ofMillis(5000), (id) -> {
173 LOG.trace("event callback timed out for {} tunnel interface ", interfaceName);
174 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
178 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
185 private void recreateTEP(String tzName, List tepts, AtomicInteger eventCallbackCount, int registeredEventSize) {
186 eventCallbackCount.incrementAndGet();
187 if (eventCallbackCount.intValue() == registeredEventSize || registeredEventSize == 0) {
188 LOG.info("Re-creating TEP {}", tzName);
189 ItmTepAddWorker tepAddWorker = new ItmTepAddWorker(tepts, null, dataBroker, imdsalApiManager,
190 itmInternalTunnelAddWorker, itmExternalTunnelAddWorker);
191 jobCoordinator.enqueueJob(tzName, tepAddWorker);
193 LOG.trace("{} call back events registered for {} tunnel interfaces",
194 registeredEventSize, eventCallbackCount);
198 private DPNTEPsInfo extractDPNTepsInfo(String tzName, String ipAddress, TransportZone transportZone) {
200 if (transportZone == null) {
201 LOG.error("Transportzone name {} is not valid.", tzName);
205 for (Subnets sub : transportZone.nonnullSubnets()) {
206 if (sub.getVteps() == null || sub.getVteps().isEmpty()) {
207 LOG.error("Transport Zone {} subnet {} has no vteps", transportZone.getZoneName(), sub.getPrefix());
209 for (Vteps vtep : sub.nonnullVteps()) {
210 if (ipAddress.equals(vtep.getIpAddress().stringValue())) {
212 List<TzMembership> zones = ItmUtils.createTransportZoneMembership(tzName);
213 LOG.trace("Transportzone {} found match for tep {} to be recovered", transportZone.getZoneName(),
216 //OfTunnels is false byDefault
217 TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(vtep.getDpnId(),
218 IpAddressBuilder.getDefaultInstance(ipAddress), vtep.getPortname(), false, sub.getVlanId(),
219 sub.getPrefix(), sub.getGatewayIp(), zones,transportZone.getTunnelType(),
220 itmConfig.getDefaultTunnelTos());
222 List<TunnelEndPoints> teps = new ArrayList<>();
223 teps.add(tunnelEndPoints);
224 return ItmUtils.createDPNTepInfo(vtep.getDpnId(), teps);