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.interfacemanager.interfaces.IInterfaceManager;
21 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
22 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
23 import org.opendaylight.genius.itm.cache.OvsBridgeEntryCache;
24 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
25 import org.opendaylight.genius.itm.cache.TunnelStateCache;
26 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker;
27 import org.opendaylight.genius.itm.confighelpers.ItmInternalTunnelAddWorker;
28 import org.opendaylight.genius.itm.confighelpers.ItmInternalTunnelDeleteWorker;
29 import org.opendaylight.genius.itm.confighelpers.ItmTepAddWorker;
30 import org.opendaylight.genius.itm.confighelpers.ItmTepRemoveWorker;
31 import org.opendaylight.genius.itm.globals.ITMConstants;
32 import org.opendaylight.genius.itm.impl.ItmUtils;
33 import org.opendaylight.genius.itm.impl.TunnelMonitoringConfig;
34 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
35 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
36 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
37 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
38 import org.opendaylight.serviceutils.srm.ServiceRecoveryInterface;
39 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.serviceutils.srm.types.rev180626.GeniusItmTep;
52 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
57 public class ItmTepInstanceRecoveryHandler implements ServiceRecoveryInterface {
59 private static final Logger LOG = LoggerFactory.getLogger(ItmTepInstanceRecoveryHandler.class);
61 private final JobCoordinator jobCoordinator;
62 private final ItmInternalTunnelAddWorker itmInternalTunnelAddWorker;
63 private final ItmExternalTunnelAddWorker itmExternalTunnelAddWorker;
64 private final DPNTEPsInfoCache dpntePsInfoCache;
65 private final DataBroker dataBroker;
66 private final ItmInternalTunnelDeleteWorker itmInternalTunnelDeleteWorker;
67 private final ItmConfig itmConfig;
68 private final EntityOwnershipUtils entityOwnershipUtils;
69 private final IMdsalApiManager imdsalApiManager;
70 private final DataTreeEventCallbackRegistrar eventCallbacks;
73 public ItmTepInstanceRecoveryHandler(DataBroker dataBroker,
75 IMdsalApiManager imdsalApiMgr,
76 JobCoordinator jobCoordinator,
77 TunnelMonitoringConfig tunnelMonitoringConfig,
78 DPNTEPsInfoCache dpntePsInfoCache, TunnelStateCache tunnelStateCache,
79 DirectTunnelUtils directTunnelUtils, DpnTepStateCache dpnTepStateCache,
80 OvsBridgeEntryCache ovsBridgeEntryCache,
81 OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
82 IInterfaceManager interfaceManager,
83 ServiceRecoveryRegistry serviceRecoveryRegistry,
84 EntityOwnershipUtils entityOwnershipUtils,
85 DataTreeEventCallbackRegistrar eventCallbacks) {
86 this.dataBroker = dataBroker;
87 this.itmConfig = itmConfig;
88 this.imdsalApiManager = imdsalApiMgr;
89 this.jobCoordinator = jobCoordinator;
90 this.dpntePsInfoCache = dpntePsInfoCache;
91 this.entityOwnershipUtils = entityOwnershipUtils;
92 this.eventCallbacks = eventCallbacks;
93 this.itmInternalTunnelAddWorker = new ItmInternalTunnelAddWorker(dataBroker, jobCoordinator,
94 tunnelMonitoringConfig, itmConfig, directTunnelUtils, interfaceManager, ovsBridgeRefEntryCache);
95 this.itmExternalTunnelAddWorker = new ItmExternalTunnelAddWorker(dataBroker, itmConfig,
97 this.itmInternalTunnelDeleteWorker = new ItmInternalTunnelDeleteWorker(dataBroker, jobCoordinator,
98 tunnelMonitoringConfig, interfaceManager, dpnTepStateCache, ovsBridgeEntryCache,
99 ovsBridgeRefEntryCache, tunnelStateCache,
101 serviceRecoveryRegistry.registerServiceRecoveryRegistry(getServiceRegistryKey(), this);
104 private String getServiceRegistryKey() {
105 return GeniusItmTep.class.toString();
109 public void recoverService(String entityId) {
110 if (!entityOwnershipUtils.isEntityOwner(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY)) {
113 LOG.info("Trigerred recovery of ITM Instance - Tep {}", entityId);
115 recoverTep(entityId);
116 } catch (InterruptedException e) {
117 LOG.error("ITM Instance tep has not been recovered.", e);
121 private void recoverTep(String entityId) throws InterruptedException {
122 List<DPNTEPsInfo> tepsToRecover = new ArrayList<>();
123 String[] params = entityId.split(":");
124 if (params.length < 2) {
125 LOG.error("Not enough arguments..Exiting...");
126 } else if (params.length > 2) {
127 LOG.info("Ignoring extra parameter and proceeding...");
129 String tzName = params[0];
130 String ipAddress = params[1];
131 TransportZone oldTz = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
132 DPNTEPsInfo dpnTepsToRecover = extractDPNTepsInfo(tzName, ipAddress, oldTz);
133 if (dpnTepsToRecover == null) {
134 LOG.error("Please Enter appropriate arguments for Tep Recovery.");
137 tepsToRecover.add(dpnTepsToRecover);
138 //List of Internel tunnels
139 List<InternalTunnel> tunnelList = ItmUtils.getInternalTunnelsFromCache(dataBroker);
140 List<String> interfaceListToRecover = new ArrayList<>();
141 LOG.debug("List of tunnel interfaces: {}" , tunnelList);
144 LOG.trace("Deleting transportzone {}", tzName);
145 ItmTepRemoveWorker tepRemoveWorker = new ItmTepRemoveWorker(tepsToRecover, null, oldTz,
146 dataBroker, imdsalApiManager, itmInternalTunnelDeleteWorker, dpntePsInfoCache);
147 jobCoordinator.enqueueJob(tzName, tepRemoveWorker);
148 AtomicInteger eventCallbackCount = new AtomicInteger(0);
149 AtomicInteger eventRegistrationCount = new AtomicInteger(0);
150 tunnelList.stream().filter(internalTunnel -> Objects.equals(internalTunnel
151 .getDestinationDPN(), dpnTepsToRecover.getDPNID()) || Objects.equals(
152 internalTunnel.getSourceDPN(), dpnTepsToRecover.getDPNID())).forEach(internalTunnel -> {
153 eventRegistrationCount.incrementAndGet();
154 interfaceListToRecover.add(String.valueOf(internalTunnel.getTunnelInterfaceNames())); });
156 if (!interfaceListToRecover.isEmpty()) {
157 interfaceListToRecover.forEach(interfaceName -> {
158 StateTunnelListKey tlKey = new StateTunnelListKey(interfaceName);
159 LOG.trace("TunnelStateKey: {} for interface: {}", tlKey, interfaceName);
160 InstanceIdentifier<StateTunnelList> stListId = ItmUtils.buildStateTunnelListId(tlKey);
161 eventCallbacks.onRemove(LogicalDatastoreType.OPERATIONAL, stListId, (unused) -> {
162 LOG.trace("callback event for a delete {} interface instance....", stListId);
163 // recreating the transportZone
164 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
165 return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
166 }, Duration.ofMillis(5000), (id) -> {
167 LOG.trace("event callback timed out for {} tunnel interface ", interfaceName);
168 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
172 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
179 private void recreateTEP(String tzName, List tepts, AtomicInteger eventCallbackCount, int registeredEventSize) {
180 eventCallbackCount.incrementAndGet();
181 if (eventCallbackCount.intValue() == registeredEventSize || registeredEventSize == 0) {
182 LOG.info("Re-creating TEP {}", tzName);
183 ItmTepAddWorker tepAddWorker = new ItmTepAddWorker(tepts, null, dataBroker,
184 imdsalApiManager, itmConfig, itmInternalTunnelAddWorker, itmExternalTunnelAddWorker,
186 jobCoordinator.enqueueJob(tzName, tepAddWorker);
188 LOG.trace("{} call back events registered for {} tunnel interfaces",
189 registeredEventSize, eventCallbackCount);
193 private DPNTEPsInfo extractDPNTepsInfo(String tzName, String ipAddress, TransportZone transportZone) {
195 if (transportZone == null) {
196 LOG.error("Transportzone name {} is not valid.", tzName);
200 for (Subnets sub : transportZone.nonnullSubnets()) {
201 if (sub.getVteps() == null || sub.getVteps().isEmpty()) {
202 LOG.error("Transport Zone {} subnet {} has no vteps", transportZone.getZoneName(), sub.getPrefix());
204 for (Vteps vtep : sub.getVteps()) {
205 if (ipAddress.equals(vtep.getIpAddress().stringValue())) {
207 List<TzMembership> zones = ItmUtils.createTransportZoneMembership(tzName);
208 LOG.trace("Transportzone {} found match for tep {} to be recovered", transportZone.getZoneName(),
211 //OfTunnels is false byDefault
212 TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(vtep.getDpnId(),
213 IpAddressBuilder.getDefaultInstance(ipAddress), vtep.getPortname(), false, sub.getVlanId(),
214 sub.getPrefix(), sub.getGatewayIp(), zones,transportZone.getTunnelType(),
215 itmConfig.getDefaultTunnelTos());
217 List<TunnelEndPoints> teps = new ArrayList<>();
218 teps.add(tunnelEndPoints);
219 return ItmUtils.createDPNTepInfo(vtep.getDpnId(), teps);