Skip to content

Commit b0c317e

Browse files
author
Huanxuan Ao
committed
Add Support for showing flavor access list
Add a attribute "access_project_id" for flavor object to display the access project id list by using "flavor show" command. Change-Id: I7f0c152b816e0ca2e32e47f9b5c1aa7663d33b6d Closes-Bug:#1575461
1 parent 55c1c57 commit b0c317e

4 files changed

Lines changed: 98 additions & 1 deletion

File tree

openstackclient/compute/v2/flavor.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,27 @@ def get_parser(self, prog_name):
380380
def take_action(self, parsed_args):
381381
compute_client = self.app.client_manager.compute
382382
resource_flavor = _find_flavor(compute_client, parsed_args.flavor)
383+
384+
access_projects = None
385+
# get access projects list of this flavor
386+
if not resource_flavor.is_public:
387+
try:
388+
flavor_access = compute_client.flavor_access.list(
389+
flavor=resource_flavor.id)
390+
projects = [utils.get_field(access, 'tenant_id')
391+
for access in flavor_access]
392+
# TODO(Huanxuan Ao): This format case can be removed after
393+
# patch https://review.openstack.org/#/c/330223/ merged.
394+
access_projects = utils.format_list(projects)
395+
except Exception as e:
396+
msg = _("Failed to get access projects list "
397+
"for flavor '%(flavor)s': %(e)s")
398+
LOG.error(msg % {'flavor': parsed_args.flavor, 'e': e})
399+
383400
flavor = resource_flavor._info.copy()
401+
flavor.update({
402+
'access_project_ids': access_projects
403+
})
384404
flavor.pop("links", None)
385405

386406
flavor['properties'] = utils.format_dict(resource_flavor.get_keys())

openstackclient/tests/compute/v2/fakes.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,35 @@ def get_flavors(flavors=None, count=2):
787787
return mock.MagicMock(side_effect=flavors)
788788

789789

790+
class FakeFlavorAccess(object):
791+
"""Fake one or more flavor accesses."""
792+
793+
@staticmethod
794+
def create_one_flavor_access(attrs=None):
795+
"""Create a fake flavor access.
796+
797+
:param Dictionary attrs:
798+
A dictionary with all attributes
799+
:return:
800+
A FakeResource object, with flavor_id, tenat_id
801+
"""
802+
attrs = attrs or {}
803+
804+
# Set default attributes.
805+
flavor_access_info = {
806+
'flavor_id': 'flavor-id-' + uuid.uuid4().hex,
807+
'tenant_id': 'tenant-id-' + uuid.uuid4().hex,
808+
}
809+
810+
# Overwrite default attributes.
811+
flavor_access_info.update(attrs)
812+
813+
flavor_access = fakes.FakeResource(
814+
info=copy.deepcopy(flavor_access_info), loaded=True)
815+
816+
return flavor_access
817+
818+
790819
class FakeKeypair(object):
791820
"""Fake one or more keypairs."""
792821

openstackclient/tests/compute/v2/test_flavor.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -619,11 +619,13 @@ def test_flavor_set_nothing(self):
619619
class TestFlavorShow(TestFlavor):
620620

621621
# Return value of self.flavors_mock.find().
622+
flavor_access = compute_fakes.FakeFlavorAccess.create_one_flavor_access()
622623
flavor = compute_fakes.FakeFlavor.create_one_flavor()
623624

624625
columns = (
625626
'OS-FLV-DISABLED:disabled',
626627
'OS-FLV-EXT-DATA:ephemeral',
628+
'access_project_ids',
627629
'disk',
628630
'id',
629631
'name',
@@ -638,6 +640,7 @@ class TestFlavorShow(TestFlavor):
638640
data = (
639641
flavor.disabled,
640642
flavor.ephemeral,
643+
None,
641644
flavor.disk,
642645
flavor.id,
643646
flavor.name,
@@ -655,6 +658,7 @@ def setUp(self):
655658
# Return value of _find_resource()
656659
self.flavors_mock.find.return_value = self.flavor
657660
self.flavors_mock.get.side_effect = exceptions.NotFound(None)
661+
self.flavor_access_mock.list.return_value = [self.flavor_access]
658662
self.cmd = flavor.ShowFlavor(self.app, None)
659663

660664
def test_show_no_options(self):
@@ -665,7 +669,7 @@ def test_show_no_options(self):
665669
self.assertRaises(tests_utils.ParserException, self.check_parser,
666670
self.cmd, arglist, verifylist)
667671

668-
def test_flavor_show(self):
672+
def test_public_flavor_show(self):
669673
arglist = [
670674
self.flavor.name,
671675
]
@@ -680,6 +684,45 @@ def test_flavor_show(self):
680684
self.assertEqual(self.columns, columns)
681685
self.assertEqual(self.data, data)
682686

687+
def test_private_flavor_show(self):
688+
private_flavor = compute_fakes.FakeFlavor.create_one_flavor(
689+
attrs={
690+
'os-flavor-access:is_public': False,
691+
}
692+
)
693+
self.flavors_mock.find.return_value = private_flavor
694+
695+
arglist = [
696+
private_flavor.name,
697+
]
698+
verifylist = [
699+
('flavor', private_flavor.name),
700+
]
701+
702+
data_with_project = (
703+
private_flavor.disabled,
704+
private_flavor.ephemeral,
705+
self.flavor_access.tenant_id,
706+
private_flavor.disk,
707+
private_flavor.id,
708+
private_flavor.name,
709+
private_flavor.is_public,
710+
utils.format_dict(private_flavor.get_keys()),
711+
private_flavor.ram,
712+
private_flavor.rxtx_factor,
713+
private_flavor.swap,
714+
private_flavor.vcpus,
715+
)
716+
717+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
718+
719+
columns, data = self.cmd.take_action(parsed_args)
720+
721+
self.flavor_access_mock.list.assert_called_with(
722+
flavor=private_flavor.id)
723+
self.assertEqual(self.columns, columns)
724+
self.assertEqual(data_with_project, data)
725+
683726

684727
class TestFlavorUnset(TestFlavor):
685728

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
features:
3+
- |
4+
Add support for showing flavor access list by using ``flavor show`` command.
5+
[Bug `1575461 <https://bugs.launchpad.net/bugs/1575461>`_]

0 commit comments

Comments
 (0)