From ba6f4037ab982b3bcf2de48cb51f919b3f37cbaf Mon Sep 17 00:00:00 2001 From: Matt Riedemann Date: Fri, 19 Jun 2015 11:25:43 -0700 Subject: [PATCH] Set encrypted key in connection_info during initialize There are encrypted volume tests in Tempest which are passing in the ceph job but the encryption providers in nova (luks and cryptsetup) are not actually being called in nova because the 'encrypted' key isn't being set in connection_info for the Rbd volume driver, and nova is keying off that value to determine if it needs to run it's encryption providers. So the tests are passing in the ceph job but it's a total false positive and the API should actually fail - either the cinder API to create the encrypted volumes if the Rbd volume driver in Cinder doesn't support encryption, or the volume attach call in nova if it can't encrypt the connected volume, either way the test should fail until that support is baked into nova. I'm not aware of any kind of 'supports_encryption' or 'encryptable' capability flag for cinder volume drivers, but that might be needed for the volume create API to fail if trying to create a volume from an encrypted volume type where the volume driver itself doesn't support encryption - but maybe it's only a nova problem since nova has the encryption providers. This is fixed generically in the VolumeManager's initialize_connection method where we check for the encrypted flag being set in the volume driver method and if not, the manager sets it based on the volume.encryption_key_id value. We do this globally since there are other volume drivers besides rbd that aren't setting the encrypted key in connection_info, but we test rbd in the gate via the ceph job so most of the bug tracking is around validation of the ceph job. Related Nova change: I8efc2628b09d4e9e59831353daa080b20e17ccde Depends-On: I8548d41095513b9e669f773e3f35353e9228ead9 DocImpact: Attaching 'encrypted' RBD volumes to a Nova server instance created from the libvirt virt driver will fail since RBD volume encryption is not currently supported in Nova's libvirt driver. Closes-Bug: #1440227 Related-Bug: #1463525 Change-Id: I03f8cae05cc117e14f7482115de685fc9f3fa54a --- cinder/tests/unit/test_volume.py | 21 +++++++++++++++++---- cinder/volume/manager.py | 5 +++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/cinder/tests/unit/test_volume.py b/cinder/tests/unit/test_volume.py index 9196497d8..24520ab26 100644 --- a/cinder/tests/unit/test_volume.py +++ b/cinder/tests/unit/test_volume.py @@ -1955,17 +1955,25 @@ class VolumeTestCase(BaseVolumeTestCase): 'name': 'fake_name', 'host': 'fake_host', 'id': 'fake_volume_id', - 'volume_admin_metadata': fake_admin_meta} + 'volume_admin_metadata': fake_admin_meta, + 'encryption_key_id': ('d371e7bb-7392-4c27-' + 'ac0b-ebd9f5d16078')} mock_volume_get.return_value = fake_volume mock_volume_update.return_value = fake_volume connector = {'ip': 'IP', 'initiator': 'INITIATOR'} mock_driver_init.return_value = { 'driver_volume_type': 'iscsi', - 'data': {'access_mode': 'rw'} + 'data': {'access_mode': 'rw', + 'encrypted': False} } mock_data_get.return_value = [] - self.volume.initialize_connection(self.context, 'id', connector) + conn_info = self.volume.initialize_connection(self.context, 'id', + connector) + # Asserts that if the driver sets the encrypted flag then the + # VolumeManager doesn't overwrite it regardless of what's in the + # volume for the encryption_key_id field. + self.assertFalse(conn_info['data']['encrypted']) mock_driver_init.assert_called_with(fake_volume, connector) data = [{'key': 'key1', 'value': 'value1'}] @@ -1991,7 +1999,12 @@ class VolumeTestCase(BaseVolumeTestCase): connector['initiator'] = None mock_data_update.reset_mock() mock_data_get.reset_mock() - self.volume.initialize_connection(self.context, 'id', connector) + mock_driver_init.return_value['data'].pop('encrypted') + conn_info = self.volume.initialize_connection(self.context, 'id', + connector) + # Asserts that VolumeManager sets the encrypted flag if the driver + # doesn't set it. + self.assertTrue(conn_info['data']['encrypted']) mock_driver_init.assert_called_with(fake_volume, connector) self.assertFalse(mock_data_get.called) self.assertFalse(mock_data_update.called) diff --git a/cinder/volume/manager.py b/cinder/volume/manager.py index 71d01e126..8c323ab08 100644 --- a/cinder/volume/manager.py +++ b/cinder/volume/manager.py @@ -1144,6 +1144,11 @@ class VolumeManager(manager.SchedulerDependentManager): else 'rw') conn_info['data']['access_mode'] = access_mode + # Add encrypted flag to connection_info if not set in the driver. + if conn_info['data'].get('encrypted') is None: + encrypted = bool(volume.get('encryption_key_id')) + conn_info['data']['encrypted'] = encrypted + LOG.info(_LI("Initialize volume connection completed successfully."), resource=volume) return conn_info -- 2.45.2