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