diff options
author | Zuul <zuul@review.openstack.org> | 2018-04-18 01:49:43 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2018-04-18 01:49:43 +0000 |
commit | 0e951157bdf0ec458510ecd9c5e2ffa820471b2c (patch) | |
tree | c91f132741278dadb6d79bf404ade740bb05ad1c | |
parent | 1b349d4bb0df3ab3a31f6f1b511cf32132c8ed0e (diff) | |
parent | 470e1bd1e42bfeb4da59e9048894be142f4cd25d (diff) | |
download | cinder-0e951157bdf0ec458510ecd9c5e2ffa820471b2c.tar.gz |
Merge "Refresh volume when checking for conflicting attachments" into stable/queens
-rw-r--r-- | cinder/tests/unit/volume/test_volume.py | 22 | ||||
-rw-r--r-- | cinder/volume/api.py | 4 |
2 files changed, 26 insertions, 0 deletions
diff --git a/cinder/tests/unit/volume/test_volume.py b/cinder/tests/unit/volume/test_volume.py index 855981cfc..ab777fc15 100644 --- a/cinder/tests/unit/volume/test_volume.py +++ b/cinder/tests/unit/volume/test_volume.py @@ -1804,6 +1804,28 @@ class VolumeTestCase(base.BaseVolumeTestCase): self.assertEqual(attachment.attach_status, 'reserved') + def test_attachment_reserve_conditional_update_attach_race(self): + # Tests a scenario where two instances are racing to attach the + # same multiattach=False volume. One updates the volume status to + # "reserved" but the other fails the conditional update which is + # then validated to not be the same instance that is already attached + # to the multiattach=False volume which triggers a failure. + volume = tests_utils.create_volume(self.context) + # Assert that we're not dealing with a multiattach volume and that + # it does not have any existing attachments. + self.assertFalse(volume.multiattach) + self.assertEqual(0, len(volume.volume_attachment)) + # Attach the first instance which is OK and should update the volume + # status to 'reserved'. + self.volume_api._attachment_reserve(self.context, volume, fake.UUID1) + # Try attaching a different instance to the same volume which should + # fail. + ex = self.assertRaises(exception.InvalidVolume, + self.volume_api._attachment_reserve, + self.context, volume, fake.UUID2) + self.assertIn("status must be available or downloading", + six.text_type(ex)) + def test_unreserve_volume_success_in_use(self): UUID = six.text_type(uuid.uuid4()) volume = tests_utils.create_volume(self.context, status='attaching') diff --git a/cinder/volume/api.py b/cinder/volume/api.py index 22591997b..e6ea48fe7 100644 --- a/cinder/volume/api.py +++ b/cinder/volume/api.py @@ -2088,6 +2088,10 @@ class API(base.Base): override = False if instance_uuid: override = True + # Refresh the volume reference in case multiple instances were + # being concurrently attached to the same non-multiattach + # volume. + vref = objects.Volume.get_by_id(ctxt, vref.id) for attachment in vref.volume_attachment: if attachment.instance_uuid != instance_uuid: override = False |