Merge "Add "--resource-class" to allocation unset"
This commit is contained in:
commit
869769e3bf
@ -155,8 +155,8 @@ class SetAllocation(command.Lister, version.CheckerMixin):
|
|||||||
class UnsetAllocation(command.Lister, version.CheckerMixin):
|
class UnsetAllocation(command.Lister, version.CheckerMixin):
|
||||||
"""Removes one or more sets of provider allocations for a consumer.
|
"""Removes one or more sets of provider allocations for a consumer.
|
||||||
|
|
||||||
Note that omitting the ``--provider`` option is equivalent to removing
|
Note that omitting both the ``--provider`` and the ``--resource-class``
|
||||||
all allocations for the given consumer.
|
option is equivalent to removing all allocations for the given consumer.
|
||||||
|
|
||||||
This command requires ``--os-placement-api-version 1.12`` or greater. Use
|
This command requires ``--os-placement-api-version 1.12`` or greater. Use
|
||||||
``openstack resource provider allocation set`` for older versions.
|
``openstack resource provider allocation set`` for older versions.
|
||||||
@ -168,7 +168,10 @@ class UnsetAllocation(command.Lister, version.CheckerMixin):
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'uuid',
|
'uuid',
|
||||||
metavar='<consumer_uuid>',
|
metavar='<consumer_uuid>',
|
||||||
help='UUID of the consumer'
|
help='UUID of the consumer. It is strongly recommended to use '
|
||||||
|
'``--os-placement-api-version 1.28`` or greater when using '
|
||||||
|
'this option to ensure the other allocation information is '
|
||||||
|
'retained. '
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--provider',
|
'--provider',
|
||||||
@ -180,22 +183,27 @@ class UnsetAllocation(command.Lister, version.CheckerMixin):
|
|||||||
'consumer has allocations on more than one provider, for '
|
'consumer has allocations on more than one provider, for '
|
||||||
'example after evacuating a server to another compute node '
|
'example after evacuating a server to another compute node '
|
||||||
'and you want to cleanup allocations on the source compute '
|
'and you want to cleanup allocations on the source compute '
|
||||||
'node resource provider in order to delete it. It is '
|
'node resource provider in order to delete it. Specify '
|
||||||
'strongly recommended to use '
|
'multiple times to remove allocations against multiple '
|
||||||
'``--os-placement-api-version 1.28`` or greater when using '
|
'resource providers. Omit this option to remove all '
|
||||||
'this option to ensure the other allocation information is '
|
'allocations for the consumer, or to remove all allocations'
|
||||||
'retained. Specify multiple times to remove allocations '
|
'of a specific resource class from all the resource provider '
|
||||||
'against multiple resource providers. Omit this option to '
|
'with the ``--resource_class`` option. '
|
||||||
'remove all allocations for the consumer.'
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--resource-class',
|
||||||
|
metavar='resource_class',
|
||||||
|
action='append',
|
||||||
|
default=[],
|
||||||
|
help='Name of a resource class from which to remove allocations '
|
||||||
|
'for the given consumer. This is useful when the consumer '
|
||||||
|
'has allocations on more than one resource class. '
|
||||||
|
'By default, this will remove allocations for the given '
|
||||||
|
'resource class from all the providers. If ``--provider`` '
|
||||||
|
'option is also specified, allocations to remove will be '
|
||||||
|
'limited to that resource class of the given resource '
|
||||||
|
'provider.'
|
||||||
)
|
)
|
||||||
# TODO(mriedem): Add a --resource-class option which can be used with
|
|
||||||
# or without --provider, e.g.:
|
|
||||||
# 1. allocation unset --provider P --resource-class VGPU = remove
|
|
||||||
# VGPU allocation from provider P for this consumer.
|
|
||||||
# 2. allocation unset --resource-class VGPU = remove VGPU allocations
|
|
||||||
# from all providers for this consumer.
|
|
||||||
# Make sure to update the note about omitting --provider in the
|
|
||||||
# command description above (due to example 2).
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
# NOTE(mriedem): We require >= 1.12 because PUT requires project_id/user_id
|
# NOTE(mriedem): We require >= 1.12 because PUT requires project_id/user_id
|
||||||
@ -210,19 +218,35 @@ class UnsetAllocation(command.Lister, version.CheckerMixin):
|
|||||||
|
|
||||||
# Get the current allocations.
|
# Get the current allocations.
|
||||||
payload = http.request('GET', url).json()
|
payload = http.request('GET', url).json()
|
||||||
|
allocations = payload['allocations']
|
||||||
|
|
||||||
if parsed_args.provider:
|
if parsed_args.resource_class:
|
||||||
allocations = payload['allocations']
|
# Remove the given resource class. Do not error out if the
|
||||||
# Remove the given provider(s) from the allocations if it exists.
|
# consumer does not have allocations against that resource
|
||||||
# Do not error out if the consumer does not have allocations
|
# class.
|
||||||
# against a provider in case we lost a race since the allocations
|
rp_uuids = set(allocations)
|
||||||
# are in the state the user wants them in anyway.
|
if parsed_args.provider:
|
||||||
for rp_uuid in parsed_args.provider:
|
# If providers are also specified, we limit to remove
|
||||||
allocations.pop(rp_uuid, None)
|
# allocations only from those providers
|
||||||
|
rp_uuids &= set(parsed_args.provider)
|
||||||
|
for rp_uuid in rp_uuids:
|
||||||
|
for rc in parsed_args.resource_class:
|
||||||
|
allocations[rp_uuid]['resources'].pop(rc, None)
|
||||||
|
if not allocations[rp_uuid]['resources']:
|
||||||
|
allocations.pop(rp_uuid, None)
|
||||||
else:
|
else:
|
||||||
# No --provider(s) specified so remove allocations from all
|
if parsed_args.provider:
|
||||||
# providers.
|
# Remove the given provider(s) from the allocations if it
|
||||||
allocations = {}
|
# exists. Do not error out if the consumer does not have
|
||||||
|
# allocations against a provider in case we lost a race since
|
||||||
|
# the allocations are in the state the user wants them in
|
||||||
|
# anyway.
|
||||||
|
for rp_uuid in parsed_args.provider:
|
||||||
|
allocations.pop(rp_uuid, None)
|
||||||
|
else:
|
||||||
|
# No --provider(s) specified so remove allocations from all
|
||||||
|
# providers.
|
||||||
|
allocations = {}
|
||||||
|
|
||||||
supports_consumer_generation = self.compare_version(version.ge('1.28'))
|
supports_consumer_generation = self.compare_version(version.ge('1.28'))
|
||||||
# 1.28+ allows PUTing an empty allocations dict as long as a
|
# 1.28+ allows PUTing an empty allocations dict as long as a
|
||||||
|
@ -260,19 +260,18 @@ class BaseTestCase(base.BaseTestCase):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
def resource_allocation_unset(self, consumer_uuid, provider=None,
|
def resource_allocation_unset(self, consumer_uuid, provider=None,
|
||||||
use_json=True):
|
resource_class=None, use_json=True):
|
||||||
|
cmd = 'resource provider allocation unset %s' % consumer_uuid
|
||||||
|
if resource_class:
|
||||||
|
cmd += ' ' + ' '.join(
|
||||||
|
'--resource-class %s' % rc for rc in resource_class)
|
||||||
if provider:
|
if provider:
|
||||||
# --provider can be specified multiple times so if we only get
|
# --provider can be specified multiple times so if we only get
|
||||||
# a single string value convert to a list.
|
# a single string value convert to a list.
|
||||||
if isinstance(provider, six.string_types):
|
if isinstance(provider, six.string_types):
|
||||||
provider = [provider]
|
provider = [provider]
|
||||||
cmd = 'resource provider allocation unset %s %s' % (
|
cmd += ' ' + ' '.join(
|
||||||
' '.join('--provider %s' %
|
'--provider %s' % rp_uuid for rp_uuid in provider)
|
||||||
rp_uuid for rp_uuid in provider),
|
|
||||||
consumer_uuid
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
cmd = 'resource provider allocation unset %s' % consumer_uuid
|
|
||||||
result = self.openstack(cmd, use_json=use_json)
|
result = self.openstack(cmd, use_json=use_json)
|
||||||
|
|
||||||
def cleanup(uuid):
|
def cleanup(uuid):
|
||||||
|
@ -22,12 +22,8 @@ class TestAllocation(base.BaseTestCase):
|
|||||||
super(TestAllocation, self).setUp()
|
super(TestAllocation, self).setUp()
|
||||||
|
|
||||||
self.rp1 = self.resource_provider_create()
|
self.rp1 = self.resource_provider_create()
|
||||||
self.inv_cpu1 = self.resource_inventory_set(
|
self.resource_inventory_set(
|
||||||
self.rp1['uuid'],
|
self.rp1['uuid'], 'VCPU=4', 'MEMORY_MB=1024')
|
||||||
'VCPU=4',
|
|
||||||
'VCPU:max_unit=4',
|
|
||||||
'MEMORY_MB=1024',
|
|
||||||
'MEMORY_MB:max_unit=1024')
|
|
||||||
|
|
||||||
def test_allocation_show_not_found(self):
|
def test_allocation_show_not_found(self):
|
||||||
consumer_uuid = str(uuid.uuid4())
|
consumer_uuid = str(uuid.uuid4())
|
||||||
@ -141,12 +137,8 @@ class TestAllocation112(base.BaseTestCase):
|
|||||||
super(TestAllocation112, self).setUp()
|
super(TestAllocation112, self).setUp()
|
||||||
|
|
||||||
self.rp1 = self.resource_provider_create()
|
self.rp1 = self.resource_provider_create()
|
||||||
self.inv_cpu1 = self.resource_inventory_set(
|
self.resource_inventory_set(
|
||||||
self.rp1['uuid'],
|
self.rp1['uuid'], 'VCPU=4', 'MEMORY_MB=1024')
|
||||||
'VCPU=4',
|
|
||||||
'VCPU:max_unit=4',
|
|
||||||
'MEMORY_MB=1024',
|
|
||||||
'MEMORY_MB:max_unit=1024')
|
|
||||||
|
|
||||||
def test_allocation_update(self):
|
def test_allocation_update(self):
|
||||||
consumer_uuid = str(uuid.uuid4())
|
consumer_uuid = str(uuid.uuid4())
|
||||||
@ -230,32 +222,49 @@ class TestAllocationUnset112(base.BaseTestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestAllocationUnset112, self).setUp()
|
super(TestAllocationUnset112, self).setUp()
|
||||||
# Create two providers with inventory.
|
# Create four providers with inventory.
|
||||||
self.rp1 = self.resource_provider_create()
|
self.rp1 = self.resource_provider_create()
|
||||||
self.inv_cpu1 = self.resource_inventory_set(
|
|
||||||
self.rp1['uuid'],
|
|
||||||
'VCPU=4',
|
|
||||||
'VCPU:max_unit=4',
|
|
||||||
'MEMORY_MB=1024',
|
|
||||||
'MEMORY_MB:max_unit=1024')
|
|
||||||
self.rp2 = self.resource_provider_create()
|
self.rp2 = self.resource_provider_create()
|
||||||
self.resource_inventory_set(self.rp2['uuid'], 'VGPU=1')
|
self.rp3 = self.resource_provider_create()
|
||||||
# Create allocations against both providers for the same consumer.
|
self.rp4 = self.resource_provider_create()
|
||||||
self.consumer_uuid = str(uuid.uuid4())
|
|
||||||
|
self.resource_inventory_set(
|
||||||
|
self.rp1['uuid'], 'VCPU=4', 'MEMORY_MB=1024')
|
||||||
|
self.resource_inventory_set(
|
||||||
|
self.rp2['uuid'], 'VGPU=1')
|
||||||
|
self.resource_inventory_set(
|
||||||
|
self.rp3['uuid'], 'VCPU=4', 'MEMORY_MB=1024', 'VGPU=1')
|
||||||
|
self.resource_inventory_set(
|
||||||
|
self.rp4['uuid'], 'VCPU=4', 'MEMORY_MB=1024', 'VGPU=1')
|
||||||
|
|
||||||
|
self.consumer_uuid1 = str(uuid.uuid4())
|
||||||
|
self.consumer_uuid2 = str(uuid.uuid4())
|
||||||
self.project_uuid = str(uuid.uuid4())
|
self.project_uuid = str(uuid.uuid4())
|
||||||
self.user_uuid = str(uuid.uuid4())
|
self.user_uuid = str(uuid.uuid4())
|
||||||
|
|
||||||
|
# Create allocations against rp1 and rp2 for consumer1.
|
||||||
self.resource_allocation_set(
|
self.resource_allocation_set(
|
||||||
self.consumer_uuid,
|
self.consumer_uuid1,
|
||||||
['rp={},VCPU=2'.format(self.rp1['uuid']),
|
['rp={},VCPU=2'.format(self.rp1['uuid']),
|
||||||
'rp={},MEMORY_MB=512'.format(self.rp1['uuid']),
|
'rp={},MEMORY_MB=512'.format(self.rp1['uuid']),
|
||||||
'rp={},VGPU=1'.format(self.rp2['uuid'])],
|
'rp={},VGPU=1'.format(self.rp2['uuid'])],
|
||||||
project_id=self.project_uuid, user_id=self.user_uuid)
|
project_id=self.project_uuid, user_id=self.user_uuid)
|
||||||
|
|
||||||
|
# Create allocations against rp3 and rp4 for consumer1.
|
||||||
|
self.resource_allocation_set(
|
||||||
|
self.consumer_uuid2,
|
||||||
|
['rp={},VCPU=1'.format(self.rp3['uuid']),
|
||||||
|
'rp={},MEMORY_MB=256'.format(self.rp3['uuid']),
|
||||||
|
'rp={},VGPU=1'.format(self.rp3['uuid']),
|
||||||
|
'rp={},VCPU=1'.format(self.rp4['uuid']),
|
||||||
|
'rp={},MEMORY_MB=256'.format(self.rp4['uuid'])],
|
||||||
|
project_id=self.project_uuid, user_id=self.user_uuid)
|
||||||
|
|
||||||
def test_allocation_unset_one_provider(self):
|
def test_allocation_unset_one_provider(self):
|
||||||
"""Tests removing allocations for one specific provider."""
|
"""Tests removing allocations for one specific provider."""
|
||||||
# Remove the allocation for rp1.
|
# Remove the allocation for rp1.
|
||||||
updated_allocs = self.resource_allocation_unset(
|
updated_allocs = self.resource_allocation_unset(
|
||||||
self.consumer_uuid, provider=self.rp1['uuid'])
|
self.consumer_uuid1, provider=self.rp1['uuid'])
|
||||||
expected = [
|
expected = [
|
||||||
{'resource_provider': self.rp2['uuid'],
|
{'resource_provider': self.rp2['uuid'],
|
||||||
'generation': 3,
|
'generation': 3,
|
||||||
@ -265,12 +274,62 @@ class TestAllocationUnset112(base.BaseTestCase):
|
|||||||
]
|
]
|
||||||
self.assertEqual(expected, updated_allocs)
|
self.assertEqual(expected, updated_allocs)
|
||||||
|
|
||||||
|
def test_allocation_unset_one_resource_class(self):
|
||||||
|
"""Tests removing allocations for resource classes."""
|
||||||
|
updated_allocs = self.resource_allocation_unset(
|
||||||
|
self.consumer_uuid2, resource_class=['MEMORY_MB'])
|
||||||
|
expected = [
|
||||||
|
{'resource_provider': self.rp3['uuid'],
|
||||||
|
'generation': 3,
|
||||||
|
'project_id': self.project_uuid,
|
||||||
|
'user_id': self.user_uuid,
|
||||||
|
'resources': {'VCPU': 1, 'VGPU': 1}},
|
||||||
|
{'resource_provider': self.rp4['uuid'],
|
||||||
|
'generation': 3,
|
||||||
|
'project_id': self.project_uuid,
|
||||||
|
'user_id': self.user_uuid,
|
||||||
|
'resources': {'VCPU': 1}}
|
||||||
|
]
|
||||||
|
self.assertEqual(expected, updated_allocs)
|
||||||
|
|
||||||
|
def test_allocation_unset_resource_classes(self):
|
||||||
|
"""Tests removing allocations for resource classes."""
|
||||||
|
updated_allocs = self.resource_allocation_unset(
|
||||||
|
self.consumer_uuid2, resource_class=['VCPU', 'MEMORY_MB'])
|
||||||
|
expected = [
|
||||||
|
{'resource_provider': self.rp3['uuid'],
|
||||||
|
'generation': 3,
|
||||||
|
'project_id': self.project_uuid,
|
||||||
|
'user_id': self.user_uuid,
|
||||||
|
'resources': {'VGPU': 1}}
|
||||||
|
]
|
||||||
|
self.assertEqual(expected, updated_allocs)
|
||||||
|
|
||||||
|
def test_allocation_unset_provider_and_rc(self):
|
||||||
|
"""Tests removing allocations of resource classes for a provider ."""
|
||||||
|
updated_allocs = self.resource_allocation_unset(
|
||||||
|
self.consumer_uuid2, provider=self.rp3['uuid'],
|
||||||
|
resource_class=['VCPU', 'MEMORY_MB'])
|
||||||
|
expected = [
|
||||||
|
{'resource_provider': self.rp3['uuid'],
|
||||||
|
'generation': 3,
|
||||||
|
'project_id': self.project_uuid,
|
||||||
|
'user_id': self.user_uuid,
|
||||||
|
'resources': {'VGPU': 1}},
|
||||||
|
{'resource_provider': self.rp4['uuid'],
|
||||||
|
'generation': 3,
|
||||||
|
'project_id': self.project_uuid,
|
||||||
|
'user_id': self.user_uuid,
|
||||||
|
'resources': {'VCPU': 1, 'MEMORY_MB': 256}},
|
||||||
|
]
|
||||||
|
self.assertEqual(expected, updated_allocs)
|
||||||
|
|
||||||
def test_allocation_unset_remove_all_providers(self):
|
def test_allocation_unset_remove_all_providers(self):
|
||||||
"""Tests removing all allocations by omitting the --provider option."""
|
"""Tests removing all allocations by omitting the --provider option."""
|
||||||
# For this test pass use_json=False to make sure we get nothing back
|
# For this test pass use_json=False to make sure we get nothing back
|
||||||
# in the output since there are no more allocations.
|
# in the output since there are no more allocations.
|
||||||
updated_allocs = self.resource_allocation_unset(
|
updated_allocs = self.resource_allocation_unset(
|
||||||
self.consumer_uuid, use_json=False)
|
self.consumer_uuid1, use_json=False)
|
||||||
self.assertEqual('', updated_allocs.strip())
|
self.assertEqual('', updated_allocs.strip())
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
The ``openstack resource provider allocation unset`` command now supports
|
||||||
|
``--resource-class`` option, which accepts string of a resource class.
|
||||||
|
This will remove allocations for the given resource class from all the
|
||||||
|
providers. If ``--provider`` option is also specified, allocations to
|
||||||
|
remove will be limited to the given resource class of the given resource
|
||||||
|
provider.
|
||||||
|
|
||||||
|
example1::
|
||||||
|
|
||||||
|
# remove VGPU allocation from provider P for this consumer.
|
||||||
|
allocation unset <consumer_uuid> --provider P --resource-class VGPU
|
||||||
|
|
||||||
|
example2::
|
||||||
|
|
||||||
|
# remove VGPU allocations from all providers for this consumer.
|
||||||
|
allocation unset <consumer_uuid> --resource-class VGPU
|
Loading…
Reference in New Issue
Block a user