OF port deletion complete implementation
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / listeners / TransportZoneListener.java
1 /*
2  * Copyright (c) 2016, 2017 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.listeners;
9
10 import com.google.common.util.concurrent.FluentFuture;
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Map.Entry;
17 import java.util.Objects;
18 import java.util.Optional;
19 import java.util.concurrent.ConcurrentHashMap;
20 import java.util.stream.Collectors;
21 import javax.inject.Inject;
22 import javax.inject.Singleton;
23 import org.eclipse.jdt.annotation.NonNull;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.opendaylight.genius.cloudscaler.api.TombstonedNodeManager;
26 import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
27 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
28 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
29 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
30 import org.opendaylight.genius.itm.cache.OfDpnTepConfigCache;
31 import org.opendaylight.genius.itm.cache.OfEndPointCache;
32 import org.opendaylight.genius.itm.cache.OfTepStateCache;
33 import org.opendaylight.genius.itm.cache.OvsBridgeEntryCache;
34 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
35 import org.opendaylight.genius.itm.cache.TunnelStateCache;
36 import org.opendaylight.genius.itm.confighelpers.HwVtep;
37 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker;
38 import org.opendaylight.genius.itm.confighelpers.ItmInternalTunnelAddWorker;
39 import org.opendaylight.genius.itm.confighelpers.ItmInternalTunnelDeleteWorker;
40 import org.opendaylight.genius.itm.confighelpers.ItmOfPortAddWorker;
41 import org.opendaylight.genius.itm.confighelpers.ItmOfPortRemoveWorker;
42 import org.opendaylight.genius.itm.confighelpers.ItmOfTunnelAddWorker;
43 import org.opendaylight.genius.itm.confighelpers.ItmOfTunnelDeleteWorker;
44 import org.opendaylight.genius.itm.confighelpers.ItmTepAddWorker;
45 import org.opendaylight.genius.itm.confighelpers.ItmTepRemoveWorker;
46 import org.opendaylight.genius.itm.confighelpers.ItmTepsNotHostedAddWorker;
47 import org.opendaylight.genius.itm.confighelpers.ItmTepsNotHostedMoveWorker;
48 import org.opendaylight.genius.itm.confighelpers.ItmTepsNotHostedRemoveWorker;
49 import org.opendaylight.genius.itm.globals.ITMConstants;
50 import org.opendaylight.genius.itm.impl.ItmUtils;
51 import org.opendaylight.genius.itm.impl.TunnelMonitoringConfig;
52 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
53 import org.opendaylight.genius.itm.recovery.impl.ItmServiceRecoveryHandler;
54 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
55 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
56 import org.opendaylight.mdsal.binding.api.DataBroker;
57 import org.opendaylight.mdsal.binding.util.Datastore;
58 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
59 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
60 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
61 import org.opendaylight.serviceutils.srm.RecoverableListener;
62 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
63 import org.opendaylight.serviceutils.tools.listener.AbstractSyncDataTreeChangeListener;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.tep.config.OfDpnTep;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.tep.config.OfDpnTepKey;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.NotHostedTransportZones;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZonesBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.TepsInNotHostedTransportZone;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.TepsInNotHostedTransportZoneKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.tepsinnothostedtransportzone.UnknownVteps;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.tepsinnothostedtransportzone.UnknownVtepsBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.not.hosted.transport.zones.tepsinnothostedtransportzone.UnknownVtepsKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.DeviceVteps;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.DeviceVtepsKey;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Vteps;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.VtepsBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.VtepsKey;
86 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
87 import org.opendaylight.yangtools.yang.common.Uint64;
88 import org.slf4j.Logger;
89 import org.slf4j.LoggerFactory;
90
91 /**
92  * This class listens for interface creation/removal/update in Configuration DS.
93  * This is used to handle interfaces for base of-ports.
94  */
95 @Singleton
96 public class TransportZoneListener extends AbstractSyncDataTreeChangeListener<TransportZone>
97         implements RecoverableListener {
98
99     private static final Logger LOG = LoggerFactory.getLogger(TransportZoneListener.class);
100     private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
101
102     private final DataBroker dataBroker;
103     private final JobCoordinator jobCoordinator;
104     private final IMdsalApiManager mdsalManager;
105     private final ItmConfig itmConfig;
106     private final ItmInternalTunnelDeleteWorker itmInternalTunnelDeleteWorker;
107     private final ItmInternalTunnelAddWorker itmInternalTunnelAddWorker;
108     private final ItmExternalTunnelAddWorker externalTunnelAddWorker;
109     private final DPNTEPsInfoCache dpnTEPsInfoCache;
110     private final ManagedNewTransactionRunner txRunner;
111     private final DataTreeEventCallbackRegistrar eventCallbacks;
112     private final TombstonedNodeManager tombstonedNodeManager;
113     private final IInterfaceManager interfaceManager;
114     private final ItmOfTunnelAddWorker itmOfTunnelAddWorker;
115     private final ItmOfTunnelDeleteWorker itmOfTunnelDeleteWorker;
116     private final OfDpnTepConfigCache ofDpnTepConfigCache;
117     private final OfTepStateCache ofTepStateCache;
118
119     @Inject
120     public TransportZoneListener(final DataBroker dataBroker,
121                                  final IMdsalApiManager mdsalManager,
122                                  final ItmConfig itmConfig, final JobCoordinator jobCoordinator,
123                                  final TunnelMonitoringConfig tunnelMonitoringConfig,
124                                  final DPNTEPsInfoCache dpnTEPsInfoCache,
125                                  final TunnelStateCache tunnelStateCache,
126                                  final DirectTunnelUtils directTunnelUtils,
127                                  final DpnTepStateCache dpnTepStateCache, final OvsBridgeEntryCache ovsBridgeEntryCache,
128                                  final OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
129                                  final IInterfaceManager interfaceManager,
130                                  final OfEndPointCache ofEndPointCache,
131                                  final ServiceRecoveryRegistry serviceRecoveryRegistry,
132                                  final DataTreeEventCallbackRegistrar eventCallbacks,
133                                  final TombstonedNodeManager tombstonedNodeManager,
134                                  final OfDpnTepConfigCache ofDpnTepConfigCache,
135                                  final OfTepStateCache ofTepStateCache) {
136         super(dataBroker, LogicalDatastoreType.CONFIGURATION,
137                 InstanceIdentifier.create(TransportZones.class).child(TransportZone.class));
138         this.dataBroker = dataBroker;
139         this.jobCoordinator = jobCoordinator;
140         this.mdsalManager = mdsalManager;
141         this.itmConfig = itmConfig;
142         this.dpnTEPsInfoCache = dpnTEPsInfoCache;
143         this.tombstonedNodeManager = tombstonedNodeManager;
144         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
145         this.eventCallbacks = eventCallbacks;
146         initializeTZNode();
147         this.ofDpnTepConfigCache = ofDpnTepConfigCache;
148         this.ofTepStateCache = ofTepStateCache;
149         this.itmInternalTunnelDeleteWorker = new ItmInternalTunnelDeleteWorker(dataBroker, jobCoordinator,
150                 tunnelMonitoringConfig, interfaceManager, dpnTepStateCache, ovsBridgeEntryCache,
151                 ovsBridgeRefEntryCache, tunnelStateCache, directTunnelUtils, tombstonedNodeManager);
152         this.itmInternalTunnelAddWorker = new ItmInternalTunnelAddWorker(dataBroker, jobCoordinator,
153                 tunnelMonitoringConfig, itmConfig, directTunnelUtils, interfaceManager,
154                 ovsBridgeRefEntryCache, ofEndPointCache, eventCallbacks);
155         this.externalTunnelAddWorker = new ItmExternalTunnelAddWorker(itmConfig, dpnTEPsInfoCache);
156         this.interfaceManager = interfaceManager;
157         this.itmOfTunnelAddWorker = new ItmOfTunnelAddWorker(dataBroker, jobCoordinator,itmConfig,
158                 directTunnelUtils, ovsBridgeRefEntryCache, eventCallbacks);
159         this.itmOfTunnelDeleteWorker = new ItmOfTunnelDeleteWorker(dataBroker, ofDpnTepConfigCache,
160                 tombstonedNodeManager, interfaceManager, directTunnelUtils, ovsBridgeRefEntryCache, ovsBridgeEntryCache,
161                 ofTepStateCache);
162         serviceRecoveryRegistry.addRecoverableListener(ItmServiceRecoveryHandler.getServiceRegistryKey(),
163                 this);
164     }
165
166     @Override
167     public void registerListener() {
168         register();
169     }
170
171     @Override
172     public void deregisterListener() {
173         close();
174     }
175
176     @SuppressWarnings("checkstyle:IllegalCatch")
177     private void initializeTZNode() {
178         InstanceIdentifier<TransportZones> path = InstanceIdentifier.create(TransportZones.class);
179         txRunner.callWithNewReadWriteTransactionAndSubmit(Datastore.CONFIGURATION, tx -> {
180             FluentFuture<Boolean> tzones = tx.exists(path);
181             if (!tzones.get()) {
182                 TransportZonesBuilder tzb = new TransportZonesBuilder();
183                 tx.put(path, tzb.build());
184             }
185         }).isDone();
186     }
187
188     @Override
189     public void remove(@NonNull InstanceIdentifier<TransportZone> instanceIdentifier,
190                        @NonNull TransportZone transportZone) {
191         LOG.debug("Received Transport Zone Remove Event: {}", transportZone);
192         boolean allowTunnelDeletion;
193
194         if (interfaceManager.isItmOfTunnelsEnabled()) {
195             Map<OfDpnTepKey, OfDpnTep> dpnTepMap = createOfTepInfo(transportZone);
196
197             if (!dpnTepMap.isEmpty()) {
198                 jobCoordinator.enqueueJob(transportZone.getZoneName(),
199                         new ItmOfPortRemoveWorker(dpnTepMap, itmOfTunnelDeleteWorker));
200             } else {
201                 EVENT_LOGGER.debug("DPN List in TZ is empty");
202             }
203         } else {
204             // check if TZ received for removal is default-transport-zone,
205             // if yes, then check if it is received from northbound, then
206             // do not entertain request and skip tunnels remove operation
207             // if def-tz removal request is due to def-tz-enabled flag is disabled or
208             // due to change in def-tz-tunnel-type, then allow def-tz tunnels deletion
209             if (ITMConstants.DEFAULT_TRANSPORT_ZONE.equalsIgnoreCase(transportZone.getZoneName())) {
210                 // Get TunnelTypeBase object for tunnel-type configured in config file
211                 Class<? extends TunnelTypeBase> tunType = ItmUtils.getTunnelType(itmConfig.getDefTzTunnelType());
212
213                 if (!itmConfig.isDefTzEnabled() || !Objects.equals(transportZone.getTunnelType(), tunType)) {
214                     allowTunnelDeletion = true;
215                 } else {
216                     // this is case when def-tz removal request is from Northbound.
217                     allowTunnelDeletion = false;
218                     LOG.error("Deletion of {} is an incorrect usage", ITMConstants.DEFAULT_TRANSPORT_ZONE);
219                 }
220             } else {
221                 allowTunnelDeletion = true;
222             }
223
224             if (allowTunnelDeletion) {
225                 //TODO : DPList code can be refactor with new specific class
226                 // which implement TransportZoneValidator
227                 EVENT_LOGGER.debug("ITM-Transportzone,TunnelDeletion {}", transportZone.getZoneName());
228                 List<DPNTEPsInfo> opDpnList = createDPNTepInfo(transportZone);
229                 List<HwVtep> hwVtepList = createhWVteps(transportZone);
230                 LOG.trace("Delete: Invoking deleteTunnels in ItmManager with DpnList {}", opDpnList);
231                 if (!opDpnList.isEmpty() || !hwVtepList.isEmpty()) {
232                     LOG.trace("Delete: Invoking ItmManager with hwVtep List {} ", hwVtepList);
233                     jobCoordinator.enqueueJob(transportZone.getZoneName(),
234                             new ItmTepRemoveWorker(opDpnList, hwVtepList, transportZone, mdsalManager,
235                                     itmInternalTunnelDeleteWorker, dpnTEPsInfoCache, txRunner, itmConfig));
236
237                     if (transportZone.getVteps() != null && !transportZone.getVteps().isEmpty()) {
238                         Map<UnknownVtepsKey, UnknownVteps> unknownVteps =
239                                 convertVtepListToUnknownVtepList(transportZone.getVteps());
240                         LOG.trace("Moving Transport Zone {} to tepsInNotHostedTransportZone Oper Ds.",
241                                 transportZone.getZoneName());
242                         jobCoordinator.enqueueJob(transportZone.getZoneName(),
243                                 new ItmTepsNotHostedAddWorker(unknownVteps, transportZone.getZoneName(),
244                                         dataBroker, txRunner));
245                     }
246                 }
247             }
248         }
249     }
250
251     @Override
252     public void update(@NonNull InstanceIdentifier<TransportZone> instanceIdentifier,
253                        @NonNull TransportZone originalTransportZone, @NonNull TransportZone updatedTransportZone) {
254         LOG.debug("Received Transport Zone Update Event: Old - {}, Updated - {}", originalTransportZone,
255                 updatedTransportZone);
256         EVENT_LOGGER.debug("ITM-Transportzone,UPDATE {}", updatedTransportZone.getZoneName());
257
258         if (interfaceManager.isItmOfTunnelsEnabled()) {
259             updateTransportZone(originalTransportZone, updatedTransportZone);
260         } else {
261             List<DPNTEPsInfo> oldDpnTepsList = createDPNTepInfo(originalTransportZone);
262             List<DPNTEPsInfo> newDpnTepsList = createDPNTepInfo(updatedTransportZone);
263             List<DPNTEPsInfo> oldDpnTepsListcopy = new ArrayList<>();
264             oldDpnTepsListcopy.addAll(oldDpnTepsList);
265             LOG.trace("oldcopy0 {}", oldDpnTepsListcopy);
266             List<DPNTEPsInfo> newDpnTepsListcopy = new ArrayList<>();
267             newDpnTepsListcopy.addAll(newDpnTepsList);
268             LOG.trace("newcopy0 {}", newDpnTepsListcopy);
269
270             oldDpnTepsList.removeAll(newDpnTepsListcopy);
271             newDpnTepsList.removeAll(oldDpnTepsListcopy);
272
273             LOG.trace("oldDpnTepsList {}", oldDpnTepsList);
274             LOG.trace("newDpnTepsList {}", newDpnTepsList);
275             LOG.trace("oldcopy {}", oldDpnTepsListcopy);
276             LOG.trace("newcopy {}", newDpnTepsListcopy);
277             LOG.trace("oldcopy Size {}", oldDpnTepsList.size());
278             LOG.trace("newcopy Size {}", newDpnTepsList.size());
279
280             boolean equalLists = newDpnTepsList.size() == oldDpnTepsList.size()
281                     && newDpnTepsList.containsAll(oldDpnTepsList);
282             LOG.trace("Is List Duplicate {} ", equalLists);
283             if (!newDpnTepsList.isEmpty() && !equalLists) {
284                 LOG.trace("Adding TEPs ");
285                 jobCoordinator.enqueueJob(updatedTransportZone.getZoneName(),
286                         new ItmTepAddWorker(newDpnTepsList, Collections.emptyList(), dataBroker, mdsalManager,
287                                 itmInternalTunnelAddWorker, externalTunnelAddWorker));
288             }
289             if (!oldDpnTepsList.isEmpty() && !equalLists) {
290                 LOG.trace("Removing TEPs ");
291                 jobCoordinator.enqueueJob(updatedTransportZone.getZoneName(),
292                         new ItmTepRemoveWorker(oldDpnTepsList, Collections.emptyList(), originalTransportZone,
293                                 mdsalManager, itmInternalTunnelDeleteWorker, dpnTEPsInfoCache, txRunner, itmConfig));
294             }
295             List<HwVtep> oldHwList = createhWVteps(originalTransportZone);
296             List<HwVtep> newHwList = createhWVteps(updatedTransportZone);
297             List<HwVtep> oldHwListcopy = new ArrayList<>();
298             oldHwListcopy.addAll(oldHwList);
299             LOG.trace("oldHwListcopy0 {}", oldHwListcopy);
300             List<HwVtep> newHwListcopy = new ArrayList<>();
301             newHwListcopy.addAll(newHwList);
302             LOG.trace("newHwListcopy0 {}", newHwListcopy);
303
304             oldHwList.removeAll(newHwListcopy);
305             newHwList.removeAll(oldHwListcopy);
306             LOG.trace("oldHwList {}", oldHwList);
307             LOG.trace("newHwList {}", newHwList);
308             LOG.trace("oldHwListcopy {}", oldHwListcopy);
309             LOG.trace("newHwListcopy {}", newHwListcopy);
310             if (!newHwList.isEmpty()) {
311                 LOG.trace("Adding HW TEPs ");
312                 jobCoordinator.enqueueJob(updatedTransportZone.getZoneName(),
313                         new ItmTepAddWorker(Collections.emptyList(),
314                         newHwList, dataBroker, mdsalManager, itmInternalTunnelAddWorker, externalTunnelAddWorker));
315             }
316             if (!oldHwList.isEmpty()) {
317                 LOG.trace("Removing HW TEPs ");
318                 jobCoordinator.enqueueJob(updatedTransportZone.getZoneName(),
319                         new ItmTepRemoveWorker(Collections.emptyList(), oldHwList, originalTransportZone, mdsalManager,
320                                 itmInternalTunnelDeleteWorker, dpnTEPsInfoCache, txRunner, itmConfig));
321             }
322         }
323     }
324
325     @Override
326     public void add(@NonNull TransportZone transportZone) {
327         LOG.debug("Received Transport Zone Add Event: {}", transportZone);
328         EVENT_LOGGER.debug("ITM-Transportzone,ADD {}", transportZone.getZoneName());
329         if (interfaceManager.isItmOfTunnelsEnabled()) {
330             Map<OfDpnTepKey, OfDpnTep> dpnTepMap = createOfTepInfo(transportZone);
331
332             if (!dpnTepMap.isEmpty()) {
333                 jobCoordinator.enqueueJob(transportZone.getZoneName(),
334                         new ItmOfPortAddWorker(dpnTepMap, itmOfTunnelAddWorker));
335             } else {
336                 EVENT_LOGGER.debug("DPN List in TZ is empty");
337             }
338         } else {
339             List<DPNTEPsInfo> opDpnList = createDPNTepInfo(transportZone);
340             //avoiding adding duplicates from nothosted to new dpnlist.
341             List<DPNTEPsInfo> duplicateFound = new ArrayList<>();
342             List<DPNTEPsInfo> notHostedDpnList = getDPNTepInfoFromNotHosted(transportZone, opDpnList);
343             for (DPNTEPsInfo notHostedDPN : notHostedDpnList) {
344                 for (DPNTEPsInfo newlyAddedDPN : opDpnList) {
345                     if (newlyAddedDPN.getDPNID().compareTo(notHostedDPN.getDPNID()) == 0
346                             || newlyAddedDPN.getTunnelEndPoints().get(0).getIpAddress()
347                             .equals(notHostedDPN.getTunnelEndPoints().get(0).getIpAddress())) {
348                         duplicateFound.add(notHostedDPN);
349                     }
350                 }
351             }
352             notHostedDpnList.removeAll(duplicateFound);
353             opDpnList.addAll(notHostedDpnList);
354
355             List<HwVtep> hwVtepList = createhWVteps(transportZone);
356             LOG.trace("Add: Operational dpnTepInfo - Before invoking ItmManager {}", opDpnList);
357             if (!opDpnList.isEmpty() || !hwVtepList.isEmpty()) {
358                 LOG.trace("Add: Invoking ItmManager with DPN List {} ", opDpnList);
359                 LOG.trace("Add: Invoking ItmManager with hwVtep List {} ", hwVtepList);
360                 jobCoordinator.enqueueJob(transportZone.getZoneName(),
361                         new ItmTepAddWorker(opDpnList, hwVtepList, dataBroker, mdsalManager, itmInternalTunnelAddWorker,
362                                 externalTunnelAddWorker));
363             }
364         }
365     }
366
367     private List<DPNTEPsInfo> getDPNTepInfoFromNotHosted(TransportZone tzNew, List<DPNTEPsInfo> opDpnList) {
368         List<DPNTEPsInfo> notHostedOpDpnList = new ArrayList<>();
369         if (isNewTZExistInNotHostedTZ(tzNew)) {
370             notHostedOpDpnList = createDPNTepInfoFromNotHosted(tzNew, opDpnList);
371         }
372         return notHostedOpDpnList;
373     }
374
375     private void updateTransportZone(TransportZone originalTransportZone, TransportZone updatedTransportZone) {
376         Map<OfDpnTepKey, OfDpnTep> oldDpnTepMap = createOfTepInfo(originalTransportZone);
377         Map<OfDpnTepKey, OfDpnTep> newDpnTepMap  = createOfTepInfo(updatedTransportZone);
378         List<OfDpnTep> oldDpnTepList = oldDpnTepMap.values().stream().collect(Collectors.toList());
379         List<OfDpnTep> newDpnTepList = newDpnTepMap.values().stream().collect(Collectors.toList());
380         List<OfDpnTep> oldDpnTepListcopy = new ArrayList<>();
381         oldDpnTepListcopy.addAll(oldDpnTepList);
382         List<OfDpnTep> newDpnTepListcopy = new ArrayList<>();
383         newDpnTepListcopy.addAll(newDpnTepList);
384
385         oldDpnTepList.removeAll(newDpnTepListcopy);
386         newDpnTepList.removeAll(oldDpnTepListcopy);
387         oldDpnTepMap.clear();
388         newDpnTepMap.clear();
389         for (OfDpnTep tep:oldDpnTepList) {
390             oldDpnTepMap.put(tep.key(), tep);
391         }
392
393         for (OfDpnTep tep:newDpnTepList) {
394             newDpnTepMap.put(tep.key(), tep);
395         }
396
397         boolean equalLists = newDpnTepList.size() == oldDpnTepList.size()
398                 && newDpnTepList.containsAll(oldDpnTepList);
399         LOG.trace("Is List Duplicate? {} ", equalLists);
400
401         if (!newDpnTepList.isEmpty() && !equalLists) {
402             jobCoordinator.enqueueJob(updatedTransportZone.getZoneName(),
403                     new ItmOfPortAddWorker(newDpnTepMap, itmOfTunnelAddWorker));
404         }
405
406         if (!oldDpnTepList.isEmpty() && !equalLists) {
407             jobCoordinator.enqueueJob(updatedTransportZone.getZoneName(),
408                     new ItmOfPortRemoveWorker(oldDpnTepMap, itmOfTunnelDeleteWorker));
409         }
410     }
411
412     private List<DPNTEPsInfo> createDPNTepInfoFromNotHosted(TransportZone tzNew, List<DPNTEPsInfo> opDpnList) {
413         Map<Uint64, List<TunnelEndPoints>> mapNotHostedDPNToTunnelEndpt = new ConcurrentHashMap<>();
414         List<DPNTEPsInfo> notHostedDpnTepInfo = new ArrayList<>();
415         String newZoneName = tzNew.getZoneName();
416         List<TzMembership> zones = ItmUtils.createTransportZoneMembership(newZoneName);
417         Class<? extends TunnelTypeBase> tunnelType  = tzNew.getTunnelType();
418
419         TepsInNotHostedTransportZone tepsInNotHostedTransportZone = getNotHostedTransportZone(newZoneName).get();
420         if (tepsInNotHostedTransportZone == null) {
421             return notHostedDpnTepInfo;
422         }
423         @Nullable Map<UnknownVtepsKey, UnknownVteps> unVtepsLst = tepsInNotHostedTransportZone.getUnknownVteps();
424         List<Vteps> vtepsList = new ArrayList<>();
425         if (unVtepsLst != null && !unVtepsLst.isEmpty()) {
426             for (UnknownVteps vteps : unVtepsLst.values()) {
427                 Uint64 dpnID = vteps.getDpnId();
428                 IpAddress ipAddress = vteps.getIpAddress();
429                 String portName = itmConfig.getPortname() == null ? ITMConstants.DUMMY_PORT : itmConfig.getPortname();
430                 int vlanId = itmConfig.getVlanId() != null ? itmConfig.getVlanId().toJava()
431                                                              : ITMConstants.DUMMY_VLANID;
432                 boolean useOfTunnel = ItmUtils.falseIfNull(vteps.isOfTunnel());
433                 String tos = vteps.getOptionTunnelTos();
434                 if (tos == null) {
435                     tos = itmConfig.getDefaultTunnelTos();
436                 }
437                 TunnelEndPoints tunnelEndPoints =
438                         ItmUtils.createTunnelEndPoints(dpnID, ipAddress, portName, useOfTunnel, vlanId, zones,
439                                 tunnelType, tos);
440                 List<TunnelEndPoints> tunnelEndPointsList = mapNotHostedDPNToTunnelEndpt.get(dpnID);
441                 if (tunnelEndPointsList != null) {
442                     tunnelEndPointsList.add(tunnelEndPoints);
443                 } else {
444                     tunnelEndPointsList = new ArrayList<>();
445                     tunnelEndPointsList.add(tunnelEndPoints);
446                     mapNotHostedDPNToTunnelEndpt.put(dpnID, tunnelEndPointsList);
447                 }
448                 Vteps newVtep = createVtepFromUnKnownVteps(dpnID,ipAddress);
449                 vtepsList.add(newVtep);
450
451                 // Enqueue 'remove TEP from TepsNotHosted list' operation
452                 // into DataStoreJobCoordinator
453                 jobCoordinator.enqueueJob(newZoneName,
454                         new ItmTepsNotHostedRemoveWorker(newZoneName, ipAddress, dpnID, dataBroker, txRunner));
455             }
456         }
457         //avoiding duplicate vteps which are already present in dpn list pushed from NBI
458         List<Vteps> foundDuplicatevtepsList = new ArrayList<>();
459         for (Vteps notHostedVteps:vtepsList) {
460             for (DPNTEPsInfo newlyAddedDPN:opDpnList) {
461                 if (notHostedVteps.getDpnId().compareTo(newlyAddedDPN.getDPNID()) == 0
462                         || newlyAddedDPN.getTunnelEndPoints().get(0).getIpAddress()
463                         .equals(notHostedVteps.getIpAddress())) {
464                     foundDuplicatevtepsList.add(notHostedVteps);
465                 }
466             }
467         }
468         vtepsList.removeAll(foundDuplicatevtepsList);
469
470         // Enqueue 'add TEP received from southbound OVSDB into ITM config DS' operation
471         // into DataStoreJobCoordinator
472         jobCoordinator.enqueueJob(newZoneName, new ItmTepsNotHostedMoveWorker(vtepsList, newZoneName, txRunner));
473
474         if (mapNotHostedDPNToTunnelEndpt.size() > 0) {
475             for (Entry<Uint64, List<TunnelEndPoints>> entry: mapNotHostedDPNToTunnelEndpt.entrySet()) {
476                 DPNTEPsInfo newDpnTepsInfo = ItmUtils.createDPNTepInfo(entry.getKey(), entry.getValue());
477                 notHostedDpnTepInfo.add(newDpnTepsInfo);
478             }
479         }
480         return notHostedDpnTepInfo;
481
482     }
483
484     private Vteps createVtepFromUnKnownVteps(Uint64 dpnID, IpAddress ipAddress) {
485         VtepsKey vtepkey = new VtepsKey(dpnID);
486         Vteps vtepObj = new VtepsBuilder().setDpnId(dpnID).setIpAddress(ipAddress).withKey(vtepkey)
487                 .build();
488         return vtepObj;
489     }
490
491     private  Map<UnknownVtepsKey, UnknownVteps> convertVtepListToUnknownVtepList(Map<VtepsKey, Vteps> vteps) {
492         Map<UnknownVtepsKey, UnknownVteps> unknownVtepsList = new HashMap<>();
493         for (Vteps vtep : vteps.values()) {
494             UnknownVtepsKey vtepkey = new UnknownVtepsKey(vtep.getDpnId());
495             UnknownVteps vtepObj =
496                     new UnknownVtepsBuilder().setDpnId(vtep.getDpnId()).setIpAddress(vtep.getIpAddress())
497                             .withKey(vtepkey).setOfTunnel(vtep.isOptionOfTunnel()).build();
498             //unknownVtepsList.values().add(vtepObj);
499             unknownVtepsList.put(vtepObj.key(),vtepObj);
500         }
501         return unknownVtepsList;
502     }
503
504     private boolean isNewTZExistInNotHostedTZ(TransportZone tzNew) {
505         boolean isPresent = false;
506         if (getNotHostedTransportZone(tzNew.getZoneName()).isPresent()) {
507             isPresent = true;
508         }
509         return isPresent;
510     }
511
512     public  Optional<TepsInNotHostedTransportZone> getNotHostedTransportZone(String transportZoneName) {
513         InstanceIdentifier<TepsInNotHostedTransportZone> notHostedTzPath = InstanceIdentifier
514                 .builder(NotHostedTransportZones.class).child(TepsInNotHostedTransportZone.class,
515                         new TepsInNotHostedTransportZoneKey(transportZoneName)).build();
516         Optional<TepsInNotHostedTransportZone> tepsInNotHostedTransportZoneOptional =
517                 ItmUtils.read(LogicalDatastoreType.OPERATIONAL, notHostedTzPath, dataBroker);
518         return tepsInNotHostedTransportZoneOptional;
519     }
520
521     private List<DPNTEPsInfo> createDPNTepInfo(TransportZone transportZone) {
522
523         Map<Uint64, List<TunnelEndPoints>> mapDPNToTunnelEndpt = new ConcurrentHashMap<>();
524         List<DPNTEPsInfo> dpnTepInfo = new ArrayList<>();
525         List<TzMembership> zones = ItmUtils.createTransportZoneMembership(transportZone.getZoneName());
526         Class<? extends TunnelTypeBase> tunnelType = transportZone.getTunnelType();
527         LOG.trace("Transport Zone_name: {}", transportZone.getZoneName());
528         @Nullable Map<VtepsKey, Vteps> vtepsList = transportZone.getVteps();
529
530         String portName = itmConfig.getPortname() == null ? ITMConstants.DUMMY_PORT : itmConfig.getPortname();
531         int vlanId = itmConfig.getVlanId() != null ? itmConfig.getVlanId().toJava() : ITMConstants.DUMMY_VLANID;
532
533         if (vtepsList != null && !vtepsList.isEmpty()) {
534             for (Vteps vteps : vtepsList.values()) {
535                 Uint64 dpnID = vteps.getDpnId();
536                 IpAddress ipAddress = vteps.getIpAddress();
537                 boolean useOfTunnel = itmConfig.isUseOfTunnels();
538                 String tos = vteps.getOptionTunnelTos();
539                 if (tos == null) {
540                     tos = itmConfig.getDefaultTunnelTos();
541                 }
542                 LOG.trace("DpnID: {}, ipAddress: {}", dpnID, ipAddress);
543                 TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(dpnID, ipAddress, portName,
544                         useOfTunnel, vlanId, zones, tunnelType, tos);
545                 EVENT_LOGGER.debug("ITM-createDPNTepInfo for {} {}", dpnID, ipAddress);
546                 List<TunnelEndPoints> tunnelEndPointsList = mapDPNToTunnelEndpt.get(dpnID);
547                 if (tunnelEndPointsList != null) {
548                     LOG.trace("Existing DPN info list in the Map: {} ", dpnID);
549                     tunnelEndPointsList.add(tunnelEndPoints);
550                 } else {
551                     LOG.trace("Adding new DPN info list to the Map: {} ", dpnID);
552                     tunnelEndPointsList = new ArrayList<>();
553                     tunnelEndPointsList.add(tunnelEndPoints);
554                     mapDPNToTunnelEndpt.put(dpnID, tunnelEndPointsList);
555
556                 }
557             }
558         }
559
560         if (!mapDPNToTunnelEndpt.isEmpty()) {
561             LOG.trace("List of dpns in the Map: {} ", mapDPNToTunnelEndpt.keySet());
562             for (Entry<Uint64, List<TunnelEndPoints>> entry : mapDPNToTunnelEndpt.entrySet()) {
563                 DPNTEPsInfo newDpnTepsInfo = ItmUtils.createDPNTepInfo(entry.getKey(), entry.getValue());
564                 dpnTepInfo.add(newDpnTepsInfo);
565             }
566         }
567         return dpnTepInfo;
568     }
569
570     private List<HwVtep> createhWVteps(TransportZone transportZone) {
571         List<HwVtep> hwVtepsList = new ArrayList<>();
572
573         String zoneName = transportZone.getZoneName();
574         Class<? extends TunnelTypeBase> tunnelType = transportZone.getTunnelType();
575         LOG.trace("Transport Zone_name: {}", zoneName);
576         @Nullable Map<DeviceVtepsKey, DeviceVteps> deviceVtepsList = transportZone.getDeviceVteps();
577         if (deviceVtepsList != null) {
578             for (DeviceVteps vteps : deviceVtepsList.values()) {
579                 String topologyId = vteps.getTopologyId();
580                 String nodeId = vteps.getNodeId();
581                 IpAddress ipAddress = vteps.getIpAddress();
582                 LOG.trace("topo-id: {}, node-id: {}, ipAddress: {}", topologyId, nodeId, ipAddress);
583                 HwVtep hwVtep = ItmUtils.createHwVtepObject(topologyId, nodeId, ipAddress,
584                         tunnelType, transportZone);
585
586                 LOG.trace("Adding new HwVtep {} info ", hwVtep.getHwIp());
587                 hwVtepsList.add(hwVtep);
588             }
589         }
590         LOG.trace("returning hwvteplist {}", hwVtepsList);
591         return hwVtepsList;
592     }
593
594     private Map<OfDpnTepKey, OfDpnTep> createOfTepInfo(TransportZone transportZone) {
595         String tunnelType = ItmUtils.convertTunnelTypetoString(transportZone.getTunnelType());
596         Map<OfDpnTepKey, OfDpnTep> dpnTepMap = new HashMap<>();
597         Map<VtepsKey, Vteps> vtepsMap = transportZone.getVteps();
598         if (vtepsMap != null && !vtepsMap.isEmpty()) {
599             for (Vteps vteps : vtepsMap.values()) {
600                 Uint64 dpnID = vteps.getDpnId();
601                 IpAddress ipAddress = vteps.getIpAddress();
602                 String ofPortName = ItmUtils.generateOfPortName(dpnID, ipAddress, tunnelType);
603                 OfDpnTep dpnTep = ItmUtils.createDpnOFTepInfo(dpnID, ipAddress, ofPortName,
604                         transportZone.getTunnelType());
605                 dpnTepMap.put(dpnTep.key(), dpnTep);
606             }
607         }
608         return dpnTepMap;
609     }
610 }