Merge "use context mgr in instance.delete"

This commit is contained in:
Zuul 2017-10-30 21:51:55 +00:00 committed by Gerrit Code Review
commit 66a2b50a3e
6 changed files with 80 additions and 67 deletions

View File

@ -1869,14 +1869,12 @@ class API(base.Base):
== vm_states.SHELVED_OFFLOADED)
if not instance.host and not shelved_offloaded:
try:
compute_utils.notify_about_instance_usage(
with compute_utils.notify_about_instance_delete(
self.notifier, context, instance,
"%s.start" % delete_type)
instance.destroy()
compute_utils.notify_about_instance_usage(
self.notifier, context, instance,
"%s.end" % delete_type,
system_metadata=instance.system_metadata)
delete_type
if delete_type != 'soft_delete'
else 'delete'):
instance.destroy()
LOG.info('Instance deleted and does not have host '
'field, its vm_state is %(state)s.',
{'state': instance.vm_state},
@ -2033,38 +2031,37 @@ class API(base.Base):
else:
LOG.warning("instance's host %s is down, deleting from "
"database", instance.host, instance=instance)
compute_utils.notify_about_instance_usage(
self.notifier, context, instance, "%s.start" % delete_type)
with compute_utils.notify_about_instance_delete(
self.notifier, context, instance,
delete_type if delete_type != 'soft_delete' else 'delete'):
elevated = context.elevated()
if self.cell_type != 'api':
# NOTE(liusheng): In nova-network multi_host scenario,deleting
# network info of the instance may need instance['host'] as
# destination host of RPC call. If instance in SHELVED_OFFLOADED
# state, instance['host'] is None, here, use shelved_host as host
# to deallocate network info and reset instance['host'] after that.
# Here we shouldn't use instance.save(), because this will mislead
# user who may think the instance's host has been changed, and
# actually, the instance.host is always None.
orig_host = instance.host
try:
if instance.vm_state == vm_states.SHELVED_OFFLOADED:
sysmeta = getattr(instance,
obj_base.get_attrname('system_metadata'))
instance.host = sysmeta.get('shelved_host')
self.network_api.deallocate_for_instance(elevated,
instance)
finally:
instance.host = orig_host
elevated = context.elevated()
if self.cell_type != 'api':
# NOTE(liusheng): In nova-network multi_host scenario,deleting
# network info of the instance may need instance['host'] as
# destination host of RPC call. If instance in
# SHELVED_OFFLOADED state, instance['host'] is None, here, use
# shelved_host as host to deallocate network info and reset
# instance['host'] after that. Here we shouldn't use
# instance.save(), because this will mislead user who may think
# the instance's host has been changed, and actually, the
# instance.host is always None.
orig_host = instance.host
try:
if instance.vm_state == vm_states.SHELVED_OFFLOADED:
sysmeta = getattr(instance,
obj_base.get_attrname(
'system_metadata'))
instance.host = sysmeta.get('shelved_host')
self.network_api.deallocate_for_instance(elevated,
instance)
finally:
instance.host = orig_host
# cleanup volumes
self._local_cleanup_bdm_volumes(bdms, instance, context)
cb(context, instance, bdms, local=True)
sys_meta = instance.system_metadata
instance.destroy()
compute_utils.notify_about_instance_usage(
self.notifier, context, instance, "%s.end" % delete_type,
system_metadata=sys_meta)
# cleanup volumes
self._local_cleanup_bdm_volumes(bdms, instance, context)
cb(context, instance, bdms, local=True)
instance.destroy()
def _do_delete(self, context, instance, bdms, local=False):
if local:

View File

@ -2654,25 +2654,25 @@ class ComputeManager(manager.Manager):
@wrap_instance_fault
def soft_delete_instance(self, context, instance, reservations):
"""Soft delete an instance on this host."""
self._notify_about_instance_usage(context, instance,
"soft_delete.start")
compute_utils.notify_about_instance_action(context, instance,
self.host, action=fields.NotificationAction.SOFT_DELETE,
phase=fields.NotificationPhase.START)
try:
self.driver.soft_delete(instance)
except NotImplementedError:
# Fallback to just powering off the instance if the
# hypervisor doesn't implement the soft_delete method
self.driver.power_off(instance)
instance.power_state = self._get_power_state(context, instance)
instance.vm_state = vm_states.SOFT_DELETED
instance.task_state = None
instance.save(expected_task_state=[task_states.SOFT_DELETING])
self._notify_about_instance_usage(context, instance, "soft_delete.end")
compute_utils.notify_about_instance_action(context, instance,
self.host, action=fields.NotificationAction.SOFT_DELETE,
phase=fields.NotificationPhase.END)
with compute_utils.notify_about_instance_delete(
self.notifier, context, instance, 'soft_delete'):
compute_utils.notify_about_instance_action(context, instance,
self.host, action=fields.NotificationAction.SOFT_DELETE,
phase=fields.NotificationPhase.START)
try:
self.driver.soft_delete(instance)
except NotImplementedError:
# Fallback to just powering off the instance if the
# hypervisor doesn't implement the soft_delete method
self.driver.power_off(instance)
instance.power_state = self._get_power_state(context, instance)
instance.vm_state = vm_states.SOFT_DELETED
instance.task_state = None
instance.save(expected_task_state=[task_states.SOFT_DELETING])
compute_utils.notify_about_instance_action(
context, instance, self.host,
action=fields.NotificationAction.SOFT_DELETE,
phase=fields.NotificationPhase.END)
@wrap_exception()
@reverts_task_state

View File

@ -945,15 +945,17 @@ class UnlimitedSemaphore(object):
@contextlib.contextmanager
def notify_about_instance_delete(notifier, context, instance):
def notify_about_instance_delete(notifier, context, instance,
delete_type='delete'):
# Pre-load system_metadata because if this context is around an
# instance.destroy(), lazy-loading it later would result in an
# InstanceNotFound error.
system_metadata = instance.system_metadata
try:
notify_about_instance_usage(notifier, context, instance,
"delete.start")
"%s.start" % delete_type)
yield
finally:
notify_about_instance_usage(notifier, context, instance, "delete.end",
notify_about_instance_usage(notifier, context, instance,
"%s.end" % delete_type,
system_metadata=system_metadata)

View File

@ -4413,6 +4413,8 @@ class ComputeTestCase(BaseTestCase,
_get_an_exception)
self.stub_out('nova.compute.manager.ComputeManager.'
'_notify_about_instance_usage', _get_an_exception)
self.stub_out('nova.compute.utils.'
'notify_about_instance_delete', _get_an_exception)
func = getattr(self.compute, operation)

View File

@ -852,9 +852,14 @@ class _ComputeAPIUnitTestMixIn(object):
test.TestingException("Unexpected error"))
def _test_downed_host_part(self, inst, updates, delete_time, delete_type):
compute_utils.notify_about_instance_usage(
self.compute_api.notifier, self.context, inst,
'%s.start' % delete_type)
if 'soft' in delete_type:
compute_utils.notify_about_instance_usage(
self.compute_api.notifier, self.context, inst,
'delete.start')
else:
compute_utils.notify_about_instance_usage(
self.compute_api.notifier, self.context, inst,
'%s.start' % delete_type)
self.context.elevated().AndReturn(self.context)
self.compute_api.network_api.deallocate_for_instance(
self.context, inst)
@ -871,10 +876,16 @@ class _ComputeAPIUnitTestMixIn(object):
self.compute_api._local_cleanup_bdm_volumes([], inst, self.context)
db.instance_destroy(self.context, inst.uuid,
constraint=None).AndReturn(fake_inst)
compute_utils.notify_about_instance_usage(
self.compute_api.notifier,
self.context, inst, '%s.end' % delete_type,
system_metadata=inst.system_metadata)
if 'soft' in delete_type:
compute_utils.notify_about_instance_usage(
self.compute_api.notifier,
self.context, inst, 'delete.end',
system_metadata=inst.system_metadata)
else:
compute_utils.notify_about_instance_usage(
self.compute_api.notifier,
self.context, inst, '%s.end' % delete_type,
system_metadata=inst.system_metadata)
cell = objects.CellMapping(uuid=uuids.cell,
transport_url='fake://',
database_connection='fake://')

View File

@ -4181,7 +4181,8 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
with test.nested(
mock.patch.object(nova.compute.utils,
'notify_about_instance_action'),
mock.patch.object(self.compute, '_notify_about_instance_usage'),
mock.patch.object(nova.compute.utils,
'notify_about_instance_delete'),
mock.patch.object(objects.Instance, 'save'),
mock.patch.object(self.compute.driver, 'soft_delete')
) as (fake_notify, fake_notify_usage, fake_save, fake_soft_delete):