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
This commit is contained in:
Sheel Rana 2016-05-01 12:07:46 +05:30 committed by Rui Chen
parent 55c1c575d6
commit 5e8957ef7f
5 changed files with 132 additions and 2 deletions

View File

@ -145,7 +145,6 @@ volume type show
Display volume type details
.. program:: volume type show
.. code:: bash

View File

@ -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.

View File

@ -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):

View File

@ -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)))

View File

@ -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>`_]