From 203f4f06961481e4013dd11c0e74afb9ffe354a4 Mon Sep 17 00:00:00 2001 From: Bence Romsics Date: Fri, 6 Jul 2018 15:22:50 +0200 Subject: [PATCH] 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) --- neutron_lib/clients/placement.py | 47 ++++++++++++++++++- neutron_lib/exceptions/placement.py | 5 ++ .../tests/unit/clients/test_placement.py | 37 ++++++++++++++- ...ent-update-ensure-rp-9e5c3cf34d49b212.yaml | 5 ++ 4 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 releasenotes/notes/placement-client-update-ensure-rp-9e5c3cf34d49b212.yaml diff --git a/neutron_lib/clients/placement.py b/neutron_lib/clients/placement.py index ceee392cf..5e36119e6 100644 --- a/neutron_lib/clients/placement.py +++ b/neutron_lib/clients/placement.py @@ -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. diff --git a/neutron_lib/exceptions/placement.py b/neutron_lib/exceptions/placement.py index a609527db..7f853c170 100644 --- a/neutron_lib/exceptions/placement.py +++ b/neutron_lib/exceptions/placement.py @@ -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.") diff --git a/neutron_lib/tests/unit/clients/test_placement.py b/neutron_lib/tests/unit/clients/test_placement.py index 2bdffa916..182209de9 100644 --- a/neutron_lib/tests/unit/clients/test_placement.py +++ b/neutron_lib/tests/unit/clients/test_placement.py @@ -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): diff --git a/releasenotes/notes/placement-client-update-ensure-rp-9e5c3cf34d49b212.yaml b/releasenotes/notes/placement-client-update-ensure-rp-9e5c3cf34d49b212.yaml new file mode 100644 index 000000000..fe6210edb --- /dev/null +++ b/releasenotes/notes/placement-client-update-ensure-rp-9e5c3cf34d49b212.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + New methods available in Placement client: + ``update_resource_provider`` and ``ensure_resource_provider``.