summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSheel Rana <ranasheel2000@gmail.com>2016-05-01 12:07:46 +0530
committerRui Chen <chenrui.momo@gmail.com>2016-07-20 16:54:58 +0800
commit5e8957ef7f4acea1ece06378c050021b64ea3f6f (patch)
treea739029aacfd736dacef67c0d434479b33b18360
parent55c1c575d63f4e9e6fc3f4dbb6c572e841b513d9 (diff)
downloadpython-openstackclient-5e8957ef7f4acea1ece06378c050021b64ea3f6f.tar.gz
Show project access for volume type
OSC does not support to show project access details for private volume types. This patch will provide support for showing project access details for private volume types. Closes-Bug:#1554891 Implements: bp cinder-command-support Change-Id: I218fb07a6e69033e9f8570748eee1df8df9d6fdc
-rw-r--r--doc/source/command-objects/volume-type.rst1
-rw-r--r--openstackclient/tests/volume/v2/fakes.py33
-rw-r--r--openstackclient/tests/volume/v2/test_type.py72
-rw-r--r--openstackclient/volume/v2/volume_type.py18
-rw-r--r--releasenotes/notes/list_volume_type_access-f7d9aa6159f757ea.yaml10
5 files changed, 132 insertions, 2 deletions
diff --git a/doc/source/command-objects/volume-type.rst b/doc/source/command-objects/volume-type.rst
index e2a277b0..ddc89335 100644
--- a/doc/source/command-objects/volume-type.rst
+++ b/doc/source/command-objects/volume-type.rst
@@ -145,7 +145,6 @@ volume type show
Display volume type details
-
.. program:: volume type show
.. code:: bash
diff --git a/openstackclient/tests/volume/v2/fakes.py b/openstackclient/tests/volume/v2/fakes.py
index 74e30a41..6809bebd 100644
--- a/openstackclient/tests/volume/v2/fakes.py
+++ b/openstackclient/tests/volume/v2/fakes.py
@@ -76,6 +76,38 @@ class FakeTransfer(object):
return transfer
+class FakeTypeAccess(object):
+ """Fake one or more volume type access."""
+
+ @staticmethod
+ def create_one_type_access(attrs=None):
+ """Create a fake volume type access for project.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes
+ :return:
+ A FakeResource object, with Volume_type_ID and Project_ID.
+ """
+ if attrs is None:
+ attrs = {}
+
+ # Set default attributes.
+ type_access_attrs = {
+ 'volume_type_id': 'volume-type-id-' + uuid.uuid4().hex,
+ 'project_id': 'project-id-' + uuid.uuid4().hex,
+ }
+
+ # Overwrite default attributes.
+ type_access_attrs.update(attrs)
+
+ type_access = fakes.FakeResource(
+ None,
+ type_access_attrs,
+ loaded=True)
+
+ return type_access
+
+
class FakeServiceClient(object):
def __init__(self, **kwargs):
@@ -666,6 +698,7 @@ class FakeType(object):
"name": 'type-name-' + uuid.uuid4().hex,
"description": 'type-description-' + uuid.uuid4().hex,
"extra_specs": {"foo": "bar"},
+ "is_public": True,
}
# Overwrite default attributes.
diff --git a/openstackclient/tests/volume/v2/test_type.py b/openstackclient/tests/volume/v2/test_type.py
index a7db2e49..e148bba4 100644
--- a/openstackclient/tests/volume/v2/test_type.py
+++ b/openstackclient/tests/volume/v2/test_type.py
@@ -13,6 +13,7 @@
#
import copy
+import mock
from osc_lib import exceptions
from osc_lib import utils
@@ -46,6 +47,7 @@ class TestTypeCreate(TestType):
columns = (
'description',
'id',
+ 'is_public',
'name',
)
@@ -56,6 +58,7 @@ class TestTypeCreate(TestType):
self.data = (
self.new_volume_type.description,
self.new_volume_type.id,
+ True,
self.new_volume_type.name,
)
@@ -357,8 +360,10 @@ class TestTypeSet(TestType):
class TestTypeShow(TestType):
columns = (
+ 'access_project_ids',
'description',
'id',
+ 'is_public',
'name',
'properties',
)
@@ -368,8 +373,10 @@ class TestTypeShow(TestType):
self.volume_type = volume_fakes.FakeType.create_one_type()
self.data = (
+ None,
self.volume_type.description,
self.volume_type.id,
+ True,
self.volume_type.name,
utils.format_dict(self.volume_type.extra_specs)
)
@@ -394,6 +401,71 @@ class TestTypeShow(TestType):
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, data)
+ def test_type_show_with_access(self):
+ arglist = [
+ self.volume_type.id
+ ]
+ verifylist = [
+ ("volume_type", self.volume_type.id)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ private_type = volume_fakes.FakeType.create_one_type(
+ attrs={'is_public': False})
+ type_access_list = volume_fakes.FakeTypeAccess.create_one_type_access()
+ with mock.patch.object(self.types_mock, 'get',
+ return_value=private_type):
+ with mock.patch.object(self.types_access_mock, 'list',
+ return_value=[type_access_list]):
+ columns, data = self.cmd.take_action(parsed_args)
+ self.types_mock.get.assert_called_once_with(
+ self.volume_type.id)
+ self.types_access_mock.list.assert_called_once_with(
+ private_type.id)
+
+ self.assertEqual(self.columns, columns)
+ private_type_data = (
+ utils.format_list([type_access_list.project_id]),
+ private_type.description,
+ private_type.id,
+ private_type.is_public,
+ private_type.name,
+ utils.format_dict(private_type.extra_specs)
+ )
+ self.assertEqual(private_type_data, data)
+
+ def test_type_show_with_list_access_exec(self):
+ arglist = [
+ self.volume_type.id
+ ]
+ verifylist = [
+ ("volume_type", self.volume_type.id)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ private_type = volume_fakes.FakeType.create_one_type(
+ attrs={'is_public': False})
+ with mock.patch.object(self.types_mock, 'get',
+ return_value=private_type):
+ with mock.patch.object(self.types_access_mock, 'list',
+ side_effect=Exception()):
+ columns, data = self.cmd.take_action(parsed_args)
+ self.types_mock.get.assert_called_once_with(
+ self.volume_type.id)
+ self.types_access_mock.list.assert_called_once_with(
+ private_type.id)
+
+ self.assertEqual(self.columns, columns)
+ private_type_data = (
+ None,
+ private_type.description,
+ private_type.id,
+ private_type.is_public,
+ private_type.name,
+ utils.format_dict(private_type.extra_specs)
+ )
+ self.assertEqual(private_type_data, data)
+
class TestTypeUnset(TestType):
diff --git a/openstackclient/volume/v2/volume_type.py b/openstackclient/volume/v2/volume_type.py
index ac11785c..62d619d0 100644
--- a/openstackclient/volume/v2/volume_type.py
+++ b/openstackclient/volume/v2/volume_type.py
@@ -282,8 +282,24 @@ class ShowVolumeType(command.ShowOne):
volume_client = self.app.client_manager.volume
volume_type = utils.find_resource(
volume_client.volume_types, parsed_args.volume_type)
- properties = utils.format_dict(volume_type._info.pop('extra_specs'))
+ properties = utils.format_dict(
+ volume_type._info.pop('extra_specs', {}))
volume_type._info.update({'properties': properties})
+ access_project_ids = None
+ if not volume_type.is_public:
+ try:
+ volume_type_access = volume_client.volume_type_access.list(
+ volume_type.id)
+ project_ids = [utils.get_field(item, 'project_id')
+ for item in volume_type_access]
+ # TODO(Rui Chen): This format list case can be removed after
+ # patch https://review.openstack.org/#/c/330223/ merged.
+ access_project_ids = utils.format_list(project_ids)
+ except Exception as e:
+ msg = _('Failed to get access project list for volume type '
+ '%(type)s: %(e)s')
+ LOG.error(msg % {'type': volume_type.id, 'e': e})
+ volume_type._info.update({'access_project_ids': access_project_ids})
return zip(*sorted(six.iteritems(volume_type._info)))
diff --git a/releasenotes/notes/list_volume_type_access-f7d9aa6159f757ea.yaml b/releasenotes/notes/list_volume_type_access-f7d9aa6159f757ea.yaml
new file mode 100644
index 00000000..aba3f75b
--- /dev/null
+++ b/releasenotes/notes/list_volume_type_access-f7d9aa6159f757ea.yaml
@@ -0,0 +1,10 @@
+---
+features:
+ - |
+ Show project access details for private volume type.
+
+ An user can list projects which have access to
+ a specific private volume type by using
+ ``volume type show <volume-type>``
+
+ [Bug `1554891 <https://bugs.launchpad.net/python-openstackclient/+bug/1554891>`_]