RP delete inventories (v1.5)
UpgradeImpact: this change will require a major version release since a previously required argument (resource_class) is now an option (--resource_class) for the "openstack resource provider inventory delete" CLI. Change-Id: I4be95feeadcbf82ab23fa2709b72db4d4203c1e7 Partially-Implements: blueprint placement-osc-plugin-rocky
This commit is contained in:
parent
844414861a
commit
0a5493f264
@ -15,21 +15,15 @@
|
||||
import logging
|
||||
|
||||
from osc_lib import utils
|
||||
from osc_placement import version
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
API_NAME = 'placement'
|
||||
API_VERSION_OPTION = 'os_placement_api_version'
|
||||
SUPPORTED_VERSIONS = [
|
||||
'1.0',
|
||||
'1.1',
|
||||
'1.2',
|
||||
'1.3',
|
||||
'1.4'
|
||||
]
|
||||
API_VERSIONS = {v: 'osc_placement.http.SessionClient'
|
||||
for v in SUPPORTED_VERSIONS}
|
||||
for v in version.SUPPORTED_VERSIONS}
|
||||
|
||||
|
||||
def make_client(instance):
|
||||
@ -51,13 +45,14 @@ def make_client(instance):
|
||||
|
||||
|
||||
def build_option_parser(parser):
|
||||
default = version.SUPPORTED_VERSIONS[0]
|
||||
parser.add_argument(
|
||||
'--os-placement-api-version',
|
||||
metavar='<placement-api-version>',
|
||||
default=utils.env(
|
||||
'OS_PLACEMENT_API_VERSION',
|
||||
default='1.0'
|
||||
default=default
|
||||
),
|
||||
help='Placement API version, default=1.0'
|
||||
)
|
||||
help='Placement API version, default=%s' % default)
|
||||
|
||||
return parser
|
||||
|
@ -15,6 +15,8 @@ from collections import defaultdict
|
||||
from osc_lib.command import command
|
||||
from osc_lib import utils
|
||||
|
||||
from osc_placement import version
|
||||
|
||||
|
||||
BASE_URL = '/resource_providers/{uuid}/inventories'
|
||||
PER_CLASS_URL = BASE_URL + '/{resource_class}'
|
||||
@ -211,10 +213,17 @@ class SetClassInventory(command.ShowOne):
|
||||
return FIELDS, utils.get_dict_properties(resource, FIELDS)
|
||||
|
||||
|
||||
# TODO(avolkov): Add delete all inventories for RP (version 1.5)
|
||||
class DeleteInventory(command.Command):
|
||||
class DeleteInventory(command.Command, version.CheckerMixin):
|
||||
|
||||
"""Delete the inventory for a given resource provider/class pair"""
|
||||
"""Delete the inventory.
|
||||
|
||||
Depending on the resource class argument presence, it can
|
||||
delete all inventory for a given resource provider or for a resource
|
||||
provider/class pair.
|
||||
|
||||
Delete all inventories for given resource provider
|
||||
requires at least ``--os-placement-api-version 1.5``.
|
||||
"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteInventory, self).get_parser(prog_name)
|
||||
@ -225,19 +234,28 @@ class DeleteInventory(command.Command):
|
||||
help='UUID of the resource provider'
|
||||
)
|
||||
parser.add_argument(
|
||||
'resource_class',
|
||||
'--resource-class',
|
||||
metavar='<resource_class>',
|
||||
help=RC_HELP
|
||||
required=self.compare_version(version.lt('1.5')),
|
||||
help=(RC_HELP +
|
||||
'\nThis argument can be omitted starting with '
|
||||
'``--os-placement-api-version 1.5``. If it is omitted all '
|
||||
'inventories of the specified resource provider '
|
||||
'will be deleted.')
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
http = self.app.client_manager.placement
|
||||
url = BASE_URL
|
||||
params = {'uuid': parsed_args.uuid}
|
||||
if parsed_args.resource_class is not None:
|
||||
url = PER_CLASS_URL
|
||||
params = {'uuid': parsed_args.uuid,
|
||||
'resource_class': parsed_args.resource_class}
|
||||
|
||||
url = PER_CLASS_URL.format(uuid=parsed_args.uuid,
|
||||
resource_class=parsed_args.resource_class)
|
||||
http.request('DELETE', url)
|
||||
http.request('DELETE', url.format(**params))
|
||||
|
||||
|
||||
class ShowInventory(command.ShowOne):
|
||||
|
@ -147,10 +147,10 @@ class BaseTestCase(base.BaseTestCase):
|
||||
return self.openstack('resource provider inventory list ' + uuid,
|
||||
use_json=True)
|
||||
|
||||
def resource_inventory_delete(self, uuid, resource_class):
|
||||
cmd = 'resource provider inventory delete {uuid} {rc}'.format(
|
||||
uuid=uuid, rc=resource_class
|
||||
)
|
||||
def resource_inventory_delete(self, uuid, resource_class=None):
|
||||
cmd = 'resource provider inventory delete {uuid}'.format(uuid=uuid)
|
||||
if resource_class:
|
||||
cmd += ' --resource-class ' + resource_class
|
||||
self.openstack(cmd)
|
||||
|
||||
def resource_inventory_set(self, uuid, *resources):
|
||||
|
@ -63,6 +63,14 @@ class TestInventory(base.BaseTestCase):
|
||||
self.assertIn('No inventory of class VCPU found for delete',
|
||||
exc.output.decode('utf-8'))
|
||||
|
||||
def test_delete_all_inventories(self):
|
||||
# Negative test to assert command failure because
|
||||
# microversion < 1.5 and --resource-class is not specified.
|
||||
self.assertCommandFailed(
|
||||
'argument --resource-class is required',
|
||||
self.resource_inventory_delete,
|
||||
'fake_uuid')
|
||||
|
||||
|
||||
class TestSetInventory(base.BaseTestCase):
|
||||
def test_fail_if_no_rp(self):
|
||||
@ -194,3 +202,13 @@ class TestSetInventory(base.BaseTestCase):
|
||||
self.assertEqual(128, inv['MEMORY_MB']['total'])
|
||||
self.assertEqual(16, inv['MEMORY_MB']['step_size'])
|
||||
self.assertEqual(32, inv['VCPU']['total'])
|
||||
|
||||
|
||||
class TestInventory15(TestInventory):
|
||||
VERSION = '1.5'
|
||||
|
||||
def test_delete_all_inventories(self):
|
||||
rp = self.resource_provider_create()
|
||||
self.resource_inventory_set(rp['uuid'], 'MEMORY_MB=16', 'VCPU=32')
|
||||
self.resource_inventory_delete(rp['uuid'])
|
||||
self.assertEqual([], self.resource_inventory_list(rp['uuid']))
|
||||
|
@ -14,6 +14,16 @@ from distutils.version import StrictVersion
|
||||
import operator
|
||||
|
||||
|
||||
SUPPORTED_VERSIONS = [
|
||||
'1.0',
|
||||
'1.1',
|
||||
'1.2',
|
||||
'1.3',
|
||||
'1.4',
|
||||
'1.5',
|
||||
]
|
||||
|
||||
|
||||
def _op(func, b):
|
||||
return lambda a: func(StrictVersion(a), StrictVersion(b))
|
||||
|
||||
@ -48,6 +58,16 @@ def _compare(ver, *predicates, **kwargs):
|
||||
|
||||
|
||||
def compare(ver, *predicates, **kwargs):
|
||||
"""Validate version satisfies provided predicates.
|
||||
|
||||
kwargs['exc'] - boolean whether exception should be raised
|
||||
kwargs['op'] - (all, any) how predicates should be checked
|
||||
|
||||
Examples:
|
||||
compare('1.1', version.gt('1.2'), exc=False) - False
|
||||
compare('1.1', version.eq('1.0'), version.eq('1.1'), op=any) - True
|
||||
|
||||
"""
|
||||
exc = kwargs.get('exc', True)
|
||||
if not _compare(ver, *predicates, **kwargs):
|
||||
if exc:
|
||||
@ -58,20 +78,33 @@ def compare(ver, *predicates, **kwargs):
|
||||
|
||||
|
||||
def check(*predicates, **check_kwargs):
|
||||
"""Decorator for command object method.
|
||||
|
||||
See `compare`
|
||||
|
||||
"""
|
||||
def wrapped(func):
|
||||
def inner(self, *args, **kwargs):
|
||||
version = self.app.client_manager.placement.api_version
|
||||
compare(version, *predicates, **check_kwargs)
|
||||
compare(get_version(self), *predicates, **check_kwargs)
|
||||
return func(self, *args, **kwargs)
|
||||
return inner
|
||||
return wrapped
|
||||
|
||||
|
||||
def get_version(obj):
|
||||
"""Extract version from a command object."""
|
||||
try:
|
||||
version = obj.app.client_manager.placement.api_version
|
||||
except AttributeError:
|
||||
# resource does not have api_version attr when docs are generated
|
||||
# so let's use the minimal one
|
||||
version = SUPPORTED_VERSIONS[0]
|
||||
return version
|
||||
|
||||
|
||||
class CheckerMixin(object):
|
||||
def check_version(self, *predicates, **kwargs):
|
||||
version = self.app.client_manager.placement.api_version
|
||||
return compare(version, *predicates, **kwargs)
|
||||
return compare(get_version(self), *predicates, **kwargs)
|
||||
|
||||
def compare_version(self, *predicates, **kwargs):
|
||||
version = self.app.client_manager.placement.api_version
|
||||
return compare(version, *predicates, exc=False, **kwargs)
|
||||
return compare(get_version(self), *predicates, exc=False, **kwargs)
|
||||
|
18
releasenotes/notes/microversion-1.5-0c6342c887669b8e.yaml
Normal file
18
releasenotes/notes/microversion-1.5-0c6342c887669b8e.yaml
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
The ``openstack resource provider inventory delete`` command now supports
|
||||
microversion `1.5`_. Specifically it is possible to delete all inventories
|
||||
of the specified resource provider.
|
||||
|
||||
See the `command documentation`__ for more details.
|
||||
|
||||
.. _1.5: https://docs.openstack.org/nova/latest/user/placement.html#delete-all-inventory-for-a-resource-provider
|
||||
.. __: https://docs.openstack.org/osc-placement/latest/cli/index.html#resource-provider-inventory-delete
|
||||
upgrade:
|
||||
- |
|
||||
The ``resource_class`` positional argument in command
|
||||
``openstack resource provider inventory delete`` was replaced with the
|
||||
``--resource-class`` optional argument. The ``--resource-class`` option
|
||||
is still required if using ``--os-placement-api-version`` less than
|
||||
1.5.
|
Loading…
x
Reference in New Issue
Block a user