a525412d05b597e50c68f7ebb20b62c6fd59a687
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / recovery / impl / ItmTepInstanceRecoveryHandler.java
1 /*
2  * Copyright (c) 2018 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.genius.itm.recovery.impl;
9
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;
61
62 @Singleton
63 public class ItmTepInstanceRecoveryHandler implements ServiceRecoveryInterface {
64
65     private static final Logger LOG = LoggerFactory.getLogger(ItmTepInstanceRecoveryHandler.class);
66
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;
81
82     @Inject
83     public ItmTepInstanceRecoveryHandler(DataBroker dataBroker,
84                                          ItmConfig itmConfig,
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,
111                 dpntePsInfoCache);
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;
119     }
120
121     private String getServiceRegistryKey() {
122         return GeniusItmTep.class.toString();
123     }
124
125     @Override
126     public void recoverService(String entityId) {
127         if (!entityOwnershipUtils.isEntityOwner(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY)) {
128             return;
129         }
130         LOG.info("Trigerred recovery of ITM Instance - Tep {}", entityId);
131         try {
132             recoverTep(entityId);
133         } catch (InterruptedException e) {
134             LOG.error("ITM Instance tep has not been recovered.", e);
135         }
136     }
137
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...");
145         }
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.");
152             return;
153         } else {
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);
159
160             if (oldTz != null) {
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());
176                             }
177                         }
178                     }
179                     LOG.trace("List of tunnels to be recovered : {}", interfaceListToRecover);
180                 } else {
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()));
186                             });
187                 }
188
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());
202                             });
203                     });
204                 } else {
205                     recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
206                 }
207             }
208         }
209     }
210
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);
218         }
219     }
220
221     private DPNTEPsInfo extractDPNTepsInfo(String tzName, String ipAddress, TransportZone transportZone) {
222
223         if (transportZone == null) {
224             LOG.error("Transportzone name {} is not valid.", tzName);
225             return null;
226         }
227
228         String portName = itmConfig.getPortname() == null ? ITMConstants.DUMMY_PORT : itmConfig.getPortname();
229         int vlanId = itmConfig.getVlanId() != null ? itmConfig.getVlanId().toJava() : ITMConstants.DUMMY_VLANID;
230
231         for (Vteps vtep : transportZone.getVteps()) {
232             if (ipAddress.equals(vtep.getIpAddress().stringValue())) {
233
234                 List<TzMembership> zones = ItmUtils.createTransportZoneMembership(tzName);
235                 LOG.trace("Transportzone {} found match for tep {} to be recovered", transportZone.getZoneName(),
236                         ipAddress);
237
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());
243
244                 List<TunnelEndPoints> teps = new ArrayList<>();
245                 teps.add(tunnelEndPoints);
246                 return ItmUtils.createDPNTepInfo(vtep.getDpnId(), teps);
247             }
248         }
249         return null;
250     }
251 }