Skip to content

Commit 5e8957e

Browse files
ranasheel2000kiwik
authored andcommitted
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
1 parent 55c1c57 commit 5e8957e

5 files changed

Lines changed: 132 additions & 2 deletions

File tree

doc/source/command-objects/volume-type.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ volume type show
145145

146146
Display volume type details
147147

148-
149148
.. program:: volume type show
150149
.. code:: bash
151150

openstackclient/tests/volume/v2/fakes.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,38 @@ def create_one_transfer(attrs=None):
7676
return transfer
7777

7878

79+
class FakeTypeAccess(object):
80+
"""Fake one or more volume type access."""
81+
82+
@staticmethod
83+
def create_one_type_access(attrs=None):
84+
"""Create a fake volume type access for project.
85+
86+
:param Dictionary attrs:
87+
A dictionary with all attributes
88+
:return:
89+
A FakeResource object, with Volume_type_ID and Project_ID.
90+
"""
91+
if attrs is None:
92+
attrs = {}
93+
94+
# Set default attributes.
95+
type_access_attrs = {
96+
'volume_type_id': 'volume-type-id-' + uuid.uuid4().hex,
97+
'project_id': 'project-id-' + uuid.uuid4().hex,
98+
}
99+
100+
# Overwrite default attributes.
101+
type_access_attrs.update(attrs)
102+
103+
type_access = fakes.FakeResource(
104+
None,
105+
type_access_attrs,
106+
loaded=True)
107+
108+
return type_access
109+
110+
79111
class FakeServiceClient(object):
80112

81113
def __init__(self, **kwargs):
@@ -666,6 +698,7 @@ def create_one_type(attrs=None, methods=None):
666698
"name": 'type-name-' + uuid.uuid4().hex,
667699
"description": 'type-description-' + uuid.uuid4().hex,
668700
"extra_specs": {"foo": "bar"},
701+
"is_public": True,
669702
}
670703

671704
# Overwrite default attributes.

openstackclient/tests/volume/v2/test_type.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#
1414

1515
import copy
16+
import mock
1617

1718
from osc_lib import exceptions
1819
from osc_lib import utils
@@ -46,6 +47,7 @@ class TestTypeCreate(TestType):
4647
columns = (
4748
'description',
4849
'id',
50+
'is_public',
4951
'name',
5052
)
5153

@@ -56,6 +58,7 @@ def setUp(self):
5658
self.data = (
5759
self.new_volume_type.description,
5860
self.new_volume_type.id,
61+
True,
5962
self.new_volume_type.name,
6063
)
6164

@@ -357,8 +360,10 @@ def test_type_set_project_access(self):
357360
class TestTypeShow(TestType):
358361

359362
columns = (
363+
'access_project_ids',
360364
'description',
361365
'id',
366+
'is_public',
362367
'name',
363368
'properties',
364369
)
@@ -368,8 +373,10 @@ def setUp(self):
368373

369374
self.volume_type = volume_fakes.FakeType.create_one_type()
370375
self.data = (
376+
None,
371377
self.volume_type.description,
372378
self.volume_type.id,
379+
True,
373380
self.volume_type.name,
374381
utils.format_dict(self.volume_type.extra_specs)
375382
)
@@ -394,6 +401,71 @@ def test_type_show(self):
394401
self.assertEqual(self.columns, columns)
395402
self.assertEqual(self.data, data)
396403

404+
def test_type_show_with_access(self):
405+
arglist = [
406+
self.volume_type.id
407+
]
408+
verifylist = [
409+
("volume_type", self.volume_type.id)
410+
]
411+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
412+
413+
private_type = volume_fakes.FakeType.create_one_type(
414+
attrs={'is_public': False})
415+
type_access_list = volume_fakes.FakeTypeAccess.create_one_type_access()
416+
with mock.patch.object(self.types_mock, 'get',
417+
return_value=private_type):
418+
with mock.patch.object(self.types_access_mock, 'list',
419+
return_value=[type_access_list]):
420+
columns, data = self.cmd.take_action(parsed_args)
421+
self.types_mock.get.assert_called_once_with(
422+
self.volume_type.id)
423+
self.types_access_mock.list.assert_called_once_with(
424+
private_type.id)
425+
426+
self.assertEqual(self.columns, columns)
427+
private_type_data = (
428+
utils.format_list([type_access_list.project_id]),
429+
private_type.description,
430+
private_type.id,
431+
private_type.is_public,
432+
private_type.name,
433+
utils.format_dict(private_type.extra_specs)
434+
)
435+
self.assertEqual(private_type_data, data)
436+
437+
def test_type_show_with_list_access_exec(self):
438+
arglist = [
439+
self.volume_type.id
440+
]
441+
verifylist = [
442+
("volume_type", self.volume_type.id)
443+
]
444+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
445+
446+
private_type = volume_fakes.FakeType.create_one_type(
447+
attrs={'is_public': False})
448+
with mock.patch.object(self.types_mock, 'get',
449+
return_value=private_type):
450+
with mock.patch.object(self.types_access_mock, 'list',
451+
side_effect=Exception()):
452+
columns, data = self.cmd.take_action(parsed_args)
453+
self.types_mock.get.assert_called_once_with(
454+
self.volume_type.id)
455+
self.types_access_mock.list.assert_called_once_with(
456+
private_type.id)
457+
458+
self.assertEqual(self.columns, columns)
459+
private_type_data = (
460+
None,
461+
private_type.description,
462+
private_type.id,
463+
private_type.is_public,
464+
private_type.name,
465+
utils.format_dict(private_type.extra_specs)
466+
)
467+
self.assertEqual(private_type_data, data)
468+
397469

398470
class TestTypeUnset(TestType):
399471

openstackclient/volume/v2/volume_type.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,24 @@ def take_action(self, parsed_args):
282282
volume_client = self.app.client_manager.volume
283283
volume_type = utils.find_resource(
284284
volume_client.volume_types, parsed_args.volume_type)
285-
properties = utils.format_dict(volume_type._info.pop('extra_specs'))
285+
properties = utils.format_dict(
286+
volume_type._info.pop('extra_specs', {}))
286287
volume_type._info.update({'properties': properties})
288+
access_project_ids = None
289+
if not volume_type.is_public:
290+
try:
291+
volume_type_access = volume_client.volume_type_access.list(
292+
volume_type.id)
293+
project_ids = [utils.get_field(item, 'project_id')
294+
for item in volume_type_access]
295+
# TODO(Rui Chen): This format list case can be removed after
296+
# patch https://review.openstack.org/#/c/330223/ merged.
297+
access_project_ids = utils.format_list(project_ids)
298+
except Exception as e:
299+
msg = _('Failed to get access project list for volume type '
300+
'%(type)s: %(e)s')
301+
LOG.error(msg % {'type': volume_type.id, 'e': e})
302+
volume_type._info.update({'access_project_ids': access_project_ids})
287303
return zip(*sorted(six.iteritems(volume_type._info)))
288304

289305

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
features:
3+
- |
4+
Show project access details for private volume type.
5+
6+
An user can list projects which have access to
7+
a specific private volume type by using
8+
``volume type show <volume-type>``
9+
10+
[Bug `1554891 <https://bugs.launchpad.net/python-openstackclient/+bug/1554891>`_]

0 commit comments

Comments
 (0)