diff --git a/doc/source/user/proxies/placement.rst b/doc/source/user/proxies/placement.rst index 0cc3f8974..b9978e7d1 100644 --- a/doc/source/user/proxies/placement.rst +++ b/doc/source/user/proxies/placement.rst @@ -10,6 +10,14 @@ The placement high-level interface is available through the ``placement`` member of a :class:`~openstack.connection.Connection` object. The ``placement`` member will only be added if the service is detected. +Resource Classes +^^^^^^^^^^^^^^^^ + +.. autoclass:: openstack.placement.v1._proxy.Proxy + :noindex: + :members: create_resource_class, update_resource_class, + delete_resource_class, get_resource_class, + resource_classes Resource Providers ^^^^^^^^^^^^^^^^^^ @@ -18,4 +26,4 @@ Resource Providers :noindex: :members: create_resource_provider, update_resource_provider, delete_resource_provider, get_resource_provider, - resource_providers + find_resource_provider, resource_providers diff --git a/doc/source/user/resources/placement/index.rst b/doc/source/user/resources/placement/index.rst index 7f581b9bb..5d8180cd9 100644 --- a/doc/source/user/resources/placement/index.rst +++ b/doc/source/user/resources/placement/index.rst @@ -4,4 +4,5 @@ Placement v1 Resources .. toctree:: :maxdepth: 1 + v1/resource_class v1/resource_provider diff --git a/doc/source/user/resources/placement/v1/resource_class.rst b/doc/source/user/resources/placement/v1/resource_class.rst new file mode 100644 index 000000000..2ef5817b9 --- /dev/null +++ b/doc/source/user/resources/placement/v1/resource_class.rst @@ -0,0 +1,13 @@ +openstack.placement.v1.resource_class +===================================== + +.. automodule:: openstack.placement.v1.resource_class + +The ResourceClass Class +----------------------- + +The ``ResourceClass`` class inherits from +:class:`~openstack.resource.Resource`. + +.. autoclass:: openstack.placement.v1.resource_class.ResourceClass + :members: diff --git a/openstack/placement/v1/_proxy.py b/openstack/placement/v1/_proxy.py index 9f222afef..a8ac8f26a 100644 --- a/openstack/placement/v1/_proxy.py +++ b/openstack/placement/v1/_proxy.py @@ -10,12 +10,94 @@ # License for the specific language governing permissions and limitations # under the License. +from openstack.placement.v1 import resource_class as _resource_class from openstack.placement.v1 import resource_provider as _resource_provider from openstack import proxy class Proxy(proxy.Proxy): + # resource classes + + def create_resource_class(self, **attrs): + """Create a new resource class from attributes. + + :param attrs: Keyword arguments which will be used to create a + :class:`~openstack.placement.v1.resource_provider.ResourceClass`, + comprised of the properties on the ResourceClass class. + + :returns: The results of resource class creation + :rtype: :class:`~openstack.placement.v1.resource_class.ResourceClass` + """ + return self._create(_resource_class.ResourceClass, **attrs) + + def delete_resource_class(self, resource_class, ignore_missing=True): + """Delete a resource class + + :param resource_class: The value can be either the ID of a resource + class or an + :class:`~openstack.placement.v1.resource_class.ResourceClass`, + instance. + :param bool ignore_missing: When set to ``False`` + :class:`~openstack.exceptions.ResourceNotFound` will be raised when + the resource class does not exist. When set to ``True``, no + exception will be set when attempting to delete a nonexistent + resource class. + + :returns: ``None`` + """ + self._delete( + _resource_class.ResourceClass, + resource_class, + ignore_missing=ignore_missing, + ) + + def update_resource_class(self, resource_class, **attrs): + """Update a resource class + + :param resource_class: The value can be either the ID of a resource + class or an + :class:`~openstack.placement.v1.resource_class.ResourceClass`, + instance. + :attrs kwargs: The attributes to update on the resource class + represented by ``resource_class``. + + :returns: The updated resource class + :rtype: :class:`~openstack.placement.v1.resource_class.ResourceClass` + """ + return self._update( + _resource_class.ResourceClass, resource_class, **attrs, + ) + + def get_resource_class(self, resource_class): + """Get a single resource_class. + + :param resource_class: The value can be either the ID of a resource + class or an + :class:`~openstack.placement.v1.resource_class.ResourceClass`, + instance. + + :returns: An instance of + :class:`~openstack.placement.v1.resource_class.ResourceClass` + :raises: :class:`~openstack.exceptions.ResourceNotFound` when no + resource class matching the criteria could be found. + """ + return self._get( + _resource_class.ResourceClass, resource_class, + ) + + def resource_classes(self, **query): + """Retrieve a generator of resource classs. + + :param kwargs query: Optional query parameters to be sent to + restrict the resource classs to be returned. + + :returns: A generator of resource class instances. + """ + return self._list(_resource_class.ResourceClass, **query) + + # resource providers + def create_resource_provider(self, **attrs): """Create a new resource provider from attributes. @@ -50,7 +132,7 @@ class Proxy(proxy.Proxy): ) def update_resource_provider(self, resource_provider, **attrs): - """Update a flavor + """Update a resource provider :param resource_provider: The value can be either the ID of a resource provider or an diff --git a/openstack/placement/v1/resource_class.py b/openstack/placement/v1/resource_class.py new file mode 100644 index 000000000..e45f5e642 --- /dev/null +++ b/openstack/placement/v1/resource_class.py @@ -0,0 +1,32 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from openstack import resource + + +class ResourceClass(resource.Resource): + resource_key = None + resources_key = 'resource_classes' + base_path = '/resource_classes' + + # Capabilities + + allow_create = True + allow_fetch = True + allow_commit = True + allow_delete = True + allow_list = True + + # Added in 1.2 + _max_microversion = '1.2' + + name = resource.Body('name', alternate_id=True) diff --git a/openstack/tests/unit/placement/v1/test_proxy.py b/openstack/tests/unit/placement/v1/test_proxy.py index 210704f09..1b915c0e9 100644 --- a/openstack/tests/unit/placement/v1/test_proxy.py +++ b/openstack/tests/unit/placement/v1/test_proxy.py @@ -11,6 +11,7 @@ # under the License. from openstack.placement.v1 import _proxy +from openstack.placement.v1 import resource_class from openstack.placement.v1 import resource_provider from openstack.tests.unit import test_proxy_base as test_proxy_base @@ -21,6 +22,42 @@ class TestPlacementProxy(test_proxy_base.TestProxyBase): super().setUp() self.proxy = _proxy.Proxy(self.session) + # resource classes + + def test_resource_class_create(self): + self.verify_create( + self.proxy.create_resource_class, + resource_class.ResourceClass, + ) + + def test_resource_class_delete(self): + self.verify_delete( + self.proxy.delete_resource_class, + resource_class.ResourceClass, + False, + ) + + def test_resource_class_update(self): + self.verify_update( + self.proxy.update_resource_class, + resource_class.ResourceClass, + False, + ) + + def test_resource_class_get(self): + self.verify_get( + self.proxy.get_resource_class, + resource_class.ResourceClass, + ) + + def test_resource_classes(self): + self.verify_list_no_kwargs( + self.proxy.resource_classes, + resource_class.ResourceClass, + ) + + # resource providers + def test_resource_provider_create(self): self.verify_create( self.proxy.create_resource_provider, diff --git a/openstack/tests/unit/placement/v1/test_resource_class.py b/openstack/tests/unit/placement/v1/test_resource_class.py new file mode 100644 index 000000000..9114dec34 --- /dev/null +++ b/openstack/tests/unit/placement/v1/test_resource_class.py @@ -0,0 +1,42 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from openstack.placement.v1 import resource_class as rc +from openstack.tests.unit import base + +FAKE = { + 'name': 'CUSTOM_FPGA', +} + + +class TestResourceClass(base.TestCase): + + def test_basic(self): + sot = rc.ResourceClass() + self.assertEqual(None, sot.resource_key) + self.assertEqual('resource_classes', sot.resources_key) + self.assertEqual('/resource_classes', sot.base_path) + self.assertTrue(sot.allow_create) + self.assertTrue(sot.allow_fetch) + self.assertTrue(sot.allow_commit) + self.assertTrue(sot.allow_delete) + self.assertTrue(sot.allow_list) + self.assertFalse(sot.allow_patch) + + self.assertDictEqual( + {'limit': 'limit', 'marker': 'marker'}, + sot._query_mapping._mapping) + + def test_make_it(self): + sot = rc.ResourceClass(**FAKE) + self.assertEqual(FAKE['name'], sot.id) + self.assertEqual(FAKE['name'], sot.name) diff --git a/releasenotes/notes/add-placement-resource-class-e1c644d978b886bc.yaml b/releasenotes/notes/add-placement-resource-class-e1c644d978b886bc.yaml new file mode 100644 index 000000000..c3631abde --- /dev/null +++ b/releasenotes/notes/add-placement-resource-class-e1c644d978b886bc.yaml @@ -0,0 +1,4 @@ +--- +features: + - | + Added support for the ``ResourceClass`` Placement resource.