Convert itm-impl to use mdsal-binding-util
[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, ofEndPointCache, itmConfig,
119                 tombstonedNodeManager);
120         serviceRecoveryRegistry.registerServiceRecoveryRegistry(getServiceRegistryKey(), this);
121         this.interfaceManager = interfaceManager;
122         this.dpnTepStateCache = dpnTepStateCache;
123     }
124
125     private String getServiceRegistryKey() {
126         return GeniusItmTep.class.toString();
127     }
128
129     @Override
130     public void recoverService(String entityId) {
131         if (!entityOwnershipUtils.isEntityOwner(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY)) {
132             return;
133         }
134         LOG.info("Trigerred recovery of ITM Instance - Tep {}", entityId);
135         try {
136             recoverTep(entityId);
137         } catch (InterruptedException e) {
138             LOG.error("ITM Instance tep has not been recovered.", e);
139         }
140     }
141
142     private void recoverTep(String entityId) throws InterruptedException {
143         List<DPNTEPsInfo> tepsToRecover = new ArrayList<>();
144         String[] params = entityId.split(":");
145         if (params.length < 2) {
146             LOG.error("Not enough arguments..Exiting...");
147         } else if (params.length > 2) {
148             LOG.info("Ignoring extra parameter and proceeding...");
149         }
150         String tzName = params[0];
151         String ipAddress = params[1];
152         TransportZone oldTz = ItmUtils.getTransportZoneFromConfigDS(tzName, dataBroker);
153         DPNTEPsInfo dpnTepsToRecover = extractDPNTepsInfo(tzName, ipAddress, oldTz);
154         if (dpnTepsToRecover == null) {
155             LOG.error("Please Enter appropriate arguments for Tep Recovery.");
156             return;
157         } else {
158             tepsToRecover.add(dpnTepsToRecover);
159             //List of Internel tunnels
160             Map<InternalTunnelKey, InternalTunnel> tunnelList = ItmUtils.getInternalTunnelsFromCache(dataBroker);
161             List<String> interfaceListToRecover = new ArrayList<>();
162             LOG.debug("List of tunnel interfaces: {}" , tunnelList);
163
164             if (oldTz != null) {
165                 LOG.trace("Deleting transportzone {}", tzName);
166                 ItmTepRemoveWorker tepRemoveWorker = new ItmTepRemoveWorker(tepsToRecover, null, oldTz,
167                         imdsalApiManager, itmInternalTunnelDeleteWorker, dpntePsInfoCache, txRunner, itmConfig);
168                 jobCoordinator.enqueueJob(tzName, tepRemoveWorker);
169                 AtomicInteger eventCallbackCount = new AtomicInteger(0);
170                 AtomicInteger eventRegistrationCount = new AtomicInteger(0);
171                 if (interfaceManager.isItmDirectTunnelsEnabled()) {
172                     Collection<DpnsTeps> dpnsTeps = dpnTepStateCache.getAllPresent();
173                     for (DpnsTeps dpnTep : dpnsTeps) {
174                         @Nullable Map<RemoteDpnsKey, RemoteDpns> rmtdpns = dpnTep.getRemoteDpns();
175                         for (RemoteDpns remoteDpn : rmtdpns.values()) {
176                             if (remoteDpn.getDestinationDpnId().equals(dpnTepsToRecover.getDPNID())
177                                     || dpnTep.getSourceDpnId().equals(dpnTepsToRecover.getDPNID())) {
178                                 eventRegistrationCount.incrementAndGet();
179                                 interfaceListToRecover.add(remoteDpn.getTunnelName());
180                             }
181                         }
182                     }
183                     LOG.trace("List of tunnels to be recovered : {}", interfaceListToRecover);
184                 } else {
185                     tunnelList.values().stream().filter(internalTunnel -> Objects.equals(internalTunnel
186                             .getDestinationDPN(), dpnTepsToRecover.getDPNID()) || Objects.equals(
187                             internalTunnel.getSourceDPN(), dpnTepsToRecover.getDPNID())).forEach(internalTunnel -> {
188                                 eventRegistrationCount.incrementAndGet();
189                                 interfaceListToRecover.add(String.valueOf(internalTunnel.getTunnelInterfaceNames()));
190                             });
191                 }
192
193                 if (!interfaceListToRecover.isEmpty()) {
194                     interfaceListToRecover.forEach(interfaceName -> {
195                         StateTunnelListKey tlKey = new StateTunnelListKey(interfaceName);
196                         LOG.trace("TunnelStateKey: {} for interface: {}", tlKey, interfaceName);
197                         InstanceIdentifier<StateTunnelList> stListId = ItmUtils.buildStateTunnelListId(tlKey);
198                         eventCallbacks.onRemove(LogicalDatastoreType.OPERATIONAL, stListId, (unused) -> {
199                             LOG.trace("callback event for a delete {} interface instance....", stListId);
200                             // recreating the transportZone
201                             recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
202                             return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
203                         }, Duration.ofMillis(5000), (id) -> {
204                                 LOG.trace("event callback timed out for {} tunnel interface ", interfaceName);
205                                 recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
206                             });
207                     });
208                 } else {
209                     recreateTEP(tzName, tepsToRecover, eventCallbackCount, interfaceListToRecover.size());
210                 }
211             }
212         }
213     }
214
215     private void recreateTEP(String tzName, List tepts, AtomicInteger eventCallbackCount, int registeredEventSize) {
216         eventCallbackCount.incrementAndGet();
217         if (eventCallbackCount.intValue() == registeredEventSize || registeredEventSize == 0) {
218             LOG.info("Re-creating TEP {}", tzName);
219             ItmTepAddWorker tepAddWorker = new ItmTepAddWorker(tepts, null, dataBroker, imdsalApiManager,
220                     itmInternalTunnelAddWorker, itmExternalTunnelAddWorker);
221             jobCoordinator.enqueueJob(tzName, tepAddWorker);
222         }
223     }
224
225     private DPNTEPsInfo extractDPNTepsInfo(String tzName, String ipAddress, TransportZone transportZone) {
226
227         if (transportZone == null) {
228             LOG.error("Transportzone name {} is not valid.", tzName);
229             return null;
230         }
231
232         String portName = itmConfig.getPortname() == null ? ITMConstants.DUMMY_PORT : itmConfig.getPortname();
233         int vlanId = itmConfig.getVlanId() != null ? itmConfig.getVlanId().toJava() : ITMConstants.DUMMY_VLANID;
234
235         for (Vteps vtep : transportZone.getVteps().values()) {
236             if (ipAddress.equals(vtep.getIpAddress().stringValue())) {
237
238                 List<TzMembership> zones = ItmUtils.createTransportZoneMembership(tzName);
239                 LOG.trace("Transportzone {} found match for tep {} to be recovered", transportZone.getZoneName(),
240                         ipAddress);
241
242                 //OfTunnels is false byDefault
243                 TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(vtep.getDpnId(),
244                         IpAddressBuilder.getDefaultInstance(ipAddress), portName, false,
245                         vlanId, zones, transportZone.getTunnelType(),
246                         itmConfig.getDefaultTunnelTos());
247
248                 List<TunnelEndPoints> teps = new ArrayList<>();
249                 teps.add(tunnelEndPoints);
250                 return ItmUtils.createDPNTepInfo(vtep.getDpnId(), teps);
251             }
252         }
253         return null;
254     }
255 }