diff options
author | 2018-03-07 13:01:37 -0700 | |
---|---|---|
committer | 2018-03-08 14:02:05 -0700 | |
commit | f77540b440d3e5224eb1648339dc8c945f29bbe2 (patch) | |
tree | 84856cebdfb36f9c758d43bb127d1b91b88cc7d6 /snaps/openstack/utils | |
parent | e4563aec1eb8f98e5e42fe513918432eddadcd37 (diff) |
Ensure the project for volumes are handled properly.
Although this patch has added the project_name member to
VolumeConfig, it does not work properly due to a cinder bug
https://bugs.launchpad.net/cinder/+bug/1641982. However, the
code will now allow for volumes with the same name to be
created on the same pod just as long as they do not exist
within the same project/tenant.
JIRA: SNAPS-270
Change-Id: Ia6f98e9b66793a69c0205d2d8e38bb3d03f3333e
Signed-off-by: spisarski <s.pisarski@cablelabs.com>
Diffstat (limited to 'snaps/openstack/utils')
-rw-r--r-- | snaps/openstack/utils/cinder_utils.py | 95 | ||||
-rw-r--r-- | snaps/openstack/utils/tests/cinder_utils_tests.py | 17 | ||||
-rw-r--r-- | snaps/openstack/utils/tests/settings_utils_tests.py | 5 |
3 files changed, 84 insertions, 33 deletions
diff --git a/snaps/openstack/utils/cinder_utils.py b/snaps/openstack/utils/cinder_utils.py index c50a166..246245e 100644 --- a/snaps/openstack/utils/cinder_utils.py +++ b/snaps/openstack/utils/cinder_utils.py @@ -43,27 +43,40 @@ def cinder_client(os_creds): region_name=os_creds.region_name) -def get_volume(cinder, volume_name=None, volume_settings=None): +def get_volume(cinder, keystone=None, volume_name=None, volume_settings=None, + project_name=None): """ Returns an OpenStack volume object for a given name :param cinder: the Cinder client + :param keystone: the Keystone client (required if project_name or + volume_settings.project_name is not None :param volume_name: the volume name to lookup :param volume_settings: the volume settings used for lookups + :param project_name: the name of the project associated with the volume :return: the volume object or None """ if volume_settings: volume_name = volume_settings.name volumes = cinder.volumes.list() - for volume in volumes: - if volume.name == volume_name: - return Volume( - name=volume.name, volume_id=volume.id, - description=volume.description, size=volume.size, - vol_type=volume.volume_type, - availability_zone=volume.availability_zone, - multi_attach=volume.multiattach, - attachments=volume.attachments) + for os_volume in volumes: + if os_volume.name == volume_name: + project_id = None + if hasattr(os_volume, 'os-vol-tenant-attr:tenant_id'): + project_id = getattr( + os_volume, 'os-vol-tenant-attr:tenant_id') + + if volume_settings and volume_settings.project_name: + project_name = volume_settings.project_name + + if project_name: + project = keystone_utils.get_project_by_id( + keystone, project_id) + + if project and project.name == project_name: + return __map_os_volume_to_domain(os_volume) + else: + return __map_os_volume_to_domain(os_volume) def __get_os_volume_by_id(cinder, volume_id): @@ -83,12 +96,29 @@ def get_volume_by_id(cinder, volume_id): :param volume_id: the volume ID to lookup :return: the SNAPS-OO Domain Volume object or None """ - volume = __get_os_volume_by_id(cinder, volume_id) + os_volume = __get_os_volume_by_id(cinder, volume_id) + return __map_os_volume_to_domain(os_volume) + + +def __map_os_volume_to_domain(os_volume): + """ + Returns a SNAPS-OO domain Volume object that is created by an OpenStack + Volume object + :param os_volume: the OpenStack volume object + :return: Volume domain object + """ + project_id = None + if hasattr(os_volume, 'os-vol-tenant-attr:tenant_id'): + project_id = getattr( + os_volume, 'os-vol-tenant-attr:tenant_id') + return Volume( - name=volume.name, volume_id=volume.id, description=volume.description, - size=volume.size, vol_type=volume.volume_type, - availability_zone=volume.availability_zone, - multi_attach=volume.multiattach, attachments=volume.attachments) + name=os_volume.name, volume_id=os_volume.id, + project_id=project_id, description=os_volume.description, + size=os_volume.size, vol_type=os_volume.volume_type, + availability_zone=os_volume.availability_zone, + multi_attach=os_volume.multiattach, + attachments=os_volume.attachments) def get_volume_status(cinder, volume): @@ -102,27 +132,36 @@ def get_volume_status(cinder, volume): return os_volume.status -def create_volume(cinder, volume_settings): +def create_volume(cinder, keystone, volume_settings): """ Creates and returns OpenStack volume object with an external URL :param cinder: the cinder client + :param keystone: the keystone client :param volume_settings: the volume settings object :return: the OpenStack volume object :raise Exception if using a file and it cannot be found """ - volume = cinder.volumes.create( - name=volume_settings.name, description=volume_settings.description, - size=volume_settings.size, imageRef=volume_settings.image_name, + project_id = None + if volume_settings.project_name: + project = keystone_utils.get_project( + keystone, project_name=volume_settings.project_name) + if project: + project_id = project.id + else: + raise KeystoneUtilsException( + 'Project cannot be found with name - ' + + volume_settings.project_name) + os_volume = cinder.volumes.create( + name=volume_settings.name, + project_id=project_id, + description=volume_settings.description, + size=volume_settings.size, + imageRef=volume_settings.image_name, volume_type=volume_settings.type_name, availability_zone=volume_settings.availability_zone, multiattach=volume_settings.multi_attach) - return Volume( - name=volume.name, volume_id=volume.id, - description=volume.description, - size=volume.size, vol_type=volume.volume_type, - availability_zone=volume.availability_zone, - multi_attach=volume.multiattach, attachments=volume.attachments) + return __map_os_volume_to_domain(os_volume) def delete_volume(cinder, volume): @@ -367,3 +406,9 @@ def delete_qos(cinder, qos): """ logger.info('Deleting QoS named - %s', qos.name) cinder.qos_specs.delete(qos.id) + + +class KeystoneUtilsException(Exception): + """ + Exception when calls to the Keystone client cannot be served properly + """ diff --git a/snaps/openstack/utils/tests/cinder_utils_tests.py b/snaps/openstack/utils/tests/cinder_utils_tests.py index b624b09..3004c0f 100644 --- a/snaps/openstack/utils/tests/cinder_utils_tests.py +++ b/snaps/openstack/utils/tests/cinder_utils_tests.py @@ -26,7 +26,7 @@ from snaps.openstack import create_volume from snaps.openstack.create_qos import Consumer from snaps.openstack.tests import validation_utils from snaps.openstack.tests.os_source_file_test import OSComponentTestCase -from snaps.openstack.utils import cinder_utils +from snaps.openstack.utils import cinder_utils, keystone_utils __author__ = 'spisarski' @@ -75,6 +75,7 @@ class CinderUtilsVolumeTests(OSComponentTestCase): self.volume_name = self.__class__.__name__ + '-' + str(guid) self.volume = None self.cinder = cinder_utils.cinder_client(self.os_creds) + self.keystone = keystone_utils.keystone_client(self.os_creds) def tearDown(self): """ @@ -94,14 +95,15 @@ class CinderUtilsVolumeTests(OSComponentTestCase): """ volume_settings = VolumeConfig(name=self.volume_name) self.volume = cinder_utils.create_volume( - self.cinder, volume_settings) + self.cinder, self.keystone, volume_settings) self.assertIsNotNone(self.volume) self.assertEqual(self.volume_name, self.volume.name) self.assertTrue(volume_active(self.cinder, self.volume)) volume = cinder_utils.get_volume( - self.cinder, volume_settings=volume_settings) + self.cinder, self.keystone, volume_settings=volume_settings, + project_name=self.os_creds.project_name) self.assertIsNotNone(volume) validation_utils.objects_equivalent(self.volume, volume) @@ -111,21 +113,24 @@ class CinderUtilsVolumeTests(OSComponentTestCase): """ volume_settings = VolumeConfig(name=self.volume_name) self.volume = cinder_utils.create_volume( - self.cinder, volume_settings) + self.cinder, self.keystone, volume_settings) self.assertIsNotNone(self.volume) self.assertEqual(self.volume_name, self.volume.name) self.assertTrue(volume_active(self.cinder, self.volume)) volume = cinder_utils.get_volume( - self.cinder, volume_settings=volume_settings) + self.cinder, self.keystone, volume_settings=volume_settings, + project_name=self.os_creds.project_name) self.assertIsNotNone(volume) validation_utils.objects_equivalent(self.volume, volume) cinder_utils.delete_volume(self.cinder, self.volume) self.assertTrue(volume_deleted(self.cinder, self.volume)) self.assertIsNone( - cinder_utils.get_volume(self.cinder, volume_settings)) + cinder_utils.get_volume( + self.cinder, self.keystone, volume_settings, + project_name=self.os_creds.project_name)) def volume_active(cinder, volume): diff --git a/snaps/openstack/utils/tests/settings_utils_tests.py b/snaps/openstack/utils/tests/settings_utils_tests.py index 7287f44..7dc59b5 100644 --- a/snaps/openstack/utils/tests/settings_utils_tests.py +++ b/snaps/openstack/utils/tests/settings_utils_tests.py @@ -358,8 +358,9 @@ class SettingsUtilsUnitTests(unittest.TestCase): def test_vol_settings_from_vol(self): volume = Volume( - name='vol-name', volume_id='vol-id', description='desc', size=99, - vol_type='vol-type', availability_zone='zone1', multi_attach=True) + name='vol-name', volume_id='vol-id', project_id='proj-id', + description='desc', size=99, vol_type='vol-type', + availability_zone='zone1', multi_attach=True) settings = settings_utils.create_volume_config(volume) self.assertEqual(volume.name, settings.name) self.assertEqual(volume.description, settings.description) |