Add support for 1.19 microversion
The 1.19 microversion of placement adds support for the generation parameter when setting aggregates on a resource provider. The value is an integer generation, available when listing or showing resource providers. If an earlier version is chosen, but a --generation arg provided, an error is reported. Similarly, if not generation is provided and the version is 1.19 or later, an error is reported. The new TestAggregate119 inherits from TestAggregate to repeat the general validation it does, overrides those methods which require a generation when using version 1.19, and adds two failure tests. One test in the super class is adjusted so that it works as desired in both classes and in both versions of Python (Python3 has different behavor of a *args before kw args). I considered changing the signature of base.resource_provider_aggregate_set but that would have meant changes is several places. Change-Id: I74157998dd19d8a8d2b68d12ed3726aac11eb013
This commit is contained in:
parent
53b32590ad
commit
206978486f
@ -11,6 +11,7 @@
|
||||
# under the License.
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import exceptions
|
||||
from osc_placement import version
|
||||
|
||||
|
||||
@ -18,7 +19,7 @@ BASE_URL = '/resource_providers/{uuid}/aggregates'
|
||||
FIELDS = ('uuid',)
|
||||
|
||||
|
||||
class SetAggregate(command.Lister):
|
||||
class SetAggregate(command.Lister, version.CheckerMixin):
|
||||
|
||||
"""Associate a list of aggregates with the resource provider.
|
||||
|
||||
@ -48,6 +49,17 @@ class SetAggregate(command.Lister):
|
||||
default=[]
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--generation',
|
||||
metavar='<resource_provider_generation>',
|
||||
type=int,
|
||||
help='The generation of resource provider. Must match the server-'
|
||||
'side generation of the resource provider or the operation '
|
||||
'will fail.\n\n'
|
||||
'This param requires at least '
|
||||
'``--os-placement-api-version 1.19``.'
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
@version.check(version.ge('1.1'))
|
||||
@ -55,7 +67,24 @@ class SetAggregate(command.Lister):
|
||||
http = self.app.client_manager.placement
|
||||
|
||||
url = BASE_URL.format(uuid=parsed_args.uuid)
|
||||
resp = http.request('PUT', url, json=parsed_args.aggregate).json()
|
||||
aggregate = parsed_args.aggregate
|
||||
generation = None
|
||||
if 'generation' in parsed_args and parsed_args.generation is not None:
|
||||
self.check_version(version.ge('1.19'))
|
||||
generation = parsed_args.generation
|
||||
|
||||
if self.compare_version(version.lt('1.19')):
|
||||
resp = http.request('PUT', url, json=aggregate).json()
|
||||
# Microversion 1.19 and beyond a generation argument is
|
||||
# required to write aggregates.
|
||||
elif generation is not None:
|
||||
data = {'aggregates': aggregate,
|
||||
'resource_provider_generation': generation}
|
||||
resp = http.request('PUT', url, json=data).json()
|
||||
else:
|
||||
raise exceptions.CommandError(
|
||||
'A generation must be specified.')
|
||||
|
||||
return FIELDS, [[r] for r in resp['aggregates']]
|
||||
|
||||
|
||||
|
@ -220,10 +220,14 @@ class BaseTestCase(base.BaseTestCase):
|
||||
return self.openstack('resource provider aggregate list ' + uuid,
|
||||
use_json=True)
|
||||
|
||||
def resource_provider_aggregate_set(self, uuid, *aggregates):
|
||||
def resource_provider_aggregate_set(self, uuid, *aggregates,
|
||||
**kwargs):
|
||||
generation = kwargs.get('generation')
|
||||
cmd = 'resource provider aggregate set %s ' % uuid
|
||||
cmd += ' '.join('--aggregate %s' % aggregate
|
||||
for aggregate in aggregates)
|
||||
if generation is not None:
|
||||
cmd += ' --generation %s' % generation
|
||||
return self.openstack(cmd, use_json=True)
|
||||
|
||||
def resource_class_list(self):
|
||||
|
@ -82,7 +82,98 @@ class TestAggregate(base.BaseTestCase):
|
||||
|
||||
def test_fail_if_incorrect_aggregate_uuid(self):
|
||||
rp = self.resource_provider_create()
|
||||
aggs = ['abc', 'efg']
|
||||
self.assertCommandFailed(
|
||||
"is not a 'uuid'",
|
||||
self.resource_provider_aggregate_set,
|
||||
rp['uuid'], 'abc', 'efg')
|
||||
rp['uuid'], *aggs)
|
||||
|
||||
# In version 1.1 a generation is not allowed.
|
||||
def test_fail_generation_arg_version_handling(self):
|
||||
rp = self.resource_provider_create()
|
||||
agg = str(uuid.uuid4())
|
||||
self.assertCommandFailed(
|
||||
"Operation or argument is not supported with version 1.1",
|
||||
self.resource_provider_aggregate_set,
|
||||
rp['uuid'], agg, generation=5)
|
||||
|
||||
|
||||
class TestAggregate119(TestAggregate):
|
||||
VERSION = '1.19'
|
||||
|
||||
def test_success_set_aggregate(self):
|
||||
rp = self.resource_provider_create()
|
||||
aggs = {str(uuid.uuid4()) for _ in range(2)}
|
||||
rows = self.resource_provider_aggregate_set(
|
||||
rp['uuid'], *aggs, generation=rp['generation'])
|
||||
|
||||
self.assertEqual(aggs, {r['uuid'] for r in rows})
|
||||
rows = self.resource_provider_aggregate_list(rp['uuid'])
|
||||
self.assertEqual(aggs, {r['uuid'] for r in rows})
|
||||
self.resource_provider_aggregate_set(
|
||||
rp['uuid'], *[], generation=rp['generation'] + 1)
|
||||
rows = self.resource_provider_aggregate_list(rp['uuid'])
|
||||
self.assertEqual([], rows)
|
||||
|
||||
def test_success_set_multiple_aggregates(self):
|
||||
# each rp is associated with two aggregates
|
||||
rps = [self.resource_provider_create() for _ in range(2)]
|
||||
aggs = {str(uuid.uuid4()) for _ in range(2)}
|
||||
for rp in rps:
|
||||
rows = self.resource_provider_aggregate_set(
|
||||
rp['uuid'], *aggs, generation=rp['generation'])
|
||||
self.assertEqual(aggs, {r['uuid'] for r in rows})
|
||||
# remove association for the first aggregate
|
||||
rows = self.resource_provider_aggregate_set(
|
||||
rps[0]['uuid'], *[], generation=rp['generation'] + 1)
|
||||
self.assertEqual([], rows)
|
||||
# second rp should be in aggregates
|
||||
rows = self.resource_provider_aggregate_list(rps[1]['uuid'])
|
||||
self.assertEqual(aggs, {r['uuid'] for r in rows})
|
||||
# cleanup
|
||||
rows = self.resource_provider_aggregate_set(
|
||||
rps[1]['uuid'], *[], generation=rp['generation'] + 1)
|
||||
self.assertEqual([], rows)
|
||||
|
||||
def test_success_set_large_number_aggregates(self):
|
||||
rp = self.resource_provider_create()
|
||||
aggs = {str(uuid.uuid4()) for _ in range(100)}
|
||||
rows = self.resource_provider_aggregate_set(
|
||||
rp['uuid'], *aggs, generation=rp['generation'])
|
||||
self.assertEqual(aggs, {r['uuid'] for r in rows})
|
||||
rows = self.resource_provider_aggregate_set(
|
||||
rp['uuid'], *[], generation=rp['generation'] + 1)
|
||||
self.assertEqual([], rows)
|
||||
|
||||
def test_fail_incorrect_generation(self):
|
||||
rp = self.resource_provider_create()
|
||||
agg = str(uuid.uuid4())
|
||||
self.assertCommandFailed(
|
||||
"Please update the generation and try again.",
|
||||
self.resource_provider_aggregate_set,
|
||||
rp['uuid'], agg, generation=99999)
|
||||
|
||||
def test_fail_generation_not_int(self):
|
||||
rp = self.resource_provider_create()
|
||||
agg = str(uuid.uuid4())
|
||||
self.assertCommandFailed(
|
||||
"invalid int value",
|
||||
self.resource_provider_aggregate_set,
|
||||
rp['uuid'], agg, generation='barney')
|
||||
|
||||
def test_fail_if_incorrect_aggregate_uuid(self):
|
||||
rp = self.resource_provider_create()
|
||||
aggs = ['abc', 'efg']
|
||||
self.assertCommandFailed(
|
||||
"is not a 'uuid'",
|
||||
self.resource_provider_aggregate_set,
|
||||
rp['uuid'], *aggs, generation=rp['generation'])
|
||||
|
||||
# In version 1.19 a generation is required.
|
||||
def test_fail_generation_arg_version_handling(self):
|
||||
rp = self.resource_provider_create()
|
||||
agg = str(uuid.uuid4())
|
||||
self.assertCommandFailed(
|
||||
"A generation must be specified.",
|
||||
self.resource_provider_aggregate_set,
|
||||
rp['uuid'], agg)
|
||||
|
@ -34,6 +34,7 @@ SUPPORTED_VERSIONS = [
|
||||
'1.16',
|
||||
'1.17',
|
||||
'1.18',
|
||||
'1.19',
|
||||
]
|
||||
|
||||
|
||||
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Support is added for the `1.19`_ placement API microversion by adding
|
||||
the ``--generation`` option to the
|
||||
``openstack resource provider aggregate set`` command.
|
||||
|
||||
.. _1.19: https://docs.openstack.org/placement/latest/placement-api-microversion-history.html#include-generation-and-conflict-detection-in-provider-aggregates-apis
|
Loading…
Reference in New Issue
Block a user