summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2018-04-18 01:49:43 +0000
committerGerrit Code Review <review@openstack.org>2018-04-18 01:49:43 +0000
commit0e951157bdf0ec458510ecd9c5e2ffa820471b2c (patch)
treec91f132741278dadb6d79bf404ade740bb05ad1c
parent1b349d4bb0df3ab3a31f6f1b511cf32132c8ed0e (diff)
parent470e1bd1e42bfeb4da59e9048894be142f4cd25d (diff)
downloadcinder-0e951157bdf0ec458510ecd9c5e2ffa820471b2c.tar.gz
Merge "Refresh volume when checking for conflicting attachments" into stable/queens
-rw-r--r--cinder/tests/unit/volume/test_volume.py22
-rw-r--r--cinder/volume/api.py4
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