Skip to content

Commit

Permalink
nova-network can't deallocate ips from deleted instances
Browse files Browse the repository at this point in the history
Allow nova-network to deallocate assigned IPs from deleted instances

Fix bug #939580

Change-Id: Ib24fea0701cf640721cd0b021c78c8c5dfbb507b
Signed-off-by: François Charlier <francois.charlier@enovance.com>
  • Loading branch information
fcharlier committed Feb 23, 2012
1 parent dd851ff commit 5ad1dea
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 9 deletions.
33 changes: 24 additions & 9 deletions nova/network/manager.py
Expand Up @@ -320,11 +320,17 @@ def deallocate_for_instance(self, context, **kwargs):
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
Expand All @@ -336,11 +342,11 @@ def deallocate_for_instance(self, context, **kwargs):
# 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()
Expand Down Expand Up @@ -756,7 +762,9 @@ def set_network_host(self, context, network_ref):

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]
Expand Down Expand Up @@ -882,21 +890,28 @@ def deallocate_for_instance(self, context, **kwargs):
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,
Expand Down
6 changes: 6 additions & 0 deletions nova/tests/test_network.py
Expand Up @@ -1291,6 +1291,12 @@ def test_double_deallocation(self):
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"
Expand Down

0 comments on commit 5ad1dea

Please sign in to comment.