diff --git a/quark/db/api.py b/quark/db/api.py index a3566a6..2281536 100644 --- a/quark/db/api.py +++ b/quark/db/api.py @@ -181,6 +181,8 @@ def port_find(context, fields=None, **filters): query = query.options(orm.joinedload("ip_addresses.subnet")) query = query.options( orm.joinedload("ip_addresses.subnet.dns_nameservers")) + query = query.options( + orm.joinedload("ip_addresses.subnet.routes")) return query.filter(*model_filters).order_by(asc(models.Port.created_at)) diff --git a/quark/db/models.py b/quark/db/models.py index 9fc9419..b85305a 100644 --- a/quark/db/models.py +++ b/quark/db/models.py @@ -231,8 +231,7 @@ class Subnet(BASEV2, models.HasId, IsHazTags): primaryjoin='Subnet.id==' 'IPAddress.subnet_id') routes = orm.relationship(Route, primaryjoin="Route.subnet_id==Subnet.id", - backref='subnet', cascade='delete', - lazy="joined") + backref='subnet', cascade='delete') enable_dhcp = sa.Column(sa.Boolean(), default=False) dns_nameservers = orm.relationship( DNSNameserver, diff --git a/quark/ipam.py b/quark/ipam.py index d2dd18c..b8f0882 100644 --- a/quark/ipam.py +++ b/quark/ipam.py @@ -206,6 +206,9 @@ class QuarkIpam(object): try: with context.session.begin(): + # NOTE(mdietz): Before I removed the lazy=joined, this + # raised with an unknown column "address" + # error. address = db_api.ip_address_find(elevated, **ip_kwargs) if address: diff --git a/quark/tests/functional/test_ipam.py b/quark/tests/functional/test_ipam.py index 8c1478b..2a3e98e 100644 --- a/quark/tests/functional/test_ipam.py +++ b/quark/tests/functional/test_ipam.py @@ -72,3 +72,43 @@ class QuarkIPAddressAllocate(QuarkIpamBaseFunctionalTest): self.assertEqual(ipaddress[0]['address'], 281470681743362) self.assertEqual(ipaddress[0]['version'], 4) self.assertEqual(ipaddress[0]['used_by_tenant_id'], "fake") + + +class QuarkIPAddressFindReallocatable(QuarkIpamBaseFunctionalTest): + @contextlib.contextmanager + def _stubs(self, network, subnet): + 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) + # 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_find_reallocatable_ips_does_not_raise(self): + """A patch recently introduced a bug wherein addressses + could not be returned to the ip_address_find call in + attempt_to_reallocate_ip. Adding this test to prevent + a future regression. + """ + network = dict(name="public", tenant_id="fake") + ipnet = netaddr.IPNetwork("0.0.0.0/24") + next_ip = ipnet.ipv6().first + 2 + subnet = dict(id=1, cidr="0.0.0.0/24", next_auto_assign_ip=next_ip, + ip_policy=None, tenant_id="fake") + + with self._stubs(network, subnet) as net: + ip_kwargs = { + "network_id": net["id"], "reuse_after": 14400, + "deallocated": True, "scope": db_api.ONE, + "lock_mode": True, "version": 4, + "order_by": "address"} + + try: + db_api.ip_address_find(self.context, **ip_kwargs) + except Exception: + self.fail("This should not have raised")