summaryrefslogtreecommitdiffstats
path: root/snaps/openstack/utils
diff options
context:
space:
mode:
authorspisarski <s.pisarski@cablelabs.com>2018-03-07 13:01:37 -0700
committerspisarski <s.pisarski@cablelabs.com>2018-03-08 14:02:05 -0700
commitf77540b440d3e5224eb1648339dc8c945f29bbe2 (patch)
tree84856cebdfb36f9c758d43bb127d1b91b88cc7d6 /snaps/openstack/utils
parente4563aec1eb8f98e5e42fe513918432eddadcd37 (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.py95
-rw-r--r--snaps/openstack/utils/tests/cinder_utils_tests.py17
-rw-r--r--snaps/openstack/utils/tests/settings_utils_tests.py5
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)