Remove unused references to DataChangeListener
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / listeners / VtepConfigSchemaListener.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
9 package org.opendaylight.genius.itm.listeners;
10
11 import com.google.common.base.Optional;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.Objects;
16 import javax.annotation.PostConstruct;
17 import javax.annotation.PreDestroy;
18 import javax.inject.Inject;
19 import javax.inject.Singleton;
20 import org.apache.commons.lang3.StringUtils;
21 import org.apache.commons.net.util.SubnetUtils;
22 import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
26 import org.opendaylight.genius.itm.cli.TepCommandHelper;
27 import org.opendaylight.genius.itm.cli.TepException;
28 import org.opendaylight.genius.itm.globals.ITMConstants;
29 import org.opendaylight.genius.itm.impl.ItmUtils;
30 import org.opendaylight.genius.mdsalutil.MDSALUtil;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.VtepConfigSchemas;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.vtep.config.schemas.VtepConfigSchema;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.vtep.config.schemas.VtepConfigSchemaBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.vtep.config.schemas.vtep.config.schema.DpnIds;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.vtep.ip.pools.VtepIpPool;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.vtep.ip.pools.VtepIpPoolBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsKey;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.VtepsKey;
48 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 /**
53  * The listener class interested in processing data change on.
54  * {@code VtepConfigSchema} objects.
55  *
56  * @see VtepConfigSchema
57  */
58 @Singleton
59 public class VtepConfigSchemaListener extends AsyncDataTreeChangeListenerBase<VtepConfigSchema,
60         VtepConfigSchemaListener> implements AutoCloseable {
61
62     /** The Constant LOG. */
63     private static final Logger LOG = LoggerFactory.getLogger(VtepConfigSchemaListener.class);
64
65     /** The data broker. */
66     private final DataBroker dataBroker;
67     /** Blueprint XML config file handle. */
68     private final ItmConfig itmConfig;
69
70     /**
71      * Instantiates a new vtep config schema listener.
72      *
73      * @param dataBroker
74      *            the db
75      * @param itmConfig
76      *            ITM config file handle
77      */
78     @Inject
79     public VtepConfigSchemaListener(final DataBroker dataBroker, final ItmConfig itmConfig) {
80         super(VtepConfigSchema.class, VtepConfigSchemaListener.class);
81         this.dataBroker = dataBroker;
82         this.itmConfig = itmConfig;
83     }
84
85     @PostConstruct
86     public void start() {
87         registerListener(LogicalDatastoreType.CONFIGURATION, this.dataBroker);
88         LOG.info("VtepConfigSchemaListener Started");
89     }
90
91     /*
92      * (non-Javadoc)
93      *
94      * @see java.lang.AutoCloseable#close()
95      */
96     @SuppressWarnings("checkstyle:IllegalCatch")
97     @Override
98     @PreDestroy
99     public void close() {
100         LOG.info("VtepConfigSchemaListener Closed");
101     }
102
103     /**
104      * Gets the wild card path.
105      *
106      * @return the wild card path
107      */
108     @Override
109     public InstanceIdentifier<VtepConfigSchema> getWildCardPath() {
110         return ItmUtils.getVtepConfigSchemaIdentifier();
111     }
112
113     /*
114      * (non-Javadoc)
115      *
116      * @see
117      * org.opendaylight.genius.mdsalutil.AbstractDataChangeListener#remove(
118      * org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
119      * org.opendaylight.yangtools.yang.binding.DataObject)
120      */
121     @SuppressWarnings("checkstyle:IllegalCatch")
122     @Override
123     protected void remove(InstanceIdentifier<VtepConfigSchema> identifier, VtepConfigSchema schema) {
124         LOG.trace("Received notification for VTEP config schema [{}] deleted.", schema.getSchemaName());
125         try {
126             List<BigInteger> lstDpnIds = ItmUtils.getDpnIdList(schema.getDpnIds());
127             if (lstDpnIds != null && !lstDpnIds.isEmpty()) {
128                 deleteVteps(schema, lstDpnIds);
129             }
130
131             // Delete IP pool corresponding to schema
132             // TODO: Ensure no schema exists with same subnet before deleting
133             String subnetCidr = ItmUtils.getSubnetCidrAsString(schema.getSubnet());
134             deleteVtepIpPool(subnetCidr);
135         } catch (Exception e) {
136             String error = "Failed to handle DCN for delete VtepConfigSchema: " + schema;
137             LOG.error(error, e);
138         }
139     }
140
141     /*
142      * (non-Javadoc)
143      *
144      * @see
145      * org.opendaylight.genius.mdsalutil.AbstractDataChangeListener#update(
146      * org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
147      * org.opendaylight.yangtools.yang.binding.DataObject,
148      * org.opendaylight.yangtools.yang.binding.DataObject)
149      */
150     @SuppressWarnings("checkstyle:IllegalCatch")
151     @Override
152     protected void update(InstanceIdentifier<VtepConfigSchema> identifier, VtepConfigSchema original,
153                           VtepConfigSchema updated) {
154         LOG.error("Received DCN for updating VTEP Original schema: {}. Updated schema: {}", original, updated);
155         //LOG.trace("Received notification for VTEP config schema [{}] updated.", original.getSchemaName());
156
157         try {
158             VtepConfigSchema orignalSchema = ItmUtils.validateVtepConfigSchema(original);
159             VtepConfigSchema updatedSchema = ItmUtils.validateVtepConfigSchema(updated);
160
161             if (doesDeleteAndAddSchemaRequired(original, updated)) {
162                 LOG.error("Failed to handle DCN for updating VTEP schema {}. Original schema: {}. Updated schema: {}",
163                         original, updated);
164                 // TODO: handle updates
165                 return;
166             }
167
168             handleUpdateOfDpnIds(orignalSchema, updatedSchema);
169
170         } catch (Exception e) {
171             String error = "Failed to handle DCN for update VtepConfigSchema original:"
172                     + original + ", updated: " + updated;
173             LOG.error(error, e);
174         }
175     }
176
177     /*
178      * (non-Javadoc)
179      *
180      * @see
181      * org.opendaylight.genius.mdsalutil.AbstractDataChangeListener#add(org.
182      * opendaylight.yangtools.yang.binding.InstanceIdentifier,
183      * org.opendaylight.yangtools.yang.binding.DataObject)
184      */
185     @SuppressWarnings("checkstyle:IllegalCatch")
186     @Override
187     protected void add(InstanceIdentifier<VtepConfigSchema> identifier, VtepConfigSchema schema) {
188         // Construct the transport zones from the provided schemas and push it
189         // to config DS.
190         LOG.trace("Add VtepConfigSchema: key: {} , value: {}", identifier, schema);
191
192         try {
193             VtepConfigSchema validatedSchema = ItmUtils.validateForAddVtepConfigSchema(schema,
194                     getAllVtepConfigSchemas());
195
196             VtepIpPool vtepIpPool = processAvailableIps(validatedSchema);
197             addVteps(validatedSchema, vtepIpPool);
198         } catch (Exception e) {
199             LOG.error("Failed to handle DCN for add VtepConfigSchema", e);
200         }
201     }
202
203     @Override
204     protected VtepConfigSchemaListener getDataTreeChangeListener() {
205         return VtepConfigSchemaListener.this;
206     }
207
208     /**
209      * Handle update of dpn ids.
210      *
211      * @param original
212      *            the original
213      * @param updated
214      *            the updated
215      */
216     private void handleUpdateOfDpnIds(VtepConfigSchema original, VtepConfigSchema updated) {
217         // Handling add/delete DPNs from schema
218         List<DpnIds> originalDpnIds = original.getDpnIds() == null ? new ArrayList<>()
219                 : original.getDpnIds();
220         List<DpnIds> updatedDpnIds = updated.getDpnIds() == null ? new ArrayList<>()
221                 : updated.getDpnIds();
222
223         handleDeletedDpnsFromSchema(original, originalDpnIds, updatedDpnIds);
224         handleNewlyAddedDpnsToSchema(original, originalDpnIds, updatedDpnIds);
225     }
226
227     /**
228      * Does delete and add schema required.
229      *
230      * @param original
231      *            the original
232      * @param updated
233      *            the updated
234      * @return true, if successful
235      */
236     private boolean doesDeleteAndAddSchemaRequired(VtepConfigSchema original, VtepConfigSchema updated) {
237         boolean delnAddRequired = false;
238         if (!StringUtils.equalsIgnoreCase(original.getPortName(), updated.getPortName())) {
239             delnAddRequired = true;
240         } else if (!Objects.equals(original.getVlanId(), updated.getVlanId())) {
241             delnAddRequired = true;
242         } else if (original.getSubnet() != null && !original.getSubnet().equals(updated.getSubnet())) {
243             delnAddRequired = true;
244         } else if (original.getGatewayIp() != null && !original.getGatewayIp().equals(updated.getGatewayIp())) {
245             delnAddRequired = true;
246         } else if (!StringUtils.equalsIgnoreCase(original.getTransportZoneName(), updated.getTransportZoneName())) {
247             delnAddRequired = true;
248         } else if (!original.getTunnelType().equals(updated.getTunnelType())) {
249             delnAddRequired = true;
250         }
251         return delnAddRequired;
252     }
253
254     /**
255      * Handle newly added dpns to schema.
256      *
257      * @param original
258      *            the original
259      * @param originalDpnIds
260      *            the original dpn ids
261      * @param updatedDpnIds
262      *            the updated dpn ids
263      */
264     private void handleNewlyAddedDpnsToSchema(VtepConfigSchema original, List<DpnIds> originalDpnIds,
265                                               List<DpnIds> updatedDpnIds) {
266         LOG.trace("Handle Addition of DPNs from VTEP Original Dpn: {}. Updated Dpn: {}",
267                 originalDpnIds, updatedDpnIds) ;
268         ArrayList<DpnIds> newlyAddedDpns = new ArrayList<>(updatedDpnIds);
269         newlyAddedDpns.removeAll(originalDpnIds);
270         LOG.debug("Newly added DPNs {} to VTEP config schema [{}].", newlyAddedDpns, original.getSchemaName());
271         if (!newlyAddedDpns.isEmpty()) {
272             VtepConfigSchema diffSchema = new VtepConfigSchemaBuilder(original).setDpnIds(newlyAddedDpns).build();
273             String subnetCidr = ItmUtils.getSubnetCidrAsString(original.getSubnet());
274             VtepIpPool vtepIpPool = getVtepIpPool(subnetCidr);
275             LOG.debug("Adding of DPNs in Diff Schema: {}", diffSchema) ;
276             addVteps(diffSchema, vtepIpPool);
277         }
278     }
279
280     /**
281      * Handle deleted dpns from schema.
282      *
283      * @param original
284      *            the original
285      * @param originalDpnIds
286      *            the original dpn ids
287      * @param updatedDpnIds
288      *            the updated dpn ids
289      */
290     private void handleDeletedDpnsFromSchema(VtepConfigSchema original, List<DpnIds> originalDpnIds,
291                                              List<DpnIds> updatedDpnIds) {
292         ArrayList<DpnIds> deletedDpns = new ArrayList<>(originalDpnIds);
293         deletedDpns.removeAll(updatedDpnIds);
294         LOG.debug("DPNs to be removed DPNs {} from VTEP config schema [{}].", deletedDpns, original.getSchemaName());
295         if (!deletedDpns.isEmpty()) {
296             LOG.debug("Deleting of DPNs from VTEP Schema: {}. To be deleted Dpns: {}", original, deletedDpns) ;
297             deleteVteps(original, ItmUtils.getDpnIdList(deletedDpns));
298         }
299     }
300
301     /**
302      * Gets all vtep config schemas.
303      *
304      * @return the all vtep config schemas
305      */
306     private List<VtepConfigSchema> getAllVtepConfigSchemas() {
307         return ItmUtils.read(LogicalDatastoreType.CONFIGURATION, ItmUtils.getVtepConfigSchemasIdentifier(),
308                 this.dataBroker).toJavaUtil().map(VtepConfigSchemas::getVtepConfigSchema).orElse(null);
309     }
310
311     /**
312      * Adds the vteps.
313      *
314      * @param schema
315      *            the schema
316      * @param vtepIpPool
317      *            the vtep ip pool
318      */
319     private void addVteps(VtepConfigSchema schema, VtepIpPool vtepIpPool) {
320         if (schema.getDpnIds() == null || schema.getDpnIds().isEmpty()) {
321             LOG.debug("DPN list is empty, skipping addVteps for schema: {}", schema);
322             return;
323         }
324
325         String subnetCidr = ItmUtils.getSubnetCidrAsString(schema.getSubnet());
326         if (vtepIpPool == null) {
327             LOG.error("VTEP config pool not found for subnetCidr {}. Failed to add VTEPs for schema {}", subnetCidr,
328                     schema);
329             return;
330         }
331         TepCommandHelper tepCommandHelper = new TepCommandHelper(this.dataBroker, itmConfig);
332         // Check this later
333         String tunType ;
334         Class<? extends TunnelTypeBase> tunnelType = schema.getTunnelType() ;
335         if (tunnelType.equals(TunnelTypeVxlan.class)) {
336             tunType = ITMConstants.TUNNEL_TYPE_VXLAN;
337         } else {
338             tunType = ITMConstants.TUNNEL_TYPE_GRE;
339         }
340         tepCommandHelper.configureTunnelType(schema.getTransportZoneName(),
341                 StringUtils.upperCase(tunType));
342
343         List<IpAddress> availableIps = vtepIpPool.getAvailableIpaddress();
344         List<IpAddress> newlyAllocatedIps = new ArrayList<>();
345         List<BigInteger> skippedDpnIds = new ArrayList<>();
346
347         String gatewayIp = handleGatewayIp(schema.getGatewayIp());
348         for (BigInteger dpnId : ItmUtils.getDpnIdList(schema.getDpnIds())) {
349             IpAddress ipAddress = getAnAvailableIP(availableIps);
350             if (ipAddress == null) {
351                 skippedDpnIds.add(dpnId);
352                 continue;
353             }
354             try {
355                 tepCommandHelper.createLocalCache(dpnId, schema.getPortName(), schema.getVlanId(),
356                         String.valueOf(ipAddress.getValue()), subnetCidr, gatewayIp,
357                         schema.getTransportZoneName(), null);
358             } catch (TepException e) {
359                 LOG.error(e.getMessage());
360             }
361             newlyAllocatedIps.add(ipAddress);
362         }
363         if (!skippedDpnIds.isEmpty()) {
364             LOG.error("No available IP addresses in the VTEP config pool {}, skipping VTEP configurations for DPN's {}",
365                     subnetCidr, skippedDpnIds);
366         }
367
368         if (!newlyAllocatedIps.isEmpty()) {
369             LOG.debug("Delete OnCommit and buildTeps in NewlyAddedDpns");
370             tepCommandHelper.deleteOnCommit();
371             tepCommandHelper.buildTeps();
372             allocateIpAddresses(newlyAllocatedIps, vtepIpPool, subnetCidr);
373         }
374     }
375
376     /**
377      * Handle gateway ip.
378      *
379      * @param gatewayIp
380      *            the gateway ip
381      * @return the string
382      */
383     private String handleGatewayIp(IpAddress gatewayIp) {
384         String strGatewayIp = gatewayIp == null ? null : String.valueOf(gatewayIp.getValue());
385         if (StringUtils.isBlank(strGatewayIp) || StringUtils.equals(ITMConstants.DUMMY_IP_ADDRESS, strGatewayIp)) {
386             // To avoid a validation exception in TepCommandHelper
387             strGatewayIp = null;
388         }
389         return strGatewayIp;
390     }
391
392     /**
393      * Delete vteps.
394      *
395      * @param schema
396      *            the schema
397      * @param lstDpnIdsToBeDeleted
398      *            the dpn ids list to be deleted
399      */
400     private void deleteVteps(VtepConfigSchema schema, List<BigInteger> lstDpnIdsToBeDeleted) {
401         TepCommandHelper tepCommandHelper = new TepCommandHelper(this.dataBroker, itmConfig);
402         List<IpAddress> freeIps = new ArrayList<>();
403
404         String subnetCidr = ItmUtils.getSubnetCidrAsString(schema.getSubnet());
405         String gatewayIp = handleGatewayIp(schema.getGatewayIp());
406
407         for (BigInteger dpnId : lstDpnIdsToBeDeleted) {
408             VtepsKey vtepkey = new VtepsKey(dpnId, schema.getPortName());
409
410             InstanceIdentifier<Vteps> vpath = InstanceIdentifier.builder(TransportZones.class)
411                     .child(TransportZone.class, new TransportZoneKey(schema.getTransportZoneName()))
412                     .child(Subnets.class, new SubnetsKey(schema.getSubnet())).child(Vteps.class, vtepkey).build();
413
414             Vteps vtep = null;
415             Optional<Vteps> vtepOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, vpath, dataBroker);
416             if (vtepOptional.isPresent()) {
417                 vtep = vtepOptional.get();
418             } else {
419                 LOG.warn("VTEP doesn't exist for DPN [{}] and port [{}].", dpnId, schema.getPortName());
420                 continue;
421             }
422
423             IpAddress ipAddress = vtep.getIpAddress();
424             try {
425                 tepCommandHelper.deleteVtep(dpnId, vtep.getPortname(), schema.getVlanId(),
426                     String.valueOf(ipAddress.getValue()), subnetCidr, gatewayIp, schema.getTransportZoneName(), null);
427             } catch (TepException e) {
428                 LOG.error(e.getMessage());
429             }
430
431             freeIps.add(ipAddress);
432         }
433         LOG.debug("Delete OnCommit in NewlyAddedDpns");
434         tepCommandHelper.deleteOnCommit();
435         deAllocateIpAddresses(freeIps, subnetCidr);
436     }
437
438     /**
439      * Calculate available IPs from the subnet mask specified in the schema.
440      * Pushes the available and allocated IP address to config DS.
441      *
442      * @param schema
443      *            the schema
444      */
445     private VtepIpPool processAvailableIps(final VtepConfigSchema schema) {
446         String subnetCidr = ItmUtils.getSubnetCidrAsString(schema.getSubnet());
447         SubnetUtils subnetUtils = new SubnetUtils(subnetCidr);
448
449         List<IpAddress> availableIps = calculateAvailableIps(subnetUtils, schema.getExcludeIpFilter(),
450                 schema.getGatewayIp());
451         VtepIpPool vtepIpPool = new VtepIpPoolBuilder().setSubnetCidr(subnetCidr).setAvailableIpaddress(availableIps)
452                 .setAllocatedIpaddress(new ArrayList<>()).build();
453
454         MDSALUtil.syncWrite(this.dataBroker, LogicalDatastoreType.CONFIGURATION,
455                 ItmUtils.getVtepIpPoolIdentifier(subnetCidr), vtepIpPool);
456         LOG.info("Vtep IP Pool with key:{} added to config DS", subnetCidr);
457         return vtepIpPool;
458     }
459
460     /**
461      * Gets the vtep ip pool.
462      *
463      * @param subnetCidr
464      *            the subnet cidr
465      * @return the vtep ip pool
466      */
467     private VtepIpPool getVtepIpPool(final String subnetCidr) {
468         return ItmUtils.read(LogicalDatastoreType.CONFIGURATION, ItmUtils.getVtepIpPoolIdentifier(subnetCidr),
469                 this.dataBroker).orNull();
470     }
471
472     /**
473      * Delete vtep ip pool.
474      *
475      * @param subnetCidr
476      *            the subnet cidr
477      */
478     private void deleteVtepIpPool(final String subnetCidr) {
479         if (StringUtils.isNotBlank(subnetCidr)) {
480             MDSALUtil.syncDelete(this.dataBroker, LogicalDatastoreType.CONFIGURATION,
481                     ItmUtils.getVtepIpPoolIdentifier(subnetCidr));
482             LOG.debug("Deleted Vtep IP Pool with key:{}", subnetCidr);
483         }
484     }
485
486     /**
487      * Gets the an available ip.
488      *
489      * @param availableIps
490      *
491      * @return the an available ip
492      */
493     private IpAddress getAnAvailableIP(List<IpAddress> availableIps) {
494         // TODO: Sort IP Addresses, get the least value
495         IpAddress ipAddress = null;
496         if (availableIps != null && !availableIps.isEmpty()) {
497             ipAddress = availableIps.remove(0);
498         }
499         return ipAddress;
500     }
501
502     /**
503      * Allocate ip addresses.
504      *
505      * @param allocatedIps
506      *            the allocated ips
507      * @param vtepIpPool
508      *            the vtep ip pool
509      * @param subnetCidr
510      *            the subnet cidr
511      */
512     private void allocateIpAddresses(List<IpAddress> allocatedIps, VtepIpPool vtepIpPool, String subnetCidr) {
513         if (allocatedIps != null && !allocatedIps.isEmpty() && vtepIpPool != null) {
514             // Remove from the available IP address list and add to allocated IP
515             // address list.
516             VtepIpPoolBuilder builder = new VtepIpPoolBuilder(vtepIpPool);
517             if (builder.getAvailableIpaddress() != null) {
518                 builder.getAvailableIpaddress().removeAll(allocatedIps);
519             }
520             if (builder.getAllocatedIpaddress() == null) {
521                 builder.setAllocatedIpaddress(allocatedIps);
522             } else {
523                 builder.getAllocatedIpaddress().addAll(allocatedIps);
524             }
525
526             MDSALUtil.syncWrite(this.dataBroker, LogicalDatastoreType.CONFIGURATION,
527                     ItmUtils.getVtepIpPoolIdentifier(subnetCidr), builder.build());
528         }
529     }
530
531     /**
532      * De-allocate ip addresses.
533      *
534      * @param freeIps
535      *            the free ips
536      * @param subnetCidr
537      *            the subnet cidr
538      */
539     private void deAllocateIpAddresses(List<IpAddress> freeIps, String subnetCidr) {
540         VtepIpPool vtepIpPool = getVtepIpPool(subnetCidr);
541         if (freeIps != null && !freeIps.isEmpty() && vtepIpPool != null) {
542             // Remove from the allocated IP address list and add to available IP
543             // address list.
544             VtepIpPoolBuilder builder = new VtepIpPoolBuilder(vtepIpPool);
545             if (builder.getAllocatedIpaddress() != null) {
546                 builder.getAllocatedIpaddress().removeAll(freeIps);
547             }
548             if (builder.getAvailableIpaddress() == null) {
549                 builder.setAvailableIpaddress(freeIps);
550             } else {
551                 builder.getAvailableIpaddress().addAll(freeIps);
552             }
553
554             MDSALUtil.syncWrite(this.dataBroker, LogicalDatastoreType.CONFIGURATION,
555                     ItmUtils.getVtepIpPoolIdentifier(subnetCidr), builder.build());
556             LOG.debug("Vtep IP Pool with key:{} updated to config DS", subnetCidr);
557         }
558     }
559
560     /**
561      * Calculate available ips.
562      *
563      * @param subnetUtils
564      *            the subnet cidr
565      * @param excludeIpFilter
566      *            the exclude ip filter
567      * @param gatewayIp
568      *            the gateway IP
569      * @return the list
570      */
571     private List<IpAddress> calculateAvailableIps(SubnetUtils subnetUtils, String excludeIpFilter,
572                                                   IpAddress gatewayIp) {
573         List<IpAddress> lstAvailableIps = new ArrayList<>();
574         SubnetInfo subnetInfo = subnetUtils.getInfo();
575         String[] arrIpAddresses = subnetInfo.getAllAddresses();
576
577         for (String ipAddress : arrIpAddresses) {
578             lstAvailableIps.add(new IpAddress(ipAddress.toCharArray()));
579         }
580         lstAvailableIps.remove(gatewayIp);
581         lstAvailableIps.removeAll(ItmUtils.getExcludeIpAddresses(excludeIpFilter, subnetInfo));
582
583         return lstAvailableIps;
584     }
585 }