diff --git a/nova/exception.py b/nova/exception.py index 7b0533435630..67f63a91b470 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -279,6 +279,11 @@ class VolumeNotCreated(NovaException): " attempts. And its status is %(volume_status)s.") +class VolumeEncryptionNotSupported(Invalid): + msg_fmt = _("Volume encryption is not supported for %(volume_type)s " + "volume %(volume_id)s") + + class InvalidKeypair(Invalid): ec2_code = 'InvalidKeyPair.Format' msg_fmt = _("Keypair data is invalid: %(reason)s") diff --git a/nova/tests/unit/volume/encryptors/test_cryptsetup.py b/nova/tests/unit/volume/encryptors/test_cryptsetup.py index ec9beadd1afb..5e523068cd7f 100644 --- a/nova/tests/unit/volume/encryptors/test_cryptsetup.py +++ b/nova/tests/unit/volume/encryptors/test_cryptsetup.py @@ -17,7 +17,9 @@ import array import mock +import six +from nova import exception from nova.keymgr import key from nova.tests.unit.volume.encryptors import test_base from nova.volume.encryptors import cryptsetup @@ -89,3 +91,14 @@ class CryptsetupEncryptorTestCase(test_base.VolumeEncryptorTestCase): run_as_root=True, check_exit_code=True), ]) self.assertEqual(1, mock_execute.call_count) + + def test_init_volume_encryption_not_supported(self): + # Tests that creating a CryptsetupEncryptor fails if there is no + # device_path key. + type = 'unencryptable' + data = dict(volume_id='a194699b-aa07-4433-a945-a5d23802043e') + connection_info = dict(driver_volume_type=type, data=data) + exc = self.assertRaises(exception.VolumeEncryptionNotSupported, + cryptsetup.CryptsetupEncryptor, + connection_info) + self.assertIn(type, six.text_type(exc)) diff --git a/nova/volume/encryptors/cryptsetup.py b/nova/volume/encryptors/cryptsetup.py index a4343a1cbfaa..3b5bcadd5a6c 100644 --- a/nova/volume/encryptors/cryptsetup.py +++ b/nova/volume/encryptors/cryptsetup.py @@ -18,6 +18,7 @@ import os from oslo_log import log as logging +from nova import exception from nova import utils from nova.volume.encryptors import base @@ -34,6 +35,15 @@ class CryptsetupEncryptor(base.VolumeEncryptor): def __init__(self, connection_info, **kwargs): super(CryptsetupEncryptor, self).__init__(connection_info, **kwargs) + # Fail if no device_path was set when connecting the volume, e.g. in + # the case of libvirt network volume drivers. + data = connection_info['data'] + if not data.get('device_path'): + volume_id = data.get('volume_id') or connection_info.get('serial') + raise exception.VolumeEncryptionNotSupported( + volume_id=volume_id, + volume_type=connection_info['driver_volume_type']) + # the device's path as given to libvirt -- e.g., /dev/disk/by-path/... self.symlink_path = connection_info['data']['device_path']