def validate_allocation_pools(self, ip_pools, subnet_cidr): """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. """ subnet = netaddr.IPNetwork(subnet_cidr) subnet_first_ip = netaddr.IPAddress(subnet.first + 1) # last address is broadcast in v4 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) # Valid allocation pool # Create an IPSet for it for easily verifying overlaps ip_sets.append(netaddr.IPSet(ip_pool.cidrs())) LOG.debug("Checking for overlaps among allocation pools " "and gateway ip") ip_ranges = ip_pools[:] # Use integer cursors as an efficient way for implementing # comparison and avoiding comparing the same pair twice 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)
def _validate_allocation_pools(self): """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. """ ip_pools = self._alloc_pools subnet_cidr = self._subnet_cidr LOG.debug(_("Performing IP validity checks on allocation pools")) ip_sets = [] for ip_pool in ip_pools: try: start_ip = netaddr.IPAddress(ip_pool['start']) end_ip = netaddr.IPAddress(ip_pool['end']) except netaddr.AddrFormatError: LOG.info( _("Found invalid IP address in pool: " "%(start)s - %(end)s:"), { 'start': ip_pool['start'], 'end': ip_pool['end'] }) raise exceptions.InvalidAllocationPool(pool=ip_pool) if (start_ip.version != self._subnet_cidr.version or end_ip.version != self._subnet_cidr.version): LOG.info( _("Specified IP addresses do not match " "the subnet IP version")) raise exceptions.InvalidAllocationPool(pool=ip_pool) if end_ip < start_ip: LOG.info( _("Start IP (%(start)s) is greater than end IP " "(%(end)s)"), { 'start': ip_pool['start'], 'end': ip_pool['end'] }) raise exceptions.InvalidAllocationPool(pool=ip_pool) if (start_ip < self._subnet_first_ip or end_ip > self._subnet_last_ip): LOG.info( _("Found pool larger than subnet " "CIDR:%(start)s - %(end)s"), { 'start': ip_pool['start'], 'end': ip_pool['end'] }) raise exceptions.OutOfBoundsAllocationPool( pool=ip_pool, subnet_cidr=subnet_cidr) # Valid allocation pool # Create an IPSet for it for easily verifying overlaps ip_sets.append( netaddr.IPSet( netaddr.IPRange(ip_pool['start'], ip_pool['end']).cidrs())) LOG.debug( _("Checking for overlaps among allocation pools " "and gateway ip")) ip_ranges = ip_pools[:] # Use integer cursors as an efficient way for implementing # comparison and avoiding comparing the same pair twice for l_cursor in xrange(len(ip_sets)): for r_cursor in xrange(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( _("Found overlapping ranges: %(l_range)s and " "%(r_range)s"), { 'l_range': l_range, 'r_range': r_range }) raise exceptions.OverlappingAllocationPools( pool_1=l_range, pool_2=r_range, subnet_cidr=subnet_cidr)