Placement client: ensure_resource_provider

All other API resources (ie. traits, resource_provider_traits and
resource_provider_inventories) we need to report on for minimum
guaranteed bandwidth have update methods that can be called in one go,
either because they have update-or-create or update-overrides-all
semantics. Here we add the 'ensure_resource_provider' method so
resource providers also have a similarly simple way of being kept in
sync.  We also add 'update_resource_provider' as a pre-requisite. On
the side we also fix a little, silent unit test type error.

Change-Id: Ib615ceeb323970d179ffb3dee14e52cb40e73ae7
Partial-Bug: #1578989
See-Also: https://review.openstack.org/502306 (nova spec)
See-Also: https://review.openstack.org/508149 (neutron spec)
This commit is contained in:
Bence Romsics 2018-07-06 15:22:50 +02:00
parent 5aa2847367
commit 203f4f0696
4 changed files with 90 additions and 4 deletions

View File

@ -128,13 +128,56 @@ class PlacementAPIClient(object):
def create_resource_provider(self, resource_provider):
"""Create a resource provider.
:param resource_provider: The resource provider. A dict with the name
(required) and the uuid (required).
:param resource_provider: The resource provider. A dict with
the uuid (required),
the name (required) and
the parent_provider_uuid (optional).
:returns: The resource provider created.
"""
url = '/resource_providers'
return self._post(url, resource_provider).json()
@_check_placement_api_available
def update_resource_provider(self, resource_provider):
"""Update the resource provider identified by uuid.
:param resource_provider: The resource provider. A dict with
the uuid (required),
the name (required) and
the parent_provider_uuid (optional).
:returns: The updated resource provider.
"""
url = '/resource_providers/%s' % resource_provider['uuid']
# update does not tolerate if the uuid is repeated in the body
update_body = resource_provider.copy()
update_body.pop('uuid')
try:
return self._put(url, update_body).json()
except ks_exc.NotFound:
raise n_exc.PlacementResourceProviderNotFound(
resource_provider=resource_provider['uuid'])
except ks_exc.Conflict:
raise n_exc.PlacementResourceProviderNameNotUnique(
name=resource_provider['name'])
@_check_placement_api_available
def ensure_resource_provider(self, resource_provider):
"""Ensure a resource provider exists by updating or creating it.
:param resource_provider: The resource provider. A dict with
the uuid (required),
the name (required) and
the parent_provider_uuid (optional).
:returns: The Resource Provider updated or created.
Beware, this is not an atomic operation of the API.
"""
try:
return self.update_resource_provider(
resource_provider=resource_provider)
except n_exc.PlacementResourceProviderNotFound:
return self.create_resource_provider(resource_provider)
@_check_placement_api_available
def delete_resource_provider(self, resource_provider_uuid):
"""Delete a resource provider.

View File

@ -60,3 +60,8 @@ class PlacementResourceClassNotFound(exceptions.NotFound):
class PlacementAPIVersionIncorrect(exceptions.NotFound):
message = _("Placement API version %(current_version)s, do not meet the"
"needed version %(needed_version)s.")
class PlacementResourceProviderNameNotUnique(exceptions.Conflict):
message = _("Another resource provider exists with the provided name: "
"%(name)s.")

View File

@ -24,6 +24,11 @@ from neutron_lib.tests import _base as base
RESOURCE_PROVIDER_UUID = uuidutils.generate_uuid()
RESOURCE_PROVIDER_NAME = 'resource_provider_name'
RESOURCE_PROVIDER = {
'uuid': RESOURCE_PROVIDER_UUID,
'name': RESOURCE_PROVIDER_NAME,
}
RESOURCE_PROVIDER_GENERATION = 1
RESOURCE_CLASS_NAME = 'resource_class_name'
TRAIT_NAME = 'trait_name'
@ -49,10 +54,38 @@ class TestPlacementAPIClient(base.BaseTestCase):
def test_create_resource_provider(self):
self.placement_api_client.create_resource_provider(
RESOURCE_PROVIDER_UUID)
RESOURCE_PROVIDER)
self.placement_fixture.mock_post.assert_called_once_with(
'/resource_providers',
RESOURCE_PROVIDER_UUID
RESOURCE_PROVIDER
)
def test_update_resource_provider(self):
self.placement_api_client.update_resource_provider(
RESOURCE_PROVIDER)
self.placement_fixture.mock_put.assert_called_once_with(
'/resource_providers/%s' % RESOURCE_PROVIDER_UUID,
{'name': RESOURCE_PROVIDER_NAME}
)
def test_ensure_update_resource_provider(self):
self.placement_api_client.ensure_resource_provider(
RESOURCE_PROVIDER)
self.placement_fixture.mock_put.assert_called_once_with(
'/resource_providers/%s' % RESOURCE_PROVIDER_UUID,
{'name': RESOURCE_PROVIDER_NAME}
)
self.placement_fixture.mock_post.assert_not_called()
def test_ensure_create_resource_provider(self):
self.placement_fixture.mock_put.side_effect = \
n_exc.PlacementResourceProviderNotFound(
resource_provider=RESOURCE_PROVIDER_UUID)
self.placement_api_client.ensure_resource_provider(
RESOURCE_PROVIDER)
self.placement_fixture.mock_post.assert_called_once_with(
'/resource_providers',
RESOURCE_PROVIDER
)
def test_delete_resource_provider(self):

View File

@ -0,0 +1,5 @@
---
features:
- |
New methods available in Placement client:
``update_resource_provider`` and ``ensure_resource_provider``.