Add support for microversion 1.38 consumer types

Story: 2005473
Task: 42878

Depends-On: https://review.opendev.org/c/openstack/placement/+/679486

Change-Id: I1b7d7095e62dc80191ff3e199959fb4d7df6f68e
This commit is contained in:
melanie witt 2021-07-23 20:11:31 +00:00
parent b0a74d094d
commit 5e38a59317
4 changed files with 115 additions and 14 deletions

View File

@ -62,6 +62,11 @@ class SetAllocation(command.Lister, version.CheckerMixin):
Starting with ``--os-placement-api-version 1.28`` a consumer generation is
used which facilitates safe concurrent modification of an allocation.
Starting with ``--os-placement-api-version 1.38`` it is required to specify
``--consumer-type`` to set allocations. It is helpful to provide a
``--consumer-type`` when setting allocations so that resource usages can be
filtered on consumer types.
"""
def get_parser(self, prog_name):
@ -97,6 +102,14 @@ class SetAllocation(command.Lister, version.CheckerMixin):
'``--os-placement-api-version 1.8``.',
required=self.compare_version(version.ge('1.8'))
)
parser.add_argument(
'--consumer-type',
metavar='consumer_type',
help='The type of the consumer. '
'This option is required starting from '
'``--os-placement-api-version 1.38``.',
required=self.compare_version(version.ge('1.38'))
)
return parser
def take_action(self, parsed_args):
@ -136,18 +149,28 @@ class SetAllocation(command.Lister, version.CheckerMixin):
self.log.warning('--project-id and --user-id options do not '
'affect allocation for '
'--os-placement-api-version less than 1.8')
if self.compare_version(version.ge('1.38')):
payload['consumer_type'] = parsed_args.consumer_type
elif parsed_args.consumer_type:
self.log.warning('--consumer-type option does not affect '
'allocation for --os-placement-api-version less '
'than 1.38')
http.request('PUT', url, json=payload)
resp = http.request('GET', url).json()
per_provider = resp['allocations'].items()
props = {}
fields = ('resource_provider', 'generation', 'resources')
allocs = [dict(resource_provider=k, **v) for k, v in per_provider]
if self.compare_version(version.ge('1.12')):
fields += ('project_id', 'user_id')
[alloc.update(project_id=resp['project_id'],
user_id=resp['user_id'])
for alloc in allocs]
props['project_id'] = resp['project_id']
props['user_id'] = resp['user_id']
if self.compare_version(version.ge('1.38')):
fields += ('consumer_type',)
props['consumer_type'] = resp['consumer_type']
allocs = [dict(resource_provider=k, **props, **v)
for k, v in per_provider]
rows = (utils.get_dict_properties(a, fields) for a in allocs)
return fields, rows
@ -262,11 +285,16 @@ class UnsetAllocation(command.Lister, version.CheckerMixin):
resp = http.request('GET', url).json()
per_provider = resp['allocations'].items()
props = {}
fields = ('resource_provider', 'generation', 'resources',
'project_id', 'user_id')
if self.compare_version(version.ge('1.38')):
fields += ('consumer_type',)
props['consumer_type'] = resp['consumer_type']
allocs = [dict(project_id=resp['project_id'], user_id=resp['user_id'],
resource_provider=k, **v) for k, v in per_provider]
resource_provider=k, **props, **v)
for k, v in per_provider]
rows = (utils.get_dict_properties(a, fields) for a in allocs)
return fields, rows
@ -277,6 +305,9 @@ class ShowAllocation(command.Lister, version.CheckerMixin):
Starting with ``--os-placement-api-version 1.12`` the API response contains
the ``project_id`` and ``user_id`` of allocations which also appears in the
CLI output.
Starting with ``--os-placement-api-version 1.38`` the API response contains
the ``consumer_type`` of consumer which also appears in the CLI output.
"""
def get_parser(self, prog_name):
@ -296,18 +327,19 @@ class ShowAllocation(command.Lister, version.CheckerMixin):
url = BASE_URL + '/' + parsed_args.uuid
resp = http.request('GET', url).json()
per_provider = resp['allocations'].items()
if self.compare_version(version.ge('1.12')):
allocs = [dict(
resource_provider=k,
project_id=resp['project_id'],
user_id=resp['user_id'],
**v) for k, v in per_provider]
else:
allocs = [dict(resource_provider=k, **v) for k, v in per_provider]
props = {}
fields = ('resource_provider', 'generation', 'resources')
if self.compare_version(version.ge('1.12')):
fields += ('project_id', 'user_id')
props['project_id'] = resp['project_id']
props['user_id'] = resp['user_id']
if self.compare_version(version.ge('1.38')):
fields += ('consumer_type',)
props['consumer_type'] = resp['consumer_type']
allocs = [dict(resource_provider=k, **props, **v)
for k, v in per_provider]
rows = (utils.get_dict_properties(a, fields) for a in allocs)
return fields, rows

View File

@ -236,7 +236,8 @@ class BaseTestCase(base.BaseTestCase):
def resource_allocation_set(self, consumer_uuid, allocations,
project_id=None, user_id=None,
use_json=True, may_print_to_stderr=False):
consumer_type=None, use_json=True,
may_print_to_stderr=False):
cmd = 'resource provider allocation set {allocs} {uuid}'.format(
uuid=consumer_uuid,
allocs=' '.join('--allocation {}'.format(a) for a in allocations)
@ -245,6 +246,8 @@ class BaseTestCase(base.BaseTestCase):
cmd += ' --project-id %s' % project_id
if user_id:
cmd += ' --user-id %s' % user_id
if consumer_type:
cmd += ' --consumer-type %s' % consumer_type
result = self.openstack(
cmd, use_json=use_json, may_print_to_stderr=may_print_to_stderr)

View File

@ -67,6 +67,23 @@ class TestAllocation(base.BaseTestCase):
'--project-id and --user-id options do not affect allocation for '
'--os-placement-api-version less than 1.8', warning)
# Test that specifying --consumer-type before microversion 1.38 does
# not result in an error but display a warning.
output, warning = self.resource_allocation_set(
consumer_uuid,
['rp={},VCPU=2'.format(self.rp1['uuid']),
'rp={},MEMORY_MB=512'.format(self.rp1['uuid'])],
consumer_type='fake-type', may_print_to_stderr=True)
expected = [
{'resource_provider': self.rp1['uuid'],
'generation': 4,
'resources': {'VCPU': 2, 'MEMORY_MB': 512}}
]
self.assertEqual(expected, output)
self.assertIn(
'--consumer-type option does not affect allocation for '
'--os-placement-api-version less than 1.38', warning)
def test_allocation_create_empty(self):
consumer_uuid = str(uuid.uuid4())
@ -208,6 +225,54 @@ class TestAllocation128(TestAllocation112):
self.assertEqual(expected, updated_alloc)
class TestAllocation138(TestAllocation128):
"""Tests allocation set command with --os-placement-api-version 1.38.
The 1.38 microversion adds the consumer_type parameter to the
GET and PUT /allocations/{consumer_id} APIs
"""
VERSION = '1.38'
def test_allocation_update(self):
consumer_uuid = str(uuid.uuid4())
project_uuid = str(uuid.uuid4())
user_uuid = str(uuid.uuid4())
# First create the initial set of allocations using rp1.
created_alloc = self.resource_allocation_set(
consumer_uuid,
['rp={},VCPU=2'.format(self.rp1['uuid']),
'rp={},MEMORY_MB=512'.format(self.rp1['uuid'])],
project_id=project_uuid, user_id=user_uuid,
consumer_type='INSTANCE'
)
retrieved_alloc = self.resource_allocation_show(consumer_uuid)
expected = [
{'resource_provider': self.rp1['uuid'],
'generation': 2,
'project_id': project_uuid,
'user_id': user_uuid,
'resources': {'VCPU': 2, 'MEMORY_MB': 512},
'consumer_type': 'INSTANCE'}
]
self.assertEqual(expected, created_alloc)
self.assertEqual(expected, retrieved_alloc)
# Now update the allocations which should use the consumer generation.
updated_alloc = self.resource_allocation_set(
consumer_uuid,
['rp={},VCPU=4'.format(self.rp1['uuid']),
'rp={},MEMORY_MB=1024'.format(self.rp1['uuid'])],
project_id=project_uuid, user_id=user_uuid,
consumer_type='MIGRATION'
)
expected[0].update({
'generation': expected[0]['generation'] + 1,
'resources': {'VCPU': 4, 'MEMORY_MB': 1024},
'consumer_type': 'MIGRATION'
})
self.assertEqual(expected, updated_alloc)
class TestAllocationUnsetOldVersion(base.BaseTestCase):
def test_invalid_version(self):

View File

@ -49,6 +49,7 @@ SUPPORTED_MICROVERSIONS = [
'1.28', # Added for provider allocation (un)set (Ussuri)
'1.29',
'1.37', # unused
'1.38', # Added for consumer types (Xena)
]
SUPPORTED_VERSIONS = SUPPORTED_MICROVERSIONS + NEGOTIATE_VERSIONS
# The max microversion lower than which are all supported by this client.