Bump version odlparent->6.0.0,mdsal->5.0.3
[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.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;
60
61 @Singleton
62 public class ItmTepInstanceRecoveryHandler implements ServiceRecoveryInterface {
63
64     private static final Logger LOG = LoggerFactory.getLogger(ItmTepInstanceRecoveryHandler.class);
65
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;
79
80     @Inject
81     public ItmTepInstanceRecoveryHandler(DataBroker dataBroker,
82                                          ItmConfig itmConfig,
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,
107                 dpntePsInfoCache);
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;
114     }
115
116     private String getServiceRegistryKey() {
117         return GeniusItmTep.class.toString();
118     }
119
120     @Override
121     public void recoverService(String entityId) {
122         if (!entityOwnershipUtils.isEntityOwner(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY)) {
123             return;
124         }
125         LOG.info("Trigerred recovery of ITM Instance - Tep {}", entityId);
126         try {
127             recoverTep(entityId);
128         } catch (InterruptedException e) {
129             LOG.error("ITM Instance tep has not been recovered.", e);
130         }
131     }
132
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...");
140         }
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.");
147             return;
148         } else {
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);
154
155             if (oldTz != null) {
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());
171                             }
172                         }
173                     }
174                     LOG.trace("List of tunnels to be recovered : {}", interfaceListToRecover);
175                 } else {
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()));
181                             });
182                 }
183
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());
197                             });
198                     });
199                 } else {
200                     recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
201                 }
202             }
203         }
204     }
205
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);
213         }
214     }
215
216     private DPNTEPsInfo extractDPNTepsInfo(String tzName, String ipAddress, TransportZone transportZone) {
217
218         if (transportZone == null) {
219             LOG.error("Transportzone name {} is not valid.", tzName);
220             return null;
221         }
222
223         String portName = itmConfig.getPortname() == null ? ITMConstants.DUMMY_PORT : itmConfig.getPortname();
224         int vlanId = itmConfig.getVlanId() != null ? itmConfig.getVlanId().toJava() : ITMConstants.DUMMY_VLANID;
225
226         for (Vteps vtep : transportZone.getVteps()) {
227             if (ipAddress.equals(vtep.getIpAddress().stringValue())) {
228
229                 List<TzMembership> zones = ItmUtils.createTransportZoneMembership(tzName);
230                 LOG.trace("Transportzone {} found match for tep {} to be recovered", transportZone.getZoneName(),
231                         ipAddress);
232
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());
238
239                 List<TunnelEndPoints> teps = new ArrayList<>();
240                 teps.add(tunnelEndPoints);
241                 return ItmUtils.createDPNTepInfo(vtep.getDpnId(), teps);
242             }
243         }
244         return null;
245     }
246 }