'Validate IP allocation pools.
Verify start and end address for each allocation pool are valid,
ie: constituted by valid and appropriately ordered IP addresses.
Also, verify pools do not overlap among themselves.
Finally, verify that each range fall within the subnet\'s CIDR.'

def validate_allocation_pools(self, ip_pools, subnet_cidr):

    subnet = netaddr.IPNetwork(subnet_cidr)
    subnet_first_ip = netaddr.IPAddress((subnet.first + 1))
    subnet_last_ip = netaddr.IPAddress((subnet.last - (subnet.version == 4)))
    LOG.debug('Performing    IP    validity    checks    on    allocation    pools')
    ip_sets = []
    for ip_pool in ip_pools:
        start_ip = netaddr.IPAddress(ip_pool.first, ip_pool.version)
        end_ip = netaddr.IPAddress(ip_pool.last, ip_pool.version)
        if ((start_ip.version != subnet.version) or (end_ip.version != subnet.version)):
            LOG.info(_LI('Specified    IP    addresses    do    not    match    the    subnet    IP    version'))
            raise n_exc.InvalidAllocationPool(pool=ip_pool)
        if ((start_ip < subnet_first_ip) or (end_ip > subnet_last_ip)):
            LOG.info(_LI('Found    pool    larger    than    subnet    CIDR:%(start)s    -    %(end)s'), {'start': start_ip, 'end': end_ip})
            raise n_exc.OutOfBoundsAllocationPool(pool=ip_pool, subnet_cidr=subnet_cidr)
        ip_sets.append(netaddr.IPSet(ip_pool.cidrs()))
    LOG.debug('Checking    for    overlaps    among    allocation    pools    and    gateway    ip')
    ip_ranges = ip_pools[:]
    for l_cursor in range(len(ip_sets)):
        for r_cursor in range((l_cursor + 1), len(ip_sets)):
            if (ip_sets[l_cursor] & ip_sets[r_cursor]):
                l_range = ip_ranges[l_cursor]
                r_range = ip_ranges[r_cursor]
                LOG.info(_LI('Found    overlapping    ranges:    %(l_range)s    and    %(r_range)s'), {'l_range': l_range, 'r_range': r_range})
                raise n_exc.OverlappingAllocationPools(pool_1=l_range, pool_2=r_range, subnet_cidr=subnet_cidr)
