OF port deletion complete implementation
[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.Map;
15 import java.util.Objects;
16 import java.util.concurrent.atomic.AtomicInteger;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.opendaylight.genius.cloudscaler.api.TombstonedNodeManager;
21 import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
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.binding.util.ManagedNewTransactionRunner;
43 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
44 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
45 import org.opendaylight.serviceutils.srm.ServiceRecoveryInterface;
46 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTeps;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpns;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpnsKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnelKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Vteps;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.serviceutils.srm.types.rev180626.GeniusItmTep;
62 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
65
66 @Singleton
67 public class ItmTepInstanceRecoveryHandler implements ServiceRecoveryInterface {
68
69     private static final Logger LOG = LoggerFactory.getLogger(ItmTepInstanceRecoveryHandler.class);
70
71     private final JobCoordinator jobCoordinator;
72     private final ItmInternalTunnelAddWorker itmInternalTunnelAddWorker;
73     private final ItmExternalTunnelAddWorker itmExternalTunnelAddWorker;
74     private final DPNTEPsInfoCache dpntePsInfoCache;
75     private final DataBroker dataBroker;
76     private final ItmInternalTunnelDeleteWorker itmInternalTunnelDeleteWorker;
77     private final ItmConfig itmConfig;
78     private final EntityOwnershipUtils entityOwnershipUtils;
79     private final IMdsalApiManager imdsalApiManager;
80     private final DataTreeEventCallbackRegistrar eventCallbacks;
81     private final ManagedNewTransactionRunner txRunner;
82     private final IInterfaceManager interfaceManager;
83     private final DpnTepStateCache dpnTepStateCache;
84     private final TombstonedNodeManager tombstonedNodeManager;
85
86     @Inject
87     public ItmTepInstanceRecoveryHandler(DataBroker dataBroker,
88                                          ItmConfig itmConfig,
89                                          IMdsalApiManager imdsalApiMgr,
90                                          JobCoordinator jobCoordinator,
91                                          TunnelMonitoringConfig tunnelMonitoringConfig,
92                                          DPNTEPsInfoCache dpntePsInfoCache, TunnelStateCache tunnelStateCache,
93                                          DirectTunnelUtils directTunnelUtils, DpnTepStateCache dpnTepStateCache,
94                                          OvsBridgeEntryCache ovsBridgeEntryCache,
95                                          OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
96                                          IInterfaceManager interfaceManager,
97                                          ServiceRecoveryRegistry serviceRecoveryRegistry,
98                                          EntityOwnershipUtils entityOwnershipUtils,
99                                          OfEndPointCache ofEndPointCache,
100                                          DataTreeEventCallbackRegistrar eventCallbacks,
101                                          TombstonedNodeManager tombstonedNodeManager) {
102         this.dataBroker = dataBroker;
103         this.itmConfig = itmConfig;
104         this.imdsalApiManager = imdsalApiMgr;
105         this.jobCoordinator = jobCoordinator;
106         this.dpntePsInfoCache = dpntePsInfoCache;
107         this.entityOwnershipUtils = entityOwnershipUtils;
108         this.eventCallbacks = eventCallbacks;
109         this.tombstonedNodeManager = tombstonedNodeManager;
110         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
111         this.itmInternalTunnelAddWorker = new ItmInternalTunnelAddWorker(dataBroker, jobCoordinator,
112                 tunnelMonitoringConfig, itmConfig, directTunnelUtils, interfaceManager,
113                 ovsBridgeRefEntryCache, ofEndPointCache, eventCallbacks);
114         this.itmExternalTunnelAddWorker = new ItmExternalTunnelAddWorker(itmConfig,
115                 dpntePsInfoCache);
116         this.itmInternalTunnelDeleteWorker = new ItmInternalTunnelDeleteWorker(dataBroker, jobCoordinator,
117                 tunnelMonitoringConfig, interfaceManager, dpnTepStateCache, ovsBridgeEntryCache,
118                 ovsBridgeRefEntryCache, tunnelStateCache, directTunnelUtils, tombstonedNodeManager);
119         serviceRecoveryRegistry.registerServiceRecoveryRegistry(getServiceRegistryKey(), this);
120         this.interfaceManager = interfaceManager;
121         this.dpnTepStateCache = dpnTepStateCache;
122     }
123
124     private String getServiceRegistryKey() {
125         return GeniusItmTep.class.toString();
126     }
127
128     @Override
129     public void recoverService(String entityId) {
130         if (!entityOwnershipUtils.isEntityOwner(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY)) {
131             return;
132         }
133         LOG.info("Trigerred recovery of ITM Instance - Tep {}", entityId);
134         try {
135             recoverTep(entityId);
136         } catch (InterruptedException e) {
137             LOG.error("ITM Instance tep has not been recovered.", e);
138         }
139     }
140
141     private void recoverTep(String entityId) throws InterruptedException {
142         List<DPNTEPsInfo> tepsToRecover = new ArrayList<>();
143         String[] params = entityId.split(":");
144         if (params.length < 2) {
145             LOG.error("Not enough arguments..Exiting...");
146         } else if (params.length > 2) {
147             LOG.info("Ignoring extra parameter and proceeding...");
148         }
149         String tzName = params[0];
150         String ipAddress = params[1];
151         TransportZone oldTz = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
152         DPNTEPsInfo dpnTepsToRecover = extractDPNTepsInfo(tzName, ipAddress, oldTz);
153         if (dpnTepsToRecover == null) {
154             LOG.error("Please Enter appropriate arguments for Tep Recovery.");
155             return;
156         } else {
157             tepsToRecover.add(dpnTepsToRecover);
158             //List of Internel tunnels
159             Map<InternalTunnelKey, InternalTunnel> tunnelList = ItmUtils.getInternalTunnelsFromCache(dataBroker);
160             List<String> interfaceListToRecover = new ArrayList<>();
161             LOG.debug("List of tunnel interfaces: {}" , tunnelList);
162
163             if (oldTz != null) {
164                 LOG.trace("Deleting transportzone {}", tzName);
165                 ItmTepRemoveWorker tepRemoveWorker = new ItmTepRemoveWorker(tepsToRecover, null, oldTz,
166                         imdsalApiManager, itmInternalTunnelDeleteWorker, dpntePsInfoCache, txRunner, itmConfig);
167                 jobCoordinator.enqueueJob(tzName, tepRemoveWorker);
168                 AtomicInteger eventCallbackCount = new AtomicInteger(0);
169                 AtomicInteger eventRegistrationCount = new AtomicInteger(0);
170                 if (interfaceManager.isItmDirectTunnelsEnabled()) {
171                     Collection<DpnsTeps> dpnsTeps = dpnTepStateCache.getAllPresent();
172                     for (DpnsTeps dpnTep : dpnsTeps) {
173                         @Nullable Map<RemoteDpnsKey, RemoteDpns> rmtdpns = dpnTep.getRemoteDpns();
174                         for (RemoteDpns remoteDpn : rmtdpns.values()) {
175                             if (remoteDpn.getDestinationDpnId().equals(dpnTepsToRecover.getDPNID())
176                                     || dpnTep.getSourceDpnId().equals(dpnTepsToRecover.getDPNID())) {
177                                 eventRegistrationCount.incrementAndGet();
178                                 interfaceListToRecover.add(remoteDpn.getTunnelName());
179                             }
180                         }
181                     }
182                     LOG.trace("List of tunnels to be recovered : {}", interfaceListToRecover);
183                 } else {
184                     tunnelList.values().stream().filter(internalTunnel -> Objects.equals(internalTunnel
185                             .getDestinationDPN(), dpnTepsToRecover.getDPNID()) || Objects.equals(
186                             internalTunnel.getSourceDPN(), dpnTepsToRecover.getDPNID())).forEach(internalTunnel -> {
187                                 eventRegistrationCount.incrementAndGet();
188                                 interfaceListToRecover.add(String.valueOf(internalTunnel.getTunnelInterfaceNames()));
189                             });
190                 }
191
192                 if (!interfaceListToRecover.isEmpty()) {
193                     interfaceListToRecover.forEach(interfaceName -> {
194                         StateTunnelListKey tlKey = new StateTunnelListKey(interfaceName);
195                         LOG.trace("TunnelStateKey: {} for interface: {}", tlKey, interfaceName);
196                         InstanceIdentifier<StateTunnelList> stListId = ItmUtils.buildStateTunnelListId(tlKey);
197                         eventCallbacks.onRemove(LogicalDatastoreType.OPERATIONAL, stListId, (unused) -> {
198                             LOG.trace("callback event for a delete {} interface instance....", stListId);
199                             // recreating the transportZone
200                             recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
201                             return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
202                         }, Duration.ofMillis(5000), (id) -> {
203                                 LOG.trace("event callback timed out for {} tunnel interface ", interfaceName);
204                                 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
205                             });
206                     });
207                 } else {
208                     recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
209                 }
210             }
211         }
212     }
213
214     private void recreateTEP(String tzName, List tepts, AtomicInteger eventCallbackCount, int registeredEventSize) {
215         eventCallbackCount.incrementAndGet();
216         if (eventCallbackCount.intValue() == registeredEventSize || registeredEventSize == 0) {
217             LOG.info("Re-creating TEP {}", tzName);
218             ItmTepAddWorker tepAddWorker = new ItmTepAddWorker(tepts, null, dataBroker, imdsalApiManager,
219                     itmInternalTunnelAddWorker, itmExternalTunnelAddWorker);
220             jobCoordinator.enqueueJob(tzName, tepAddWorker);
221         }
222     }
223
224     private DPNTEPsInfo extractDPNTepsInfo(String tzName, String ipAddress, TransportZone transportZone) {
225
226         if (transportZone == null) {
227             LOG.error("Transportzone name {} is not valid.", tzName);
228             return null;
229         }
230
231         String portName = itmConfig.getPortname() == null ? ITMConstants.DUMMY_PORT : itmConfig.getPortname();
232         int vlanId = itmConfig.getVlanId() != null ? itmConfig.getVlanId().toJava() : ITMConstants.DUMMY_VLANID;
233
234         for (Vteps vtep : transportZone.getVteps().values()) {
235             if (ipAddress.equals(vtep.getIpAddress().stringValue())) {
236
237                 List<TzMembership> zones = ItmUtils.createTransportZoneMembership(tzName);
238                 LOG.trace("Transportzone {} found match for tep {} to be recovered", transportZone.getZoneName(),
239                         ipAddress);
240
241                 //OfTunnels is false byDefault
242                 TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(vtep.getDpnId(),
243                         IpAddressBuilder.getDefaultInstance(ipAddress), portName, false,
244                         vlanId, zones, transportZone.getTunnelType(),
245                         itmConfig.getDefaultTunnelTos());
246
247                 List<TunnelEndPoints> teps = new ArrayList<>();
248                 teps.add(tunnelEndPoints);
249                 return ItmUtils.createDPNTepInfo(vtep.getDpnId(), teps);
250             }
251         }
252         return null;
253     }
254 }