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