]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Prevent creating encrypted volume with image
authorlisali <xiaoyan.li@intel.com>
Fri, 7 Aug 2015 06:35:27 +0000 (14:35 +0800)
committerlisali <xiaoyan.li@intel.com>
Tue, 11 Aug 2015 01:23:28 +0000 (09:23 +0800)
When creating an encrypted volume with a unencrypted image,
cinder just copies the unencrypted data to the volume,
which keeps unencrypted data in the volume.
But when booting/attaching the volume to Nova, it thinks
encrypted data on the volume. As a result, Nova reads
the data incorrectly.

The fix is to prevent such action. Later, we can
implement to write encrypted data in encrypted volumes
when creating from unencrypted image.

Change-Id: I0af8318222cee023451c38812bf83cdb4086faae
Closes-bug: #1482464

cinder/tests/unit/volume/flows/test_create_volume_flow.py
cinder/volume/flows/api/create_volume.py

index 5ec263d0bcece39a795510447b3d7de958c38ef0..5b7a4be1ab5098fd627cdaf0429de394ba4fce71 100644 (file)
@@ -21,6 +21,8 @@ from cinder import exception
 from cinder import test
 from cinder.tests.unit import fake_snapshot
 from cinder.tests.unit import fake_volume
+from cinder.tests.unit.image import fake as fake_image
+from cinder.tests.unit.keymgr import mock_key_mgr
 from cinder.tests.unit.volume.flows import fake_volume_api
 from cinder.volume.flows.api import create_volume
 from cinder.volume.flows.manager import create_volume as create_volume_manager
@@ -77,6 +79,97 @@ class CreateVolumeFlowTestCase(test.TestCase):
 
         task._cast_create_volume(self.ctxt, spec, props)
 
+    @mock.patch('cinder.volume.volume_types.is_encrypted')
+    @mock.patch('cinder.volume.flows.api.create_volume.'
+                'ExtractVolumeRequestTask.'
+                '_get_volume_type_id')
+    def test_extract_volume_request_from_image_encrypted(
+            self,
+            fake_get_volume_type_id,
+            fake_is_encrypted):
+
+        fake_image_service = fake_image.FakeImageService()
+        image_id = 1
+        image_meta = {}
+        image_meta['id'] = image_id
+        image_meta['status'] = 'active'
+        image_meta['size'] = 1
+        fake_image_service.create(self.ctxt, image_meta)
+        fake_key_manager = mock_key_mgr.MockKeyManager()
+
+        task = create_volume.ExtractVolumeRequestTask(
+            fake_image_service,
+            {'nova'})
+
+        fake_is_encrypted.return_value = True
+        self.assertRaises(exception.InvalidInput,
+                          task.execute,
+                          self.ctxt,
+                          size=1,
+                          snapshot=None,
+                          image_id=image_id,
+                          source_volume=None,
+                          availability_zone='nova',
+                          volume_type=None,
+                          metadata=None,
+                          key_manager=fake_key_manager,
+                          source_replica=None,
+                          consistencygroup=None,
+                          cgsnapshot=None)
+
+    @mock.patch('cinder.volume.volume_types.is_encrypted')
+    @mock.patch('cinder.volume.volume_types.get_volume_type_qos_specs')
+    @mock.patch('cinder.volume.flows.api.create_volume.'
+                'ExtractVolumeRequestTask.'
+                '_get_volume_type_id')
+    def test_extract_volume_request_from_image(
+            self,
+            fake_get_type_id,
+            fake_get_qos,
+            fake_is_encrypted):
+
+        fake_image_service = fake_image.FakeImageService()
+        image_id = 2
+        image_meta = {}
+        image_meta['id'] = image_id
+        image_meta['status'] = 'active'
+        image_meta['size'] = 1
+        fake_image_service.create(self.ctxt, image_meta)
+        fake_key_manager = mock_key_mgr.MockKeyManager()
+        volume_type = 'type1'
+
+        task = create_volume.ExtractVolumeRequestTask(
+            fake_image_service,
+            {'nova'})
+
+        fake_is_encrypted.return_value = False
+        fake_get_type_id.return_value = 1
+        fake_get_qos.return_value = {'qos_specs': None}
+        result = task.execute(self.ctxt,
+                              size=1,
+                              snapshot=None,
+                              image_id=image_id,
+                              source_volume=None,
+                              availability_zone='nova',
+                              volume_type=volume_type,
+                              metadata=None,
+                              key_manager=fake_key_manager,
+                              source_replica=None,
+                              consistencygroup=None,
+                              cgsnapshot=None)
+        expected_result = {'size': 1,
+                           'snapshot_id': None,
+                           'source_volid': None,
+                           'availability_zone': 'nova',
+                           'volume_type': volume_type,
+                           'volume_type_id': 1,
+                           'encryption_key_id': None,
+                           'qos_specs': None,
+                           'source_replicaid': None,
+                           'consistencygroup_id': None,
+                           'cgsnapshot_id': None, }
+        self.assertEqual(expected_result, result)
+
 
 class CreateVolumeFlowManagerTestCase(test.TestCase):
 
index 5f1a4adfcbb5b22d6f107ba73e1194d430a90a39..4af58ba9686267ea72392a254ce424c6073362ff 100644 (file)
@@ -382,6 +382,13 @@ class ExtractVolumeRequestTask(flow_utils.CinderTask):
         volume_type_id = self._get_volume_type_id(volume_type,
                                                   source_volume, snapshot)
 
+        if image_id and volume_types.is_encrypted(context, volume_type_id):
+            msg = _('Create encrypted volumes with type %(type)s '
+                    'from image %(image)s is not supported.')
+            msg = msg % {'type': volume_type_id,
+                         'image': image_id, }
+            raise exception.InvalidInput(reason=msg)
+
         encryption_key_id = self._get_encryption_key_id(key_manager,
                                                         context,
                                                         volume_type_id,