From 5ad1dea4daf264fe11429288597d26dc4974fe05 Mon Sep 17 00:00:00 2001 From: François Charlier Date: Thu, 23 Feb 2012 16:32:54 +0100 Subject: nova-network can't deallocate ips from deleted instances MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow nova-network to deallocate assigned IPs from deleted instances Fix bug #939580 Change-Id: Ib24fea0701cf640721cd0b021c78c8c5dfbb507b Signed-off-by: François Charlier --- nova/network/manager.py | 33 ++++++++++++++++++++++++--------- nova/tests/test_network.py | 6 ++++++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/nova/network/manager.py b/nova/network/manager.py index 493cdbe1b..7cc12a4f1 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -320,11 +320,17 @@ class FloatingIP(object): rpc.called by network_api """ instance_id = kwargs.get('instance_id') + + # NOTE(francois.charlier): in some cases the instance might be + # deleted before the IPs are released, so we need to get deleted + # instances too + read_deleted_context = context.elevated(read_deleted='yes') LOG.debug(_("floating IP deallocation for instance |%s|"), instance_id, - context=context) + context=read_deleted_context) try: - fixed_ips = self.db.fixed_ip_get_by_instance(context, instance_id) + fixed_ips = self.db.fixed_ip_get_by_instance(read_deleted_context, + instance_id) except exception.FixedIpNotFoundForInstance: fixed_ips = [] # add to kwargs so we can pass to super to save a db lookup there @@ -336,11 +342,11 @@ class FloatingIP(object): # disassociate floating ips related to fixed_ip for floating_ip in floating_ips: address = floating_ip['address'] - self.disassociate_floating_ip(context, address, + self.disassociate_floating_ip(read_deleted_context, address, affect_auto_assigned=True) # deallocate if auto_assigned if floating_ip['auto_assigned']: - self.deallocate_floating_ip(context, address, + self.deallocate_floating_ip(read_deleted_context, address, affect_auto_assigned=True) # call the next inherited class's deallocate_for_instance() @@ -756,7 +762,9 @@ class NetworkManager(manager.SchedulerDependentManager): def _do_trigger_security_group_members_refresh_for_instance(self, instance_id): - admin_context = context.get_admin_context() + # NOTE(francois.charlier): the instance may have been deleted already + # thus enabling `read_deleted` + admin_context = context.get_admin_context(read_deleted='yes') instance_ref = self.db.instance_get(admin_context, instance_id) groups = instance_ref['security_groups'] group_ids = [group['id'] for group in groups] @@ -882,21 +890,28 @@ class NetworkManager(manager.SchedulerDependentManager): rpc.called by network_api kwargs can contain fixed_ips to circumvent another db lookup """ + # NOTE(francois.charlier): in some cases the instance might be + # deleted before the IPs are released, so we need to get deleted + # instances too + read_deleted_context = context.elevated(read_deleted='yes') + instance_id = kwargs.pop('instance_id') try: fixed_ips = (kwargs.get('fixed_ips') or - self.db.fixed_ip_get_by_instance(context, + self.db.fixed_ip_get_by_instance(read_deleted_context, instance_id)) except exception.FixedIpNotFoundForInstance: fixed_ips = [] LOG.debug(_("network deallocation for instance |%s|"), instance_id, - context=context) + context=read_deleted_context) # deallocate fixed ips for fixed_ip in fixed_ips: - self.deallocate_fixed_ip(context, fixed_ip['address'], **kwargs) + self.deallocate_fixed_ip(read_deleted_context, fixed_ip['address'], + **kwargs) # deallocate vifs (mac addresses) - self.db.virtual_interface_delete_by_instance(context, instance_id) + self.db.virtual_interface_delete_by_instance(read_deleted_context, + instance_id) @wrap_check_policy def get_instance_nw_info(self, context, instance_id, instance_uuid, diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index 7b4269463..2606ba0db 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -1291,6 +1291,12 @@ class FloatingIPTestCase(test.TestCase): self.network.deallocate_for_instance(self.context, instance_id=instance_ref['id']) + def test_deallocation_deleted_instance(self): + instance_ref = db.api.instance_create(self.context, + {"project_id": self.project_id, "deleted": True}) + self.network.deallocate_for_instance(self.context, + instance_id=instance_ref['id']) + def test_floating_dns_create_conflict(self): zone = "example.org" address1 = "10.10.10.11" -- cgit