diff --git a/openstack/resource.py b/openstack/resource.py index 60f377ecf..27db32702 100644 --- a/openstack/resource.py +++ b/openstack/resource.py @@ -2503,8 +2503,10 @@ def wait_for_delete(session, resource, interval, wait, callback=None): resource = resource.fetch(session, skip_cache=True) if not resource: return orig_resource - if resource.status.lower() == 'deleted': - return resource + # Some resources like VolumeAttachment don't have status field. + if hasattr(resource, 'status'): + if resource.status.lower() == 'deleted': + return resource except exceptions.NotFoundException: return orig_resource diff --git a/openstack/tests/functional/compute/v2/test_volume_attachment.py b/openstack/tests/functional/compute/v2/test_volume_attachment.py index c65da7696..1e357c855 100644 --- a/openstack/tests/functional/compute/v2/test_volume_attachment.py +++ b/openstack/tests/functional/compute/v2/test_volume_attachment.py @@ -137,3 +137,17 @@ class TestServerVolumeAttachment(ft_base.BaseComputeTest): status='available', wait=self._wait_for_timeout, ) + + # Wait for the attachment to be deleted. + # This is done to prevent a race between the BDM + # record being deleted and we trying to delete the server. + self.user_cloud.compute.wait_for_delete( + volume_attachment, + wait=self._wait_for_timeout, + ) + + # Verify the server doesn't have any volume attachment + volume_attachments = list( + self.user_cloud.compute.volume_attachments(self.server) + ) + self.assertEqual(0, len(volume_attachments))