]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Snapshot of bootable volume goes in error state
authorPranaliDeore <pranali11.deore@nttdata.com>
Tue, 27 Jan 2015 12:46:58 +0000 (04:46 -0800)
committerPranaliDeore <pranali11.deore@nttdata.com>
Mon, 16 Feb 2015 05:43:03 +0000 (21:43 -0800)
If volume is not created from image, no glance
metadata would be available for that volume/snapshot
in volume glance metadata table. So simply catch
GlanceMetadataNotFound and do nothing.

Closes-Bug: #1413880
Change-Id: Ic3267d422912f94e966412859e2b8bddeddfb75f

cinder/tests/test_volume.py
cinder/volume/flows/manager/create_volume.py
cinder/volume/manager.py

index 4a3756afa791ccdc399dab2ca48bd42443db5050..24c2024972a3e79a4223e9408a40348f4a58d5e2 100644 (file)
@@ -1097,6 +1097,202 @@ class VolumeTestCase(BaseVolumeTestCase):
         # calling manager.create_volume.
         self.assertRaises(exception.VolumeNotFound, gthreads[0].wait)
 
+    def _raise_metadata_copy_failure(self, method, dst_vol_id, **kwargs):
+        # MetadataCopyFailure exception will be raised if DB service is Down
+        # while copying the volume glance metadata
+        with mock.patch.object(db, method) as mock_db:
+            mock_db.side_effect = exception.MetadataCopyFailure(
+                reason="Because of DB service down.")
+            self.assertRaises(exception.MetadataCopyFailure,
+                              self.volume.create_volume,
+                              self.context,
+                              dst_vol_id,
+                              **kwargs)
+
+        # ensure that status of volume is 'error'
+        vol = db.volume_get(self.context, dst_vol_id)
+        self.assertEqual('error', vol['status'])
+
+        # cleanup resource
+        db.volume_destroy(self.context, dst_vol_id)
+
+    def test_create_volume_from_volume_with_glance_volume_metadata_none(self):
+        # create source volume
+        src_vol = tests_utils.create_volume(self.context, **self.volume_params)
+        src_vol_id = src_vol['id']
+
+        self.volume.create_volume(self.context, src_vol_id)
+        # set bootable flag of volume to True
+        db.volume_update(self.context, src_vol['id'], {'bootable': True})
+
+        # create volume from source volume
+        dst_vol = tests_utils.create_volume(self.context,
+                                            **self.volume_params)
+        self.volume.create_volume(self.context,
+                                  dst_vol['id'],
+                                  source_volid=src_vol_id)
+
+        self.assertRaises(exception.GlanceMetadataNotFound,
+                          db.volume_glance_metadata_copy_from_volume_to_volume,
+                          self.context, src_vol_id, dst_vol['id'])
+
+        # ensure that status of volume is 'available'
+        vol = db.volume_get(self.context, dst_vol['id'])
+        self.assertEqual('available', vol['status'])
+
+        # cleanup resource
+        db.volume_destroy(self.context, src_vol_id)
+        db.volume_destroy(self.context, dst_vol['id'])
+
+    def test_create_volume_from_volume_raise_metadata_copy_failure(
+            self):
+        # create source volume
+        src_vol = tests_utils.create_volume(self.context, **self.volume_params)
+        src_vol_id = src_vol['id']
+
+        self.volume.create_volume(self.context, src_vol_id)
+        # set bootable flag of volume to True
+        db.volume_update(self.context, src_vol['id'], {'bootable': True})
+
+        # create volume from source volume
+        dst_vol = tests_utils.create_volume(self.context,
+                                            source_volid=src_vol_id,
+                                            **self.volume_params)
+        self._raise_metadata_copy_failure(
+            'volume_glance_metadata_copy_from_volume_to_volume',
+            dst_vol['id'],
+            source_volid=src_vol_id)
+
+        # cleanup resource
+        db.volume_destroy(self.context, src_vol_id)
+
+    def test_create_volume_from_snapshot_raise_metadata_copy_failure(
+            self):
+        # create source volume
+        src_vol = tests_utils.create_volume(self.context, **self.volume_params)
+        src_vol_id = src_vol['id']
+
+        self.volume.create_volume(self.context, src_vol_id)
+        # set bootable flag of volume to True
+        db.volume_update(self.context, src_vol['id'], {'bootable': True})
+
+        # create volume from snapshot
+        snapshot_id = self._create_snapshot(src_vol['id'])['id']
+        self.volume.create_snapshot(self.context, src_vol['id'], snapshot_id)
+
+        # ensure that status of snapshot is 'available'
+        snapshot_ref = db.snapshot_get(self.context, snapshot_id)['status']
+        self.assertEqual('available', snapshot_ref)
+
+        dst_vol = tests_utils.create_volume(self.context,
+                                            **self.volume_params)
+        self._raise_metadata_copy_failure(
+            'volume_glance_metadata_copy_to_volume',
+            dst_vol['id'],
+            snapshot_id=snapshot_id)
+
+        # cleanup resource
+        db.snapshot_destroy(self.context, snapshot_id)
+        db.volume_destroy(self.context, src_vol_id)
+
+    @mock.patch(
+        'cinder.volume.driver.VolumeDriver.create_replica_test_volume')
+    def test_create_volume_from_srcreplica_raise_metadata_copy_failure(
+            self, _create_replica_test):
+        _create_replica_test.return_value = None
+        # create source volume
+        src_vol = tests_utils.create_volume(self.context, **self.volume_params)
+        src_vol_id = src_vol['id']
+
+        self.volume.create_volume(self.context, src_vol_id)
+        # set bootable flag of volume to True
+        db.volume_update(self.context, src_vol['id'], {'bootable': True})
+
+        # create volume from source volume
+        dst_vol = tests_utils.create_volume(self.context,
+                                            source_volid=src_vol_id,
+                                            **self.volume_params)
+        self._raise_metadata_copy_failure(
+            'volume_glance_metadata_copy_from_volume_to_volume',
+            dst_vol['id'],
+            source_volid=src_vol_id)
+
+        # cleanup resource
+        db.volume_destroy(self.context, src_vol_id)
+
+    def test_create_volume_from_snapshot_with_glance_volume_metadata_none(
+            self):
+        # create source volume
+        src_vol = tests_utils.create_volume(self.context, **self.volume_params)
+        src_vol_id = src_vol['id']
+
+        self.volume.create_volume(self.context, src_vol_id)
+        # set bootable flag of volume to True
+        db.volume_update(self.context, src_vol['id'], {'bootable': True})
+
+        volume = db.volume_get(self.context, src_vol_id)
+
+        # create snapshot of volume
+        snapshot_id = self._create_snapshot(volume['id'])['id']
+        self.volume.create_snapshot(self.context, volume['id'], snapshot_id)
+
+        # ensure that status of snapshot is 'available'
+        snapshot_ref = db.snapshot_get(self.context, snapshot_id)['status']
+        self.assertEqual('available', snapshot_ref)
+
+        # create volume from snapshot
+        dst_vol = tests_utils.create_volume(self.context,
+                                            **self.volume_params)
+        self.volume.create_volume(self.context,
+                                  dst_vol['id'],
+                                  snapshot_id=snapshot_id)
+
+        self.assertRaises(exception.GlanceMetadataNotFound,
+                          db.volume_glance_metadata_copy_to_volume,
+                          self.context, dst_vol['id'], snapshot_id)
+
+        # ensure that status of volume is 'available'
+        vol = db.volume_get(self.context, dst_vol['id'])
+        self.assertEqual('available', vol['status'])
+
+        # cleanup resource
+        db.snapshot_destroy(self.context, snapshot_id)
+        db.volume_destroy(self.context, src_vol_id)
+        db.volume_destroy(self.context, dst_vol['id'])
+
+    @mock.patch(
+        'cinder.volume.driver.VolumeDriver.create_replica_test_volume')
+    def test_create_volume_from_srcreplica_with_glance_volume_metadata_none(
+            self, _create_replica_test):
+        """Test volume can be created from a volume replica."""
+        _create_replica_test.return_value = None
+
+        volume_src = tests_utils.create_volume(self.context,
+                                               **self.volume_params)
+        self.volume.create_volume(self.context, volume_src['id'])
+        db.volume_update(self.context, volume_src['id'], {'bootable': True})
+
+        volume = db.volume_get(self.context, volume_src['id'])
+        volume_dst = tests_utils.create_volume(
+            self.context,
+            source_replicaid=volume['id'],
+            **self.volume_params)
+        self.volume.create_volume(self.context, volume_dst['id'],
+                                  source_replicaid=volume['id'])
+
+        self.assertRaises(exception.GlanceMetadataNotFound,
+                          db.volume_glance_metadata_copy_from_volume_to_volume,
+                          self.context, volume_src['id'], volume_dst['id'])
+
+        self.assertEqual('available',
+                         db.volume_get(self.context,
+                                       volume_dst['id']).status)
+        self.assertTrue(_create_replica_test.called)
+
+        # cleanup resource
+        db.volume_destroy(self.context, volume_dst['id'])
+        db.volume_destroy(self.context, volume_src['id'])
+
     def test_create_volume_from_snapshot_delete_lock_taken(self):
         # create source volume
         src_vol = tests_utils.create_volume(self.context, **self.volume_params)
@@ -2126,6 +2322,29 @@ class VolumeTestCase(BaseVolumeTestCase):
         db.snapshot_destroy(ctxt, snap_id)
         db.volume_destroy(ctxt, volume_id)
 
+    def test_create_snapshot_from_bootable_volume_with_volume_metadata_none(
+            self):
+        volume = tests_utils.create_volume(self.context, **self.volume_params)
+        volume_id = volume['id']
+
+        self.volume.create_volume(self.context, volume_id)
+        # set bootable flag of volume to True
+        db.volume_update(self.context, volume_id, {'bootable': True})
+
+        snapshot_id = self._create_snapshot(volume['id'])['id']
+        self.volume.create_snapshot(self.context, volume['id'], snapshot_id)
+        self.assertRaises(exception.GlanceMetadataNotFound,
+                          db.volume_snapshot_glance_metadata_get,
+                          self.context, snapshot_id)
+
+        # ensure that status of snapshot is 'available'
+        snapshot_ref = db.snapshot_get(self.context, snapshot_id)['status']
+        self.assertEqual('available', snapshot_ref)
+
+        # cleanup resource
+        db.snapshot_destroy(self.context, snapshot_id)
+        db.volume_destroy(self.context, volume_id)
+
     def test_delete_busy_snapshot(self):
         """Test snapshot can be created and deleted."""
 
index acc50fabb76de9b004786dd898413704d6473e56..fea8a063181ce3f46c57b6d672392babb5f47330 100644 (file)
@@ -394,6 +394,11 @@ class CreateVolumeFromSpecTask(flow_utils.CinderTask):
                                           'vol_id': volume_id})
                 self._capture_volume_image_metadata(context, volume_id,
                                                     image_id, image_meta)
+        except exception.GlanceMetadataNotFound:
+            # If volume is not created from image, No glance metadata
+            # would be available for that volume in
+            # volume glance metadata table
+            pass
         except exception.CinderException as ex:
             LOG.exception(exception_template % {'src_type': src_type,
                                                 'src_id': src_id,
index e488ecd3606afc95189541ed0e33e70588d035e9..5033c0689ba7f9d47d2124e937e2443941dbaa8b 100644 (file)
@@ -568,6 +568,11 @@ class VolumeManager(manager.SchedulerDependentManager):
             try:
                 self.db.volume_glance_metadata_copy_to_snapshot(
                     context, snapshot_ref['id'], volume_id)
+            except exception.GlanceMetadataNotFound:
+                # If volume is not created from image, No glance metadata
+                # would be available for that volume in
+                # volume glance metadata table
+                pass
             except exception.CinderException as ex:
                 LOG.exception(_LE("Failed updating %(snapshot_id)s"
                                   " metadata using the provided volumes"