diff --git a/nova/compute/manager.py b/nova/compute/manager.py index b1bd1f5a04b1..79cc1d4026f5 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -4958,15 +4958,14 @@ class ComputeManager(manager.Manager): connector = stashed_connector self.volume_api.terminate_connection(context, volume_id, connector) - - if destroy_bdm: - bdm.destroy() - + self.volume_api.detach(context.elevated(), volume_id, instance.uuid, + attachment_id) info = dict(volume_id=volume_id) self._notify_about_instance_usage( context, instance, "volume.detach", extra_usage_info=info) - self.volume_api.detach(context.elevated(), volume_id, instance.uuid, - attachment_id) + + if destroy_bdm: + bdm.destroy() @wrap_exception() @wrap_instance_fault diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index afe05ad07cb0..4ad891a29d98 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -432,9 +432,27 @@ class ComputeVolumeTestCase(BaseTestCase): self.assertRaises( test.TestingException, self.compute.detach_volume, self.context, 'fake', instance, 'fake_id') - mock_internal_detach.assert_called_once_with(self.context, - instance, - fake_bdm, {}) + self.assertFalse(mock_destroy.called) + + def test_detach_volume_bdm_destroyed(self): + # Assert that the BDM is destroyed given a successful call to detach + # the volume from the instance in Cinder. + fake_bdm = objects.BlockDeviceMapping(**self.fake_volume) + instance = self._create_fake_instance_obj() + + with test.nested( + mock.patch.object(self.compute, '_driver_detach_volume'), + mock.patch.object(self.compute.volume_api, 'detach'), + mock.patch.object(objects.BlockDeviceMapping, + 'get_by_volume_and_instance'), + mock.patch.object(fake_bdm, 'destroy') + ) as (mock_internal_detach, mock_detach, mock_get, mock_destroy): + mock_get.return_value = fake_bdm + self.compute.detach_volume(self.context, uuids.volume_id, instance, + uuids.attachment_id) + mock_detach.assert_called_once_with(mock.ANY, uuids.volume_id, + instance.uuid, + uuids.attachment_id) self.assertTrue(mock_destroy.called) def test_await_block_device_created_too_slow(self):