RP list: member_of and resources parameters (v1.3, v1.4)

Change-Id: I380ac35d72ee45cd064805bdb4bac4977d436831
Partially-Implements: blueprint placement-osc-plugin-rocky
This commit is contained in:
Andrey Volkov 2017-10-11 10:41:44 +03:00 committed by Matt Riedemann
parent 006f1eb6d0
commit 844414861a
5 changed files with 111 additions and 5 deletions

View File

@ -24,7 +24,9 @@ API_VERSION_OPTION = 'os_placement_api_version'
SUPPORTED_VERSIONS = [
'1.0',
'1.1',
'1.2'
'1.2',
'1.3',
'1.4'
]
API_VERSIONS = {v: 'osc_placement.http.SessionClient'
for v in SUPPORTED_VERSIONS}

View File

@ -14,6 +14,7 @@ from osc_lib.command import command
from osc_lib import utils
from osc_placement.resources import common
from osc_placement import version
BASE_URL = '/resource_providers'
@ -53,7 +54,7 @@ class CreateResourceProvider(command.ShowOne):
return FIELDS, utils.get_dict_properties(resource, FIELDS)
class ListResourceProvider(command.Lister):
class ListResourceProvider(command.Lister, version.CheckerMixin):
"""List resource providers"""
def get_parser(self, prog_name):
@ -69,6 +70,30 @@ class ListResourceProvider(command.Lister):
metavar='<name>',
help='Name of the resource provider'
)
parser.add_argument(
'--aggregate-uuid',
default=[],
action='append',
metavar='<aggregate_uuid>',
help='UUID of the resource provider aggregate of which the '
'listed resource providers are a member. The returned '
'resource providers must be associated with at least one of '
'the aggregates identified by uuid. '
'May be repeated.\n\n'
'This param requires at least '
'``--os-placement-api-version 1.3``.'
)
parser.add_argument(
'--resource',
metavar='<resource_class>=<value>',
default=[],
action='append',
help='A resource class value pair indicating an '
'amount of resource of a specified class that a provider '
'must have the capacity to serve. May be repeated.\n\n'
'This param requires at least '
'``--os-placement-api-version 1.4``.'
)
return parser
@ -76,10 +101,18 @@ class ListResourceProvider(command.Lister):
http = self.app.client_manager.placement
filters = {}
if 'name' in parsed_args and parsed_args.name:
if parsed_args.name:
filters['name'] = parsed_args.name
if 'uuid' in parsed_args and parsed_args.uuid:
if parsed_args.uuid:
filters['uuid'] = parsed_args.uuid
if parsed_args.aggregate_uuid:
self.check_version(version.ge('1.3'))
filters['member_of'] = 'in:' + ','.join(parsed_args.aggregate_uuid)
if parsed_args.resource:
self.check_version(version.ge('1.4'))
filters['resources'] = ','.join(
resource.replace('=', ':')
for resource in parsed_args.resource)
url = common.url_with_filters(BASE_URL, filters)
resources = http.request('GET', url).json()['resource_providers']

View File

@ -91,12 +91,18 @@ class BaseTestCase(base.BaseTestCase):
return self.openstack(cmd, use_json=True)
def resource_provider_list(self, uuid=None, name=None):
def resource_provider_list(self, uuid=None, name=None,
aggregate_uuids=None, resources=None):
to_exec = 'resource provider list'
if uuid:
to_exec += ' --uuid ' + uuid
if name:
to_exec += ' --name ' + name
if aggregate_uuids:
to_exec += ' ' + ' '.join(
'--aggregate-uuid %s' % a for a in aggregate_uuids)
if resources:
to_exec += ' ' + ' '.join('--resource %s' % r for r in resources)
return self.openstack(to_exec, use_json=True)

View File

@ -142,3 +142,52 @@ class TestResourceProvider(base.BaseTestCase):
by_uuid = self.resource_provider_list(uuid=str(uuid.uuid4()))
self.assertEqual([], by_uuid)
def test_fail_if_incorrect_options(self):
# aggregate_uuids param is available starting 1.3
self.assertCommandFailed(
'Operation or argument is not supported',
self.resource_provider_list, aggregate_uuids=['1'])
# resource param is available starting 1.4
self.assertCommandFailed('Operation or argument is not supported',
self.resource_provider_list, resources=['1'])
class TestResourceProvider14(base.BaseTestCase):
VERSION = '1.4'
def test_fail_if_incorrect_aggregate_uuid(self):
# aggregate_uuid requires the uuid like format
self.assertCommandFailed(
'Invalid uuid value', self.resource_provider_list,
aggregate_uuids=['fake_uuid'])
def test_return_empty_list_for_nonexistent_aggregate(self):
self.resource_provider_create()
agg = str(uuid.uuid4())
self.assertEqual([], self.resource_provider_list(
aggregate_uuids=[agg]))
def test_return_properly_for_aggregate_uuid_request(self):
self.resource_provider_create()
rp2 = self.resource_provider_create()
agg = str(uuid.uuid4())
self.resource_provider_aggregate_set(rp2['uuid'], agg)
rps = self.resource_provider_list(
aggregate_uuids=[agg, str(uuid.uuid4())])
self.assertEqual(1, len(rps))
self.assertEqual(rp2['uuid'], rps[0]['uuid'])
def test_return_empty_list_if_no_resource(self):
rp = self.resource_provider_create()
self.assertEqual([], self.resource_provider_list(
resources=['MEMORY_MB=256'], uuid=rp['uuid']))
def test_return_properly_for_resource_request(self):
rp1 = self.resource_provider_create()
rp2 = self.resource_provider_create()
self.resource_inventory_set(rp1['uuid'], 'PCI_DEVICE=8')
self.resource_inventory_set(rp2['uuid'], 'PCI_DEVICE=16')
rps = self.resource_provider_list(resources=['PCI_DEVICE=16'])
self.assertEqual(1, len(rps))
self.assertEqual(rp2['uuid'], rps[0]['uuid'])

View File

@ -0,0 +1,16 @@
---
features:
- |
The ``openstack resource provider list`` command now supports microversion
`1.3`_ and `1.4`_. Specifically two new options are added to the command:
* ``--aggregate-uuid``: List resource providers which are members of at
least one of the specified resource provider aggregates.
* ``--resource``: List resource providers which have the capacity to serve
allocation requests for the given amount of specified resource class.
See the `command documentation`__ for more details.
.. _1.3: https://docs.openstack.org/nova/latest/user/placement.html#member-of-query-parameter
.. _1.4: https://docs.openstack.org/nova/latest/user/placement.html#filter-resource-providers-by-requested-resource-capacity-maximum-in-ocata
.. __: https://docs.openstack.org/osc-placement/latest/cli/index.html#resource-provider-list