diff --git a/doc/source/user/proxies/placement.rst b/doc/source/user/proxies/placement.rst index fe15e73a2..b7bd15625 100644 --- a/doc/source/user/proxies/placement.rst +++ b/doc/source/user/proxies/placement.rst @@ -14,19 +14,21 @@ Resource Classes ^^^^^^^^^^^^^^^^ .. autoclass:: openstack.placement.v1._proxy.Proxy - :noindex: - :members: create_resource_class, update_resource_class, - delete_resource_class, get_resource_class, - resource_classes + :noindex: + :members: create_resource_class, update_resource_class, + delete_resource_class, get_resource_class, + resource_classes Resource Providers ^^^^^^^^^^^^^^^^^^ .. autoclass:: openstack.placement.v1._proxy.Proxy - :noindex: - :members: create_resource_provider, update_resource_provider, - delete_resource_provider, get_resource_provider, - find_resource_provider, resource_providers + :noindex: + :members: create_resource_provider, update_resource_provider, + delete_resource_provider, get_resource_provider, + find_resource_provider, resource_providers, + get_resource_provider_aggregates, + set_resource_provider_aggregates Resource Provider Inventories ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/openstack/placement/v1/_proxy.py b/openstack/placement/v1/_proxy.py index 1781b6867..d3a0b79fc 100644 --- a/openstack/placement/v1/_proxy.py +++ b/openstack/placement/v1/_proxy.py @@ -209,6 +209,50 @@ class Proxy(proxy.Proxy): """ return self._list(_resource_provider.ResourceProvider, **query) + # resource provider aggregates + + def get_resource_provider_aggregates(self, resource_provider): + """Get a list of aggregates for a resource provider. + + :param resource_provider: The value can be either the ID of a resource + provider or an + :class:`~openstack.placement.v1.resource_provider.ResourceProvider`, + instance. + + :returns: An instance of + :class:`~openstack.placement.v1.resource_provider.ResourceProvider` + with the ``aggregates`` attribute populated. + :raises: :class:`~openstack.exceptions.ResourceNotFound` when no + resource provider matching the criteria could be found. + """ + res = self._get_resource( + _resource_provider.ResourceProvider, + resource_provider, + ) + return res.fetch_aggregates(self) + + def set_resource_provider_aggregates(self, resource_provider, *aggregates): + """Update aggregates for a resource provider. + + :param resource_provider: The value can be either the ID of a resource + provider or an + :class:`~openstack.placement.v1.resource_provider.ResourceProvider`, + instance. + :param aggregates: A list of aggregates. These aggregates will replace + all aggregates currently present. + + :returns: An instance of + :class:`~openstack.placement.v1.resource_provider.ResourceProvider` + with the ``aggregates`` attribute populated with the updated value. + :raises: :class:`~openstack.exceptions.ResourceNotFound` when no + resource provider matching the criteria could be found. + """ + res = self._get_resource( + _resource_provider.ResourceProvider, + resource_provider, + ) + return res.set_aggregates(self, aggregates=aggregates) + # resource provider inventories def create_resource_provider_inventory( diff --git a/openstack/placement/v1/resource_provider.py b/openstack/placement/v1/resource_provider.py index 1d6ba5d83..4da2d3bcc 100644 --- a/openstack/placement/v1/resource_provider.py +++ b/openstack/placement/v1/resource_provider.py @@ -10,7 +10,9 @@ # License for the specific language governing permissions and limitations # under the License. +from openstack import exceptions from openstack import resource +from openstack import utils class ResourceProvider(resource.Resource): @@ -45,6 +47,8 @@ class ResourceProvider(resource.Resource): # Properties + #: Aggregates + aggregates = resource.Body('aggregates', type=list, list_type=str) #: The UUID of a resource provider. id = resource.Body('uuid', alternate_id=True) #: A consistent view marker that assists with the management of concurrent @@ -59,3 +63,52 @@ class ResourceProvider(resource.Resource): parent_provider_id = resource.Body('parent_provider_uuid') #: Read-only UUID of the top-most provider in this provider tree. root_provider_id = resource.Body('root_provider_uuid') + + def fetch_aggregates(self, session): + """List aggregates set on the resource provider + + :param session: The session to use for making this request + :return: The resource provider with aggregates populated + """ + url = utils.urljoin(self.base_path, self.id, 'aggregates') + microversion = self._get_microversion(session, action='fetch') + + response = session.get(url, microversion=microversion) + exceptions.raise_from_response(response) + data = response.json() + + updates = {'aggregates': data['aggregates']} + if utils.supports_microversion(session, '1.19'): + updates['generation'] = data['resource_provider_generation'] + self._body.attributes.update(updates) + + return self + + def set_aggregates(self, session, aggregates=None): + """Replaces aggregates on the resource provider + + :param session: The session to use for making this request + :param list aggregates: List of aggregates + :return: The resource provider with updated aggregates populated + """ + url = utils.urljoin(self.base_path, self.id, 'aggregates') + microversion = self._get_microversion(session, action='commit') + + body = { + 'aggregates': aggregates or [], + } + if utils.supports_microversion(session, '1.19'): + body['resource_provider_generation'] = self.generation + + response = session.put(url, json=body, microversion=microversion) + exceptions.raise_from_response(response) + data = response.json() + + updates = {'aggregates': data['aggregates']} + if 'resource_provider_generation' in data: + updates['resource_provider_generation'] = data[ + 'resource_provider_generation' + ] + self._body.attributes.update(updates) + + return self diff --git a/openstack/tests/functional/placement/v1/test_resource_provider.py b/openstack/tests/functional/placement/v1/test_resource_provider.py index e5db948a8..516182242 100644 --- a/openstack/tests/functional/placement/v1/test_resource_provider.py +++ b/openstack/tests/functional/placement/v1/test_resource_provider.py @@ -10,6 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. +import uuid + from openstack.placement.v1 import resource_provider as _resource_provider from openstack.tests.functional import base @@ -93,3 +95,25 @@ class TestResourceProvider(base.BaseFunctionalTest): new_resource_provider_name, resource_provider.name, ) + + def test_resource_provider_aggregates(self): + aggregates = [uuid.uuid4().hex, uuid.uuid4().hex] + + # update the resource provider aggregates + + resource_provider = ( + self.operator_cloud.placement.set_resource_provider_aggregates( + self.resource_provider, + *aggregates, + ) + ) + self.assertCountEqual(aggregates, resource_provider.aggregates) + + # retrieve details of resource provider aggregates + + resource_provider = ( + self.operator_cloud.placement.get_resource_provider_aggregates( + self.resource_provider, + ) + ) + self.assertCountEqual(aggregates, resource_provider.aggregates) diff --git a/openstack/tests/unit/placement/v1/test_proxy.py b/openstack/tests/unit/placement/v1/test_proxy.py index 0687551ea..5dcdec11d 100644 --- a/openstack/tests/unit/placement/v1/test_proxy.py +++ b/openstack/tests/unit/placement/v1/test_proxy.py @@ -90,6 +90,23 @@ class TestPlacementResourceProvider(TestPlacementProxy): resource_provider.ResourceProvider, ) + def test_resource_provider_set_aggregates(self): + self._verify( + 'openstack.placement.v1.resource_provider.ResourceProvider.set_aggregates', + self.proxy.set_resource_provider_aggregates, + method_args=['value', 'a', 'b'], + expected_args=[self.proxy], + expected_kwargs={'aggregates': ('a', 'b')}, + ) + + def test_resource_provider_get_aggregates(self): + self._verify( + 'openstack.placement.v1.resource_provider.ResourceProvider.fetch_aggregates', + self.proxy.get_resource_provider_aggregates, + method_args=['value'], + expected_args=[self.proxy], + ) + class TestPlacementResourceProviderInventory(TestPlacementProxy): def test_resource_provider_inventory_create(self): diff --git a/releasenotes/notes/add-placement-resource-provider-aggregates-1310c0be6a4097d3.yaml b/releasenotes/notes/add-placement-resource-provider-aggregates-1310c0be6a4097d3.yaml new file mode 100644 index 000000000..e8385edad --- /dev/null +++ b/releasenotes/notes/add-placement-resource-provider-aggregates-1310c0be6a4097d3.yaml @@ -0,0 +1,4 @@ +--- +features: + - | + Add support for aggregates to the ``ResourceProvider`` Placement resource.