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
This commit is contained in:
parent
55c1c575d6
commit
b0c317ebdd
@ -380,7 +380,27 @@ class ShowFlavor(command.ShowOne):
|
|||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
compute_client = self.app.client_manager.compute
|
compute_client = self.app.client_manager.compute
|
||||||
resource_flavor = _find_flavor(compute_client, parsed_args.flavor)
|
resource_flavor = _find_flavor(compute_client, parsed_args.flavor)
|
||||||
|
|
||||||
|
access_projects = None
|
||||||
|
# get access projects list of this flavor
|
||||||
|
if not resource_flavor.is_public:
|
||||||
|
try:
|
||||||
|
flavor_access = compute_client.flavor_access.list(
|
||||||
|
flavor=resource_flavor.id)
|
||||||
|
projects = [utils.get_field(access, 'tenant_id')
|
||||||
|
for access in flavor_access]
|
||||||
|
# TODO(Huanxuan Ao): This format case can be removed after
|
||||||
|
# patch https://review.openstack.org/#/c/330223/ merged.
|
||||||
|
access_projects = utils.format_list(projects)
|
||||||
|
except Exception as e:
|
||||||
|
msg = _("Failed to get access projects list "
|
||||||
|
"for flavor '%(flavor)s': %(e)s")
|
||||||
|
LOG.error(msg % {'flavor': parsed_args.flavor, 'e': e})
|
||||||
|
|
||||||
flavor = resource_flavor._info.copy()
|
flavor = resource_flavor._info.copy()
|
||||||
|
flavor.update({
|
||||||
|
'access_project_ids': access_projects
|
||||||
|
})
|
||||||
flavor.pop("links", None)
|
flavor.pop("links", None)
|
||||||
|
|
||||||
flavor['properties'] = utils.format_dict(resource_flavor.get_keys())
|
flavor['properties'] = utils.format_dict(resource_flavor.get_keys())
|
||||||
|
@ -787,6 +787,35 @@ class FakeFlavor(object):
|
|||||||
return mock.MagicMock(side_effect=flavors)
|
return mock.MagicMock(side_effect=flavors)
|
||||||
|
|
||||||
|
|
||||||
|
class FakeFlavorAccess(object):
|
||||||
|
"""Fake one or more flavor accesses."""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_one_flavor_access(attrs=None):
|
||||||
|
"""Create a fake flavor access.
|
||||||
|
|
||||||
|
:param Dictionary attrs:
|
||||||
|
A dictionary with all attributes
|
||||||
|
:return:
|
||||||
|
A FakeResource object, with flavor_id, tenat_id
|
||||||
|
"""
|
||||||
|
attrs = attrs or {}
|
||||||
|
|
||||||
|
# Set default attributes.
|
||||||
|
flavor_access_info = {
|
||||||
|
'flavor_id': 'flavor-id-' + uuid.uuid4().hex,
|
||||||
|
'tenant_id': 'tenant-id-' + uuid.uuid4().hex,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Overwrite default attributes.
|
||||||
|
flavor_access_info.update(attrs)
|
||||||
|
|
||||||
|
flavor_access = fakes.FakeResource(
|
||||||
|
info=copy.deepcopy(flavor_access_info), loaded=True)
|
||||||
|
|
||||||
|
return flavor_access
|
||||||
|
|
||||||
|
|
||||||
class FakeKeypair(object):
|
class FakeKeypair(object):
|
||||||
"""Fake one or more keypairs."""
|
"""Fake one or more keypairs."""
|
||||||
|
|
||||||
|
@ -619,11 +619,13 @@ class TestFlavorSet(TestFlavor):
|
|||||||
class TestFlavorShow(TestFlavor):
|
class TestFlavorShow(TestFlavor):
|
||||||
|
|
||||||
# Return value of self.flavors_mock.find().
|
# Return value of self.flavors_mock.find().
|
||||||
|
flavor_access = compute_fakes.FakeFlavorAccess.create_one_flavor_access()
|
||||||
flavor = compute_fakes.FakeFlavor.create_one_flavor()
|
flavor = compute_fakes.FakeFlavor.create_one_flavor()
|
||||||
|
|
||||||
columns = (
|
columns = (
|
||||||
'OS-FLV-DISABLED:disabled',
|
'OS-FLV-DISABLED:disabled',
|
||||||
'OS-FLV-EXT-DATA:ephemeral',
|
'OS-FLV-EXT-DATA:ephemeral',
|
||||||
|
'access_project_ids',
|
||||||
'disk',
|
'disk',
|
||||||
'id',
|
'id',
|
||||||
'name',
|
'name',
|
||||||
@ -638,6 +640,7 @@ class TestFlavorShow(TestFlavor):
|
|||||||
data = (
|
data = (
|
||||||
flavor.disabled,
|
flavor.disabled,
|
||||||
flavor.ephemeral,
|
flavor.ephemeral,
|
||||||
|
None,
|
||||||
flavor.disk,
|
flavor.disk,
|
||||||
flavor.id,
|
flavor.id,
|
||||||
flavor.name,
|
flavor.name,
|
||||||
@ -655,6 +658,7 @@ class TestFlavorShow(TestFlavor):
|
|||||||
# Return value of _find_resource()
|
# Return value of _find_resource()
|
||||||
self.flavors_mock.find.return_value = self.flavor
|
self.flavors_mock.find.return_value = self.flavor
|
||||||
self.flavors_mock.get.side_effect = exceptions.NotFound(None)
|
self.flavors_mock.get.side_effect = exceptions.NotFound(None)
|
||||||
|
self.flavor_access_mock.list.return_value = [self.flavor_access]
|
||||||
self.cmd = flavor.ShowFlavor(self.app, None)
|
self.cmd = flavor.ShowFlavor(self.app, None)
|
||||||
|
|
||||||
def test_show_no_options(self):
|
def test_show_no_options(self):
|
||||||
@ -665,7 +669,7 @@ class TestFlavorShow(TestFlavor):
|
|||||||
self.assertRaises(tests_utils.ParserException, self.check_parser,
|
self.assertRaises(tests_utils.ParserException, self.check_parser,
|
||||||
self.cmd, arglist, verifylist)
|
self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
def test_flavor_show(self):
|
def test_public_flavor_show(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
self.flavor.name,
|
self.flavor.name,
|
||||||
]
|
]
|
||||||
@ -680,6 +684,45 @@ class TestFlavorShow(TestFlavor):
|
|||||||
self.assertEqual(self.columns, columns)
|
self.assertEqual(self.columns, columns)
|
||||||
self.assertEqual(self.data, data)
|
self.assertEqual(self.data, data)
|
||||||
|
|
||||||
|
def test_private_flavor_show(self):
|
||||||
|
private_flavor = compute_fakes.FakeFlavor.create_one_flavor(
|
||||||
|
attrs={
|
||||||
|
'os-flavor-access:is_public': False,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.flavors_mock.find.return_value = private_flavor
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
private_flavor.name,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('flavor', private_flavor.name),
|
||||||
|
]
|
||||||
|
|
||||||
|
data_with_project = (
|
||||||
|
private_flavor.disabled,
|
||||||
|
private_flavor.ephemeral,
|
||||||
|
self.flavor_access.tenant_id,
|
||||||
|
private_flavor.disk,
|
||||||
|
private_flavor.id,
|
||||||
|
private_flavor.name,
|
||||||
|
private_flavor.is_public,
|
||||||
|
utils.format_dict(private_flavor.get_keys()),
|
||||||
|
private_flavor.ram,
|
||||||
|
private_flavor.rxtx_factor,
|
||||||
|
private_flavor.swap,
|
||||||
|
private_flavor.vcpus,
|
||||||
|
)
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.flavor_access_mock.list.assert_called_with(
|
||||||
|
flavor=private_flavor.id)
|
||||||
|
self.assertEqual(self.columns, columns)
|
||||||
|
self.assertEqual(data_with_project, data)
|
||||||
|
|
||||||
|
|
||||||
class TestFlavorUnset(TestFlavor):
|
class TestFlavorUnset(TestFlavor):
|
||||||
|
|
||||||
|
5
releasenotes/notes/bug-1575461-3fed33e53795684a.yaml
Normal file
5
releasenotes/notes/bug-1575461-3fed33e53795684a.yaml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add support for showing flavor access list by using ``flavor show`` command.
|
||||||
|
[Bug `1575461 <https://bugs.launchpad.net/bugs/1575461>`_]
|
Loading…
Reference in New Issue
Block a user