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