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