diff --git a/doc/notification_samples/instance-delete-end.json b/doc/notification_samples/instance-delete-end.json index 681b6eb82b..1c1fa48d74 100644 --- a/doc/notification_samples/instance-delete-end.json +++ b/doc/notification_samples/instance-delete-end.json @@ -4,7 +4,18 @@ "nova_object.data":{ "architecture":"x86_64", "availability_zone": "nova", - "block_devices":[], + "block_devices":[{ + "nova_object.data": { + "boot_index": null, + "delete_on_termination": false, + "device_name": "/dev/sdb", + "tag": null, + "volume_id": "a07f71dc-8151-4e7d-a0cc-cd24a3f11113" + }, + "nova_object.name": "BlockDevicePayload", + "nova_object.namespace": "nova", + "nova_object.version": "1.0" + }], "created_at":"2012-10-29T13:42:11Z", "deleted_at":"2012-10-29T13:42:11Z", "display_name":"some-server", diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 75329951dc..997956e440 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -731,7 +731,7 @@ class ComputeManager(manager.Manager): system_metadata=system_meta) compute_utils.notify_about_instance_action(context, instance, self.host, action=fields.NotificationAction.DELETE, - phase=fields.NotificationPhase.END) + phase=fields.NotificationPhase.END, bdms=bdms) self._delete_scheduler_instance_info(context, instance.uuid) def _init_instance(self, context, instance): @@ -2254,7 +2254,7 @@ class ComputeManager(manager.Manager): "shutdown.start") compute_utils.notify_about_instance_action(context, instance, self.host, action=fields.NotificationAction.SHUTDOWN, - phase=fields.NotificationPhase.START) + phase=fields.NotificationPhase.START, bdms=bdms) network_info = instance.get_network_info() @@ -2341,7 +2341,7 @@ class ComputeManager(manager.Manager): "shutdown.end") compute_utils.notify_about_instance_action(context, instance, self.host, action=fields.NotificationAction.SHUTDOWN, - phase=fields.NotificationPhase.END) + phase=fields.NotificationPhase.END, bdms=bdms) def _cleanup_volumes(self, context, instance_uuid, bdms, raise_exc=True): exc_info = None @@ -2377,7 +2377,7 @@ class ComputeManager(manager.Manager): "delete.start") compute_utils.notify_about_instance_action(context, instance, self.host, action=fields.NotificationAction.DELETE, - phase=fields.NotificationPhase.START) + phase=fields.NotificationPhase.START, bdms=bdms) self._shutdown_instance(context, instance, bdms) # NOTE(dims): instance.info_cache.delete() should be called after @@ -2688,13 +2688,13 @@ class ComputeManager(manager.Manager): admin_password, network_info=network_info, block_device_info=new_block_device_info) - def _notify_instance_rebuild_error(self, context, instance, error): + def _notify_instance_rebuild_error(self, context, instance, error, bdms): self._notify_about_instance_usage(context, instance, 'rebuild.error', fault=error) compute_utils.notify_about_instance_action( context, instance, self.host, action=fields.NotificationAction.REBUILD, - phase=fields.NotificationPhase.ERROR, exception=error) + phase=fields.NotificationPhase.ERROR, exception=error, bdms=bdms) @messaging.expected_exceptions(exception.PreserveEphemeralNotSupported) @wrap_exception() @@ -2801,8 +2801,7 @@ class ComputeManager(manager.Manager): # not raise ComputeResourcesUnavailable. rt.delete_allocation_for_evacuated_instance( instance, scheduled_node, node_type='destination') - self._notify_instance_rebuild_error(context, instance, e) - + self._notify_instance_rebuild_error(context, instance, e, bdms) raise exception.BuildAbortException( instance_uuid=instance.uuid, reason=e.format_message()) except (exception.InstanceNotFound, @@ -2810,13 +2809,13 @@ class ComputeManager(manager.Manager): LOG.debug('Instance was deleted while rebuilding', instance=instance) self._set_migration_status(migration, 'failed') - self._notify_instance_rebuild_error(context, instance, e) + self._notify_instance_rebuild_error(context, instance, e, bdms) except Exception as e: self._set_migration_status(migration, 'failed') if recreate or scheduled_node is not None: rt.delete_allocation_for_evacuated_instance( instance, scheduled_node, node_type='destination') - self._notify_instance_rebuild_error(context, instance, e) + self._notify_instance_rebuild_error(context, instance, e, bdms) raise else: instance.apply_migration_context() @@ -2907,7 +2906,8 @@ class ComputeManager(manager.Manager): compute_utils.notify_about_instance_action( context, instance, self.host, action=fields.NotificationAction.REBUILD, - phase=fields.NotificationPhase.START) + phase=fields.NotificationPhase.START, + bdms=bdms) instance.power_state = self._get_power_state(context, instance) instance.task_state = task_states.REBUILDING @@ -2979,7 +2979,8 @@ class ComputeManager(manager.Manager): compute_utils.notify_about_instance_action( context, instance, self.host, action=fields.NotificationAction.REBUILD, - phase=fields.NotificationPhase.END) + phase=fields.NotificationPhase.END, + bdms=bdms) def _handle_bad_volumes_detached(self, context, instance, bad_devices, block_device_info): @@ -4000,12 +4001,13 @@ class ComputeManager(manager.Manager): self._notify_about_instance_usage( context, instance, "resize.start", network_info=network_info) - compute_utils.notify_about_instance_action(context, instance, - self.host, action=fields.NotificationAction.RESIZE, - phase=fields.NotificationPhase.START) - bdms = objects.BlockDeviceMappingList.get_by_instance_uuid( context, instance.uuid) + + compute_utils.notify_about_instance_action(context, instance, + self.host, action=fields.NotificationAction.RESIZE, + phase=fields.NotificationPhase.START, bdms=bdms) + block_device_info = self._get_instance_block_device_info( context, instance, bdms=bdms) @@ -4042,7 +4044,7 @@ class ComputeManager(manager.Manager): compute_utils.notify_about_instance_action(context, instance, self.host, action=fields.NotificationAction.RESIZE, - phase=fields.NotificationPhase.END) + phase=fields.NotificationPhase.END, bdms=bdms) self.instance_events.clear_events_for_instance(instance) def _terminate_volume_connections(self, context, instance, bdms): @@ -4399,12 +4401,21 @@ class ComputeManager(manager.Manager): def _shelve_instance(self, context, instance, image_id, clean_shutdown): LOG.info('Shelving', instance=instance) + offload = CONF.shelved_offload_time == 0 + if offload: + # Get the BDMs early so we can pass them into versioned + # notifications since _shelve_offload_instance needs the + # BDMs anyway. + bdms = objects.BlockDeviceMappingList.get_by_instance_uuid( + context, instance.uuid) + else: + bdms = None compute_utils.notify_usage_exists(self.notifier, context, instance, current_period=True) self._notify_about_instance_usage(context, instance, 'shelve.start') compute_utils.notify_about_instance_action(context, instance, self.host, action=fields.NotificationAction.SHELVE, - phase=fields.NotificationPhase.START) + phase=fields.NotificationPhase.START, bdms=bdms) def update_task_state(task_state, expected_state=task_states.SHELVING): shelving_state_map = { @@ -4436,11 +4447,11 @@ class ComputeManager(manager.Manager): self._notify_about_instance_usage(context, instance, 'shelve.end') compute_utils.notify_about_instance_action(context, instance, self.host, action=fields.NotificationAction.SHELVE, - phase=fields.NotificationPhase.END) + phase=fields.NotificationPhase.END, bdms=bdms) - if CONF.shelved_offload_time == 0: + if offload: self._shelve_offload_instance(context, instance, - clean_shutdown=False) + clean_shutdown=False, bdms=bdms) @wrap_exception() @reverts_task_state @@ -4463,13 +4474,17 @@ class ComputeManager(manager.Manager): self._shelve_offload_instance(context, instance, clean_shutdown) do_shelve_offload_instance() - def _shelve_offload_instance(self, context, instance, clean_shutdown): + def _shelve_offload_instance(self, context, instance, clean_shutdown, + bdms=None): LOG.info('Shelve offloading', instance=instance) + if bdms is None: + bdms = objects.BlockDeviceMappingList.get_by_instance_uuid( + context, instance.uuid) self._notify_about_instance_usage(context, instance, 'shelve_offload.start') compute_utils.notify_about_instance_action(context, instance, self.host, action=fields.NotificationAction.SHELVE_OFFLOAD, - phase=fields.NotificationPhase.START) + phase=fields.NotificationPhase.START, bdms=bdms) self._power_off_instance(context, instance, clean_shutdown) current_power_state = self._get_power_state(context, instance) @@ -4477,8 +4492,6 @@ class ComputeManager(manager.Manager): self.network_api.cleanup_instance_network_on_host(context, instance, instance.host) network_info = self.network_api.get_instance_nw_info(context, instance) - bdms = objects.BlockDeviceMappingList.get_by_instance_uuid( - context, instance.uuid) block_device_info = self._get_instance_block_device_info(context, instance, @@ -4516,7 +4529,7 @@ class ComputeManager(manager.Manager): 'shelve_offload.end') compute_utils.notify_about_instance_action(context, instance, self.host, action=fields.NotificationAction.SHELVE_OFFLOAD, - phase=fields.NotificationPhase.END) + phase=fields.NotificationPhase.END, bdms=bdms) @wrap_exception() @reverts_task_state @@ -4558,16 +4571,17 @@ class ComputeManager(manager.Manager): def _unshelve_instance(self, context, instance, image, filter_properties, node): LOG.info('Unshelving', instance=instance) + bdms = objects.BlockDeviceMappingList.get_by_instance_uuid( + context, instance.uuid) + self._notify_about_instance_usage(context, instance, 'unshelve.start') compute_utils.notify_about_instance_action(context, instance, self.host, action=fields.NotificationAction.UNSHELVE, - phase=fields.NotificationPhase.START) + phase=fields.NotificationPhase.START, bdms=bdms) instance.task_state = task_states.SPAWNING instance.save() - bdms = objects.BlockDeviceMappingList.get_by_instance_uuid( - context, instance.uuid) block_device_info = self._prep_block_device(context, instance, bdms) scrubbed_keys = self._unshelve_instance_key_scrub(instance) @@ -4624,7 +4638,7 @@ class ComputeManager(manager.Manager): self._notify_about_instance_usage(context, instance, 'unshelve.end') compute_utils.notify_about_instance_action(context, instance, self.host, action=fields.NotificationAction.UNSHELVE, - phase=fields.NotificationPhase.END) + phase=fields.NotificationPhase.END, bdms=bdms) @messaging.expected_exceptions(NotImplementedError) @wrap_instance_fault @@ -6011,7 +6025,8 @@ class ComputeManager(manager.Manager): compute_utils.notify_about_instance_action(context, instance, self.host, action=fields.NotificationAction.LIVE_MIGRATION_ROLLBACK, - phase=fields.NotificationPhase.START) + phase=fields.NotificationPhase.START, + bdms=bdms) do_cleanup, destroy_disks = self._live_migration_cleanup_flags( migrate_data) @@ -6024,9 +6039,11 @@ class ComputeManager(manager.Manager): self._notify_about_instance_usage(context, instance, "live_migration._rollback.end") compute_utils.notify_about_instance_action(context, instance, + self.host, action=fields.NotificationAction.LIVE_MIGRATION_ROLLBACK, - phase=fields.NotificationPhase.END) + phase=fields.NotificationPhase.END, + bdms=bdms) self._set_migration_status(migration, migration_status) diff --git a/nova/compute/utils.py b/nova/compute/utils.py index 14f5455f59..bb632f6422 100644 --- a/nova/compute/utils.py +++ b/nova/compute/utils.py @@ -352,7 +352,7 @@ def _get_fault_and_priority_from_exc(exception): @rpc.if_notifications_enabled def notify_about_instance_action(context, instance, host, action, phase=None, source=fields.NotificationSource.COMPUTE, - exception=None): + exception=None, bdms=None): """Send versioned notification about the action made on the instance :param instance: the instance which the action performed on :param host: the host emitting the notification @@ -360,11 +360,14 @@ def notify_about_instance_action(context, instance, host, action, phase=None, :param phase: the phase of the action :param source: the source of the notification :param exception: the thrown exception (used in error notifications) + :param bdms: BlockDeviceMappingList object for the instance. If it is not + provided then we will load it from the db if so configured """ fault, priority = _get_fault_and_priority_from_exc(exception) payload = instance_notification.InstanceActionPayload( instance=instance, - fault=fault) + fault=fault, + bdms=bdms) notification = instance_notification.InstanceActionNotification( context=context, priority=priority, diff --git a/nova/notifications/objects/instance.py b/nova/notifications/objects/instance.py index c1b8353b30..bd13b21611 100644 --- a/nova/notifications/objects/instance.py +++ b/nova/notifications/objects/instance.py @@ -108,14 +108,15 @@ class InstancePayload(base.NotificationPayloadBase): 'auto_disk_config': fields.DiskConfigField() } - def __init__(self, instance): + def __init__(self, instance, bdms=None): super(InstancePayload, self).__init__() network_info = instance.get_network_info() self.ip_addresses = IpPayload.from_network_info(network_info) self.flavor = flavor_payload.FlavorPayload(flavor=instance.flavor) - # TODO(gibi): investigate the possibility to use already in scope bdm - # when available like in instance.create - self.block_devices = BlockDevicePayload.from_instance(instance) + if bdms is not None: + self.block_devices = BlockDevicePayload.from_bdms(bdms) + else: + self.block_devices = BlockDevicePayload.from_instance(instance) self.populate_schema(instance=instance) @@ -134,8 +135,9 @@ class InstanceActionPayload(InstancePayload): 'fault': fields.ObjectField('ExceptionPayload', nullable=True), } - def __init__(self, instance, fault): - super(InstanceActionPayload, self).__init__(instance=instance) + def __init__(self, instance, fault, bdms=None): + super(InstanceActionPayload, self).__init__(instance=instance, + bdms=bdms) self.fault = fault @@ -352,12 +354,21 @@ class BlockDevicePayload(base.NotificationPayloadBase): return None instance_bdms = instance.get_bdms() - bdms = [] if instance_bdms is not None: - for bdm in instance_bdms: - if bdm.volume_id is not None: - bdms.append(cls(bdm)) - return bdms + return cls.from_bdms(instance_bdms) + else: + return [] + + @classmethod + def from_bdms(cls, bdms): + """Returns a list of BlockDevicePayload objects based on the passed + BlockDeviceMappingList. + """ + payloads = [] + for bdm in bdms: + if bdm.volume_id is not None: + payloads.append(cls(bdm)) + return payloads @nova_base.NovaObjectRegistry.register_notification diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index cb3ba0b1da..49aa1f5052 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -5235,9 +5235,9 @@ class ComputeTestCase(BaseTestCase, clean_shutdown=clean_shutdown) mock_notify_action.assert_has_calls([ mock.call(self.context, instance, 'fake-mini', - action='resize', phase='start'), + action='resize', phase='start', bdms='fake_bdms'), mock.call(self.context, instance, 'fake-mini', - action='resize', phase='end')]) + action='resize', phase='end', bdms='fake_bdms')]) mock_get_instance_vol_bdinfo.assert_called_once_with( self.context, instance, bdms='fake_bdms') mock_terminate_vol_conn.assert_called_once_with(self.context, @@ -6283,7 +6283,8 @@ class ComputeTestCase(BaseTestCase, dest_node = objects.ComputeNode(host='foo', uuid=uuids.dest_node) mock_get_node.return_value = dest_node - mock_bdms.return_value = objects.BlockDeviceMappingList() + bdms = objects.BlockDeviceMappingList() + mock_bdms.return_value = bdms @mock.patch('nova.compute.utils.notify_about_instance_action') @mock.patch.object(self.compute, '_live_migration_cleanup_flags') @@ -6297,9 +6298,11 @@ class ComputeTestCase(BaseTestCase, instance.project_id, test.MatchType(dict)) mock_notify.assert_has_calls([ mock.call(c, instance, self.compute.host, - action='live_migration_rollback', phase='start'), + action='live_migration_rollback', phase='start', + bdms=bdms), mock.call(c, instance, self.compute.host, - action='live_migration_rollback', phase='end')]) + action='live_migration_rollback', phase='end', + bdms=bdms)]) mock_nw_api.setup_networks_on_host.assert_called_once_with( c, instance, self.compute.host) _test() @@ -6323,7 +6326,8 @@ class ComputeTestCase(BaseTestCase, dest_node = objects.ComputeNode(host='foo', uuid=uuids.dest_node) mock_get_node.return_value = dest_node - mock_bdms.return_value = objects.BlockDeviceMappingList() + bdms = objects.BlockDeviceMappingList() + mock_bdms.return_value = bdms @mock.patch('nova.compute.utils.notify_about_instance_action') @mock.patch.object(self.compute, '_live_migration_cleanup_flags') @@ -6338,9 +6342,11 @@ class ComputeTestCase(BaseTestCase, instance.project_id, test.MatchType(dict)) mock_notify.assert_has_calls([ mock.call(c, instance, self.compute.host, - action='live_migration_rollback', phase='start'), + action='live_migration_rollback', phase='start', + bdms=bdms), mock.call(c, instance, self.compute.host, - action='live_migration_rollback', phase='end')]) + action='live_migration_rollback', phase='end', + bdms=bdms)]) mock_nw_api.setup_networks_on_host.assert_called_once_with( c, instance, self.compute.host) _test() @@ -12002,19 +12008,19 @@ class EvacuateHostTestCase(BaseTestCase): if vm_states_is_stopped: mock_notify.assert_has_calls([ mock.call(ctxt, self.inst, self.inst.host, - action='rebuild', phase='start'), + action='rebuild', phase='start', bdms=bdms), mock.call(ctxt, self.inst, self.inst.host, action='power_off', phase='start'), mock.call(ctxt, self.inst, self.inst.host, action='power_off', phase='end'), mock.call(ctxt, self.inst, self.inst.host, - action='rebuild', phase='end')]) + action='rebuild', phase='end', bdms=bdms)]) else: mock_notify.assert_has_calls([ mock.call(ctxt, self.inst, self.inst.host, - action='rebuild', phase='start'), + action='rebuild', phase='start', bdms=bdms), mock.call(ctxt, self.inst, self.inst.host, - action='rebuild', phase='end')]) + action='rebuild', phase='end', bdms=bdms)]) mock_setup_networks_on_host.assert_called_once_with( ctxt, self.inst, self.inst.host) diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py index dc610404ce..9a3844fca3 100644 --- a/nova/tests/unit/compute/test_compute_mgr.py +++ b/nova/tests/unit/compute/test_compute_mgr.py @@ -155,10 +155,11 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase): specd_compute._shutdown_instance = _mark_shutdown mock_inst.info_cache = call_tracker + mock_bdms = mock.Mock() specd_compute._delete_instance(specd_compute, self.context, mock_inst, - mock.Mock()) + mock_bdms) methods_called = [n for n, a, k in call_tracker.mock_calls] self.assertEqual(['clear_events_for_instance', @@ -169,7 +170,8 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase): mock_inst, specd_compute.host, action='delete', - phase='start') + phase='start', + bdms=mock_bdms) def _make_compute_node(self, hyp_hostname, cn_id): cn = mock.Mock(spec_set=['hypervisor_hostname', 'id', @@ -296,9 +298,9 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase): mock_notify.assert_has_calls([ mock.call(self.context, instance, 'fake-mini', - action='delete', phase='start'), + action='delete', phase='start', bdms=[]), mock.call(self.context, instance, 'fake-mini', - action='delete', phase='end')]) + action='delete', phase='end', bdms=[])]) def test_check_device_tagging_no_tagging(self): bdms = objects.BlockDeviceMappingList(objects=[ @@ -1207,9 +1209,9 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase): notify=True, try_deallocate_networks=False) mock_notify.assert_has_calls([ mock.call(self.context, instance, 'fake-mini', - action='shutdown', phase='start'), + action='shutdown', phase='start', bdms=bdms), mock.call(self.context, instance, 'fake-mini', - action='shutdown', phase='end')]) + action='shutdown', phase='end', bdms=bdms)]) @mock.patch('nova.context.RequestContext.elevated') @mock.patch('nova.objects.Instance.get_network_info') @@ -3595,7 +3597,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase): ) mock_notify.assert_called_once_with( mock.ANY, instance, 'fake-mini', action='rebuild', phase='error', - exception=exc) + exception=exc, bdms=None) def test_rebuild_deleting(self): instance = fake_instance.fake_instance_obj(self.context) @@ -6088,7 +6090,8 @@ class ComputeManagerMigrationTestCase(test.NoDBTestCase): @mock.patch('nova.objects.BlockDeviceMappingList.get_by_instance_uuid') def _test(mock_bdm, mock_lmcf, mock_notify, mock_nwapi, mock_notify_about_instance_action): - mock_bdm.return_value = objects.BlockDeviceMappingList() + bdms = objects.BlockDeviceMappingList() + mock_bdm.return_value = bdms mock_lmcf.return_value = False, False mock_instance = mock.MagicMock() compute._rollback_live_migration(self.context, @@ -6099,9 +6102,11 @@ class ComputeManagerMigrationTestCase(test.NoDBTestCase): mock_instance.project_id, test.MatchType(dict)) mock_notify_about_instance_action.assert_has_calls([ mock.call(self.context, mock_instance, compute.host, - action='live_migration_rollback', phase='start'), + action='live_migration_rollback', phase='start', + bdms=bdms), mock.call(self.context, mock_instance, compute.host, - action='live_migration_rollback', phase='end')]) + action='live_migration_rollback', phase='end', + bdms=bdms)]) self.assertIsInstance(mock_lmcf.call_args_list[0][0][0], migrate_data_obj.LiveMigrateData) diff --git a/nova/tests/unit/compute/test_compute_utils.py b/nova/tests/unit/compute/test_compute_utils.py index 8ccc83a912..2453d49cad 100644 --- a/nova/tests/unit/compute/test_compute_utils.py +++ b/nova/tests/unit/compute/test_compute_utils.py @@ -491,13 +491,23 @@ class UsageInfoTestCase(test.TestCase): def test_notify_about_instance_action(self): instance = create_instance(self.context) + bdms = block_device_obj.block_device_make_list( + self.context, + [fake_block_device.FakeDbBlockDeviceDict( + {'source_type': 'volume', + 'device_name': '/dev/vda', + 'instance_uuid': 'f8000000-0000-0000-0000-000000000000', + 'destination_type': 'volume', + 'boot_index': 0, + 'volume_id': 'de8836ac-d75e-11e2-8271-5254009297d6'})]) compute_utils.notify_about_instance_action( self.context, instance, host='fake-compute', action='delete', - phase='start') + phase='start', + bdms=bdms) self.assertEqual(len(fake_notifier.VERSIONED_NOTIFICATIONS), 1) notification = fake_notifier.VERSIONED_NOTIFICATIONS[0] @@ -522,6 +532,15 @@ class UsageInfoTestCase(test.TestCase): self.assertIn(attr, payload, "Key %s not in payload" % attr) self.assertEqual(payload['image_uuid'], uuids.fake_image_ref) + self.assertEqual(1, len(payload['block_devices'])) + payload_bdm = payload['block_devices'][0]['nova_object.data'] + self.assertEqual( + {'boot_index': 0, + 'delete_on_termination': False, + 'device_name': '/dev/vda', + 'tag': None, + 'volume_id': 'de8836ac-d75e-11e2-8271-5254009297d6'}, + payload_bdm) def test_notify_about_instance_create(self): keypair = objects.KeyPair(name='my-key', user_id='fake', type='ssh', diff --git a/nova/tests/unit/compute/test_shelve.py b/nova/tests/unit/compute/test_shelve.py index af5319ef9f..8432baa6e7 100644 --- a/nova/tests/unit/compute/test_shelve.py +++ b/nova/tests/unit/compute/test_shelve.py @@ -47,6 +47,7 @@ def _fake_resources(): class ShelveComputeManagerTestCase(test_compute.BaseTestCase): + @mock.patch.object(objects.BlockDeviceMappingList, 'get_by_instance_uuid') @mock.patch.object(nova.compute.manager.ComputeManager, '_terminate_volume_connections') @mock.patch.object(nova.virt.fake.SmallFakeDriver, 'power_off') @@ -58,7 +59,7 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase): def _shelve_instance(self, shelved_offload_time, mock_notify, mock_notify_instance_usage, mock_get_power_state, mock_snapshot, mock_power_off, mock_terminate, - clean_shutdown=True): + mock_get_bdms, clean_shutdown=True): mock_get_power_state.return_value = 123 CONF.set_override('shelved_offload_time', shelved_offload_time) @@ -70,6 +71,11 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase): instance.task_state = task_states.SHELVING instance.save() + fake_bdms = None + if shelved_offload_time == 0: + fake_bdms = objects.BlockDeviceMappingList() + mock_get_bdms.return_value = fake_bdms + tracking = {'last_state': instance.vm_state} def check_save(expected_task_state=None): @@ -119,9 +125,9 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase): clean_shutdown=clean_shutdown) mock_notify.assert_has_calls([ mock.call(self.context, instance, 'fake-mini', - action='shelve', phase='start'), + action='shelve', phase='start', bdms=fake_bdms), mock.call(self.context, instance, 'fake-mini', - action='shelve', phase='end')]) + action='shelve', phase='end', bdms=fake_bdms)]) # prepare expect call lists mock_notify_instance_usage_call_list = [ @@ -184,6 +190,7 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase): instance = self._shelve_offload(clean_shutdown=False) mock_power_off.assert_called_once_with(instance, 0, 0) + @mock.patch.object(objects.BlockDeviceMappingList, 'get_by_instance_uuid') @mock.patch.object(nova.compute.manager.ComputeManager, '_terminate_volume_connections') @mock.patch('nova.compute.resource_tracker.ResourceTracker.' @@ -197,22 +204,26 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase): @mock.patch('nova.compute.utils.notify_about_instance_action') def _shelve_offload(self, mock_notify, mock_notify_instance_usage, mock_get_power_state, mock_update_resource_tracker, - mock_delete_alloc, mock_terminate, + mock_delete_alloc, mock_terminate, mock_get_bdms, clean_shutdown=True): host = 'fake-mini' instance = self._create_fake_instance_obj(params={'host': host}) instance.task_state = task_states.SHELVING instance.save() self.useFixture(utils_fixture.TimeFixture()) + fake_bdms = objects.BlockDeviceMappingList() + mock_get_bdms.return_value = fake_bdms with mock.patch.object(instance, 'save'): self.compute.shelve_offload_instance(self.context, instance, clean_shutdown=clean_shutdown) mock_notify.assert_has_calls([ mock.call(self.context, instance, 'fake-mini', - action='shelve_offload', phase='start'), + action='shelve_offload', phase='start', + bdms=fake_bdms), mock.call(self.context, instance, 'fake-mini', - action='shelve_offload', phase='end')]) + action='shelve_offload', phase='end', + bdms=fake_bdms)]) self.assertEqual(vm_states.SHELVED_OFFLOADED, instance.vm_state) self.assertIsNone(instance.task_state) @@ -236,6 +247,7 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase): return instance + @mock.patch('nova.objects.BlockDeviceMappingList.get_by_instance_uuid') @mock.patch('nova.compute.utils.notify_about_instance_action') @mock.patch.object(nova.compute.manager.ComputeManager, '_notify_about_instance_usage') @@ -248,7 +260,10 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase): def test_unshelve(self, mock_setup_network, mock_get_power_state, mock_spawn, mock_prep_block_device, mock_notify_instance_usage, - mock_notify_instance_action): + mock_notify_instance_action, + mock_get_bdms): + mock_bdms = mock.Mock() + mock_get_bdms.return_value = mock_bdms instance = self._create_fake_instance_obj() instance.task_state = task_states.UNSHELVING instance.save() @@ -312,9 +327,9 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase): mock_notify_instance_action.assert_has_calls([ mock.call(self.context, instance, 'fake-mini', - action='unshelve', phase='start'), + action='unshelve', phase='start', bdms=mock_bdms), mock.call(self.context, instance, 'fake-mini', - action='unshelve', phase='end')]) + action='unshelve', phase='end', bdms=mock_bdms)]) # prepare expect call lists mock_notify_instance_usage_call_list = [ @@ -346,6 +361,7 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase): self.assertEqual(self.compute.host, instance.host) self.assertFalse(instance.auto_disk_config) + @mock.patch('nova.objects.BlockDeviceMappingList.get_by_instance_uuid') @mock.patch('nova.compute.utils.notify_about_instance_action') @mock.patch.object(nova.compute.resource_tracker.ResourceTracker, 'instance_claim') @@ -363,7 +379,10 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase): mock_prep_block_device, mock_spawn, mock_get_power_state, mock_setup_network, mock_instance_claim, - mock_notify_instance_action): + mock_notify_instance_action, + mock_get_bdms): + mock_bdms = mock.Mock() + mock_get_bdms.return_value = mock_bdms instance = self._create_fake_instance_obj() node = test_compute.NODENAME limits = {} @@ -405,9 +424,9 @@ class ShelveComputeManagerTestCase(test_compute.BaseTestCase): mock_notify_instance_action.assert_has_calls([ mock.call(self.context, instance, 'fake-mini', - action='unshelve', phase='start'), + action='unshelve', phase='start', bdms=mock_bdms), mock.call(self.context, instance, 'fake-mini', - action='unshelve', phase='end')]) + action='unshelve', phase='end', bdms=mock_bdms)]) # prepare expect call lists mock_notify_instance_usage_call_list = [