summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2018-08-09 05:54:21 +0000
committerGerrit Code Review <review@openstack.org>2018-08-09 05:54:21 +0000
commit62b34ec6e9ce07ac54b386226c2d414da6098ed0 (patch)
tree34ec269897efb4e080f41a70ae29d9c8eb20f6b2
parentd9877f83de022278225aea2ce1238ec638a6a80c (diff)
parent9c0123eb70b0928786d81469cc3ccbd4f30f38fe (diff)
Merge "Fix _attachment_reserve to not allow attaching an invalid status volume"
-rw-r--r--cinder/tests/unit/volume/test_volume.py18
-rw-r--r--cinder/volume/api.py11
2 files changed, 24 insertions, 5 deletions
diff --git a/cinder/tests/unit/volume/test_volume.py b/cinder/tests/unit/volume/test_volume.py
index f88af88..7b1d39d 100644
--- a/cinder/tests/unit/volume/test_volume.py
+++ b/cinder/tests/unit/volume/test_volume.py
@@ -1859,6 +1859,24 @@ class VolumeTestCase(base.BaseVolumeTestCase):
1859 self.assertIn("status must be available or downloading", 1859 self.assertIn("status must be available or downloading",
1860 six.text_type(ex)) 1860 six.text_type(ex))
1861 1861
1862 def test_attachment_reserve_with_instance_uuid_error_volume(self):
1863 # Tests that trying to create an attachment (with an instance_uuid
1864 # provided) on a volume that's not 'available' or 'downloading' status
1865 # will fail if the volume does not have any attachments, similar to how
1866 # the volume reserve action works.
1867 volume = tests_utils.create_volume(self.context, status='error')
1868 # Assert that we're not dealing with a multiattach volume and that
1869 # it does not have any existing attachments.
1870 self.assertFalse(volume.multiattach)
1871 self.assertEqual(0, len(volume.volume_attachment))
1872 # Try attaching an instance to the volume which should fail based on
1873 # the volume status.
1874 ex = self.assertRaises(exception.InvalidVolume,
1875 self.volume_api._attachment_reserve,
1876 self.context, volume, fake.UUID1)
1877 self.assertIn("status must be available or downloading",
1878 six.text_type(ex))
1879
1862 def test_unreserve_volume_success_in_use(self): 1880 def test_unreserve_volume_success_in_use(self):
1863 UUID = six.text_type(uuid.uuid4()) 1881 UUID = six.text_type(uuid.uuid4())
1864 volume = tests_utils.create_volume(self.context, status='attaching') 1882 volume = tests_utils.create_volume(self.context, status='attaching')
diff --git a/cinder/volume/api.py b/cinder/volume/api.py
index 0d16479..d6c6699 100644
--- a/cinder/volume/api.py
+++ b/cinder/volume/api.py
@@ -2086,18 +2086,19 @@ class API(base.Base):
2086 result = vref.conditional_update({'status': 'reserved'}, expected) 2086 result = vref.conditional_update({'status': 'reserved'}, expected)
2087 2087
2088 if not result: 2088 if not result:
2089 # Make sure we're not going to the same instance, in which case
2090 # it could be a live-migrate or similar scenario (LP BUG: 1694530)
2091 override = False 2089 override = False
2092 if instance_uuid: 2090 if instance_uuid:
2093 override = True
2094 # Refresh the volume reference in case multiple instances were 2091 # Refresh the volume reference in case multiple instances were
2095 # being concurrently attached to the same non-multiattach 2092 # being concurrently attached to the same non-multiattach
2096 # volume. 2093 # volume.
2097 vref = objects.Volume.get_by_id(ctxt, vref.id) 2094 vref = objects.Volume.get_by_id(ctxt, vref.id)
2098 for attachment in vref.volume_attachment: 2095 for attachment in vref.volume_attachment:
2099 if attachment.instance_uuid != instance_uuid: 2096 # If we're attaching the same volume to the same instance,
2100 override = False 2097 # we could be migrating the instance to another host in
2098 # which case we want to allow the reservation.
2099 # (LP BUG: 1694530)
2100 if attachment.instance_uuid == instance_uuid:
2101 override = True
2101 break 2102 break
2102 2103
2103 if not override: 2104 if not override: