Fixes #75
IP addresses in subnets marked as "do_not_use" are now ignored successfully.
This commit is contained in:
		@@ -267,6 +267,10 @@ def ip_address_find(context, lock_mode=False, **filters):
 | 
			
		||||
            query = query.filter(stmt.c.ports_count <= 1)
 | 
			
		||||
 | 
			
		||||
    model_filters = _model_query(context, models.IPAddress, filters)
 | 
			
		||||
    if "do_not_use" in filters:
 | 
			
		||||
        query = query.filter(models.Subnet.do_not_use ==
 | 
			
		||||
                             filters["do_not_use"])
 | 
			
		||||
 | 
			
		||||
    if filters.get("device_id"):
 | 
			
		||||
        model_filters.append(models.IPAddress.ports.any(
 | 
			
		||||
            models.Port.device_id.in_(filters["device_id"])))
 | 
			
		||||
 
 | 
			
		||||
@@ -196,7 +196,8 @@ class QuarkIpam(object):
 | 
			
		||||
            "network_id": net_id, "reuse_after": reuse_after,
 | 
			
		||||
            "deallocated": True, "scope": db_api.ONE,
 | 
			
		||||
            "ip_address": ip_address, "lock_mode": True,
 | 
			
		||||
            "version": version, "order_by": "address"}
 | 
			
		||||
            "version": version, "order_by": "address",
 | 
			
		||||
            "do_not_use": False}
 | 
			
		||||
 | 
			
		||||
        if sub_ids:
 | 
			
		||||
            ip_kwargs["subnet_id"] = sub_ids
 | 
			
		||||
 
 | 
			
		||||
@@ -14,10 +14,13 @@
 | 
			
		||||
# limitations under the License.
 | 
			
		||||
 | 
			
		||||
import contextlib
 | 
			
		||||
import datetime
 | 
			
		||||
import netaddr
 | 
			
		||||
 | 
			
		||||
from neutron.common import exceptions
 | 
			
		||||
from neutron import context
 | 
			
		||||
from neutron.db import api as neutron_db_api
 | 
			
		||||
from neutron.openstack.common import timeutils
 | 
			
		||||
from oslo.config import cfg
 | 
			
		||||
import unittest2
 | 
			
		||||
 | 
			
		||||
@@ -74,6 +77,73 @@ class QuarkIPAddressAllocate(QuarkIpamBaseFunctionalTest):
 | 
			
		||||
            self.assertEqual(ipaddress[0]['used_by_tenant_id'], "fake")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class QuarkIPAddressReallocate(QuarkIpamBaseFunctionalTest):
 | 
			
		||||
    @contextlib.contextmanager
 | 
			
		||||
    def _stubs(self, network, subnet, address):
 | 
			
		||||
        self.ipam = quark.ipam.QuarkIpamANY()
 | 
			
		||||
        with self.context.session.begin():
 | 
			
		||||
            next_ip = subnet.pop("next_auto_assign_ip", 0)
 | 
			
		||||
            net_mod = db_api.network_create(self.context, **network)
 | 
			
		||||
            subnet["network"] = net_mod
 | 
			
		||||
            sub_mod = db_api.subnet_create(self.context, **subnet)
 | 
			
		||||
 | 
			
		||||
            address["network_id"] = net_mod["id"]
 | 
			
		||||
            address["subnet_id"] = sub_mod["id"]
 | 
			
		||||
            ip = db_api.ip_address_create(self.context, **address)
 | 
			
		||||
            address.pop("address")
 | 
			
		||||
            db_api.ip_address_update(self.context, ip, **address)
 | 
			
		||||
 | 
			
		||||
            # NOTE(asadoughi): update after cidr constructor has been invoked
 | 
			
		||||
            db_api.subnet_update(self.context,
 | 
			
		||||
                                 sub_mod,
 | 
			
		||||
                                 next_auto_assign_ip=next_ip)
 | 
			
		||||
        yield net_mod
 | 
			
		||||
 | 
			
		||||
    def test_allocate_finds_ip_reallocates(self):
 | 
			
		||||
        network = dict(name="public", tenant_id="fake")
 | 
			
		||||
        ipnet = netaddr.IPNetwork("0.0.0.0/24")
 | 
			
		||||
        next_ip = ipnet.ipv6().first + 10
 | 
			
		||||
        subnet = dict(cidr="0.0.0.0/24", next_auto_assign_ip=next_ip,
 | 
			
		||||
                      ip_policy=None, tenant_id="fake", do_not_use=False)
 | 
			
		||||
 | 
			
		||||
        addr = netaddr.IPAddress("0.0.0.2")
 | 
			
		||||
 | 
			
		||||
        after_reuse_after = cfg.CONF.QUARK.ipam_reuse_after + 1
 | 
			
		||||
        reusable_after = datetime.timedelta(seconds=after_reuse_after)
 | 
			
		||||
        deallocated_at = timeutils.utcnow() - reusable_after
 | 
			
		||||
        ip_address = dict(address=addr, version=4, _deallocated=True,
 | 
			
		||||
                          deallocated_at=deallocated_at)
 | 
			
		||||
 | 
			
		||||
        with self._stubs(network, subnet, ip_address) as net:
 | 
			
		||||
            ipaddress = []
 | 
			
		||||
            self.ipam.allocate_ip_address(self.context, ipaddress,
 | 
			
		||||
                                          net["id"], 0, 0)
 | 
			
		||||
            self.assertIsNotNone(ipaddress[0]['id'])
 | 
			
		||||
            expected = netaddr.IPAddress("0.0.0.2").ipv6().value
 | 
			
		||||
            self.assertEqual(ipaddress[0]['address'], expected)
 | 
			
		||||
            self.assertEqual(ipaddress[0]['version'], 4)
 | 
			
		||||
            self.assertEqual(ipaddress[0]['used_by_tenant_id'], "fake")
 | 
			
		||||
 | 
			
		||||
    def test_allocate_finds_ip_in_do_not_use_subnet_raises(self):
 | 
			
		||||
        network = dict(name="public", tenant_id="fake")
 | 
			
		||||
        ipnet = netaddr.IPNetwork("0.0.0.0/24")
 | 
			
		||||
        next_ip = ipnet.ipv6().first + 3
 | 
			
		||||
        subnet = dict(cidr="0.0.0.0/24", next_auto_assign_ip=next_ip,
 | 
			
		||||
                      ip_policy=None, tenant_id="fake", do_not_use=True)
 | 
			
		||||
 | 
			
		||||
        addr = netaddr.IPAddress("0.0.0.2")
 | 
			
		||||
        after_reuse_after = cfg.CONF.QUARK.ipam_reuse_after + 1
 | 
			
		||||
        reusable_after = datetime.timedelta(seconds=after_reuse_after)
 | 
			
		||||
        deallocated_at = timeutils.utcnow() - reusable_after
 | 
			
		||||
        ip_address = dict(address=addr, version=4, _deallocated=True,
 | 
			
		||||
                          deallocated_at=deallocated_at)
 | 
			
		||||
 | 
			
		||||
        with self._stubs(network, subnet, ip_address) as net:
 | 
			
		||||
            with self.assertRaises(exceptions.IpAddressGenerationFailure):
 | 
			
		||||
                self.ipam.allocate_ip_address(self.context, [], net["id"],
 | 
			
		||||
                                              0, 0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class QuarkIPAddressFindReallocatable(QuarkIpamBaseFunctionalTest):
 | 
			
		||||
    @contextlib.contextmanager
 | 
			
		||||
    def _stubs(self, network, subnet):
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user