placement: Add support for resource provider inventories
Unlike resource classes, this one is not easy. The list operation is particularly tricky: unlike most OpenStack APIs that returns a list of objects, the resource provider inventory list operation returns an object with resource class as the keys and the inventory details as the values. Put another way, we see: { "MEMORY_MB": { ... }, "VCPU": { ... }, ... } instead of the more typical: [ { "resource_class": "MEMORY_MB", ... }, { "resource_class": "VCPU", ... }, ... ] This need special handling code, namely a reimplementation of the 'list' class method. In addition, updating inventory requires providing 'resource_provider_generation'. This should match the current server value of this field, but by setting this SDK assumes the field is unchanged and doesn't include it in the list of "dirty" attributes. This requires manually adding the 'resource_provider_generation' value to the list of 'dirty' fields before the 'commit' operation. Change-Id: I5ea5d0a477147e1a4e30b428f17b44807253deaa Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
parent
69fea357b5
commit
15207b2070
@ -27,3 +27,14 @@ Resource Providers
|
||||
:members: create_resource_provider, update_resource_provider,
|
||||
delete_resource_provider, get_resource_provider,
|
||||
find_resource_provider, resource_providers
|
||||
|
||||
Resource Provider Inventories
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autoclass:: openstack.placement.v1._proxy.Proxy
|
||||
:noindex:
|
||||
:members: create_resource_provider_inventory,
|
||||
update_resource_provider_inventory,
|
||||
delete_resource_provider_inventory,
|
||||
get_resource_provider_inventory,
|
||||
resource_provider_inventories
|
||||
|
@ -6,3 +6,4 @@ Placement v1 Resources
|
||||
|
||||
v1/resource_class
|
||||
v1/resource_provider
|
||||
v1/resource_provider_inventory
|
||||
|
@ -0,0 +1,13 @@
|
||||
openstack.placement.v1.resource_provider_inventory
|
||||
==================================================
|
||||
|
||||
.. automodule:: openstack.placement.v1.resource_provider_inventory
|
||||
|
||||
The ResourceProviderInventory Class
|
||||
-----------------------------------
|
||||
|
||||
The ``ResourceProviderInventory`` class inherits from
|
||||
:class:`~openstack.resource.Resource`.
|
||||
|
||||
.. autoclass:: openstack.placement.v1.resource_provider_inventory.ResourceProviderInventory
|
||||
:members:
|
@ -12,7 +12,11 @@
|
||||
|
||||
from openstack.placement.v1 import resource_class as _resource_class
|
||||
from openstack.placement.v1 import resource_provider as _resource_provider
|
||||
from openstack.placement.v1 import (
|
||||
resource_provider_inventory as _resource_provider_inventory,
|
||||
)
|
||||
from openstack import proxy
|
||||
from openstack import resource
|
||||
|
||||
|
||||
class Proxy(proxy.Proxy):
|
||||
@ -204,3 +208,160 @@ class Proxy(proxy.Proxy):
|
||||
:returns: A generator of resource provider instances.
|
||||
"""
|
||||
return self._list(_resource_provider.ResourceProvider, **query)
|
||||
|
||||
# resource provider inventories
|
||||
|
||||
def create_resource_provider_inventory(
|
||||
self,
|
||||
resource_provider,
|
||||
resource_class,
|
||||
*,
|
||||
total,
|
||||
**attrs,
|
||||
):
|
||||
"""Create a new resource provider inventory from attributes
|
||||
|
||||
:param resource_provider: Either the ID of a resource provider or a
|
||||
:class:`~openstack.placement.v1.resource_provider.ResourceProvider`
|
||||
instance.
|
||||
:param total: The actual amount of the resource that the provider can
|
||||
accommodate.
|
||||
:param attrs: Keyword arguments which will be used to create a
|
||||
:class:`~openstack.placement.v1.resource_provider_inventory.ResourceProviderInventory`,
|
||||
comprised of the properties on the ResourceProviderInventory class.
|
||||
|
||||
:returns: The results of resource provider inventory creation
|
||||
:rtype: :class:`~openstack.placement.v1.resource_provider_inventory.ResourceProviderInventory`
|
||||
""" # noqa: E501
|
||||
resource_provider_id = resource.Resource._get_id(resource_provider)
|
||||
resource_class_name = resource.Resource._get_id(resource_class)
|
||||
return self._create(
|
||||
_resource_provider_inventory.ResourceProviderInventory,
|
||||
resource_provider_id=resource_provider_id,
|
||||
resource_class=resource_class_name,
|
||||
total=total,
|
||||
**attrs,
|
||||
)
|
||||
|
||||
def delete_resource_provider_inventory(
|
||||
self,
|
||||
resource_provider_inventory,
|
||||
resource_provider=None,
|
||||
ignore_missing=True,
|
||||
):
|
||||
"""Delete a resource provider inventory
|
||||
|
||||
:param resource_provider_inventory: The value can be either the ID of a
|
||||
resource provider or an
|
||||
:class:`~openstack.placement.v1.resource_provider_inventory.ResourceProviderInventory`,
|
||||
instance.
|
||||
:param resource_provider: Either the ID of a resource provider or a
|
||||
:class:`~openstack.placement.v1.resource_provider.ResourceProvider`
|
||||
instance. This value must be specified when
|
||||
``resource_provider_inventory`` is an ID.
|
||||
:param bool ignore_missing: When set to ``False``
|
||||
:class:`~openstack.exceptions.ResourceNotFound` will be raised when
|
||||
the resource provider inventory does not exist. When set to
|
||||
``True``, no exception will be set when attempting to delete a
|
||||
nonexistent resource provider inventory.
|
||||
|
||||
:returns: ``None``
|
||||
"""
|
||||
resource_provider_id = self._get_uri_attribute(
|
||||
resource_provider_inventory,
|
||||
resource_provider,
|
||||
'resource_provider_id',
|
||||
)
|
||||
self._delete(
|
||||
_resource_provider_inventory.ResourceProviderInventory,
|
||||
resource_provider_inventory,
|
||||
resource_provider_id=resource_provider_id,
|
||||
ignore_missing=ignore_missing,
|
||||
)
|
||||
|
||||
def update_resource_provider_inventory(
|
||||
self,
|
||||
resource_provider_inventory,
|
||||
resource_provider=None,
|
||||
*,
|
||||
resource_provider_generation=None,
|
||||
**attrs,
|
||||
):
|
||||
"""Update a resource provider's inventory
|
||||
|
||||
:param resource_provider_inventory: The value can be either the ID of a resource
|
||||
provider inventory or an
|
||||
:class:`~openstack.placement.v1.resource_provider_inventory.ResourceProviderInventory`,
|
||||
instance.
|
||||
:param resource_provider: Either the ID of a resource provider or a
|
||||
:class:`~openstack.placement.v1.resource_provider.ResourceProvider`
|
||||
instance. This value must be specified when
|
||||
``resource_provider_inventory`` is an ID.
|
||||
:attrs kwargs: The attributes to update on the resource provider inventory
|
||||
represented by ``resource_provider_inventory``.
|
||||
|
||||
:returns: The updated resource provider inventory
|
||||
:rtype: :class:`~openstack.placement.v1.resource_provider_inventory.ResourceProviderInventory`
|
||||
""" # noqa: E501
|
||||
resource_provider_id = self._get_uri_attribute(
|
||||
resource_provider_inventory,
|
||||
resource_provider,
|
||||
'resource_provider_id',
|
||||
)
|
||||
return self._update(
|
||||
_resource_provider_inventory.ResourceProviderInventory,
|
||||
resource_provider_inventory,
|
||||
resource_provider_id=resource_provider_id,
|
||||
resource_provider_generation=resource_provider_generation,
|
||||
**attrs,
|
||||
)
|
||||
|
||||
def get_resource_provider_inventory(
|
||||
self,
|
||||
resource_provider_inventory,
|
||||
resource_provider=None,
|
||||
):
|
||||
"""Get a single resource_provider_inventory
|
||||
|
||||
:param resource_provider_inventory: The value can be either the ID of a
|
||||
resource provider inventory or an
|
||||
:class:`~openstack.placement.v1.resource_provider_inventory.ResourceProviderInventory`,
|
||||
instance.
|
||||
:param resource_provider: Either the ID of a resource provider or a
|
||||
:class:`~openstack.placement.v1.resource_provider.ResourceProvider`
|
||||
instance. This value must be specified when
|
||||
``resource_provider_inventory`` is an ID.
|
||||
|
||||
:returns: An instance of
|
||||
:class:`~openstack.placement.v1.resource_provider_inventory.ResourceProviderInventory`
|
||||
:raises: :class:`~openstack.exceptions.ResourceNotFound` when no
|
||||
resource provider inventory matching the criteria could be found.
|
||||
"""
|
||||
resource_provider_id = self._get_uri_attribute(
|
||||
resource_provider_inventory,
|
||||
resource_provider,
|
||||
'resource_provider_id',
|
||||
)
|
||||
return self._get(
|
||||
_resource_provider_inventory.ResourceProviderInventory,
|
||||
resource_provider_inventory,
|
||||
resource_provider_id=resource_provider_id,
|
||||
)
|
||||
|
||||
def resource_provider_inventories(self, resource_provider, **query):
|
||||
"""Retrieve a generator of resource provider inventories
|
||||
|
||||
:param resource_provider: Either the ID of a resource provider or a
|
||||
:class:`~openstack.placement.v1.resource_provider.ResourceProvider`
|
||||
instance.
|
||||
:param query: Optional query parameters to be sent to limit
|
||||
the resources being returned.
|
||||
|
||||
:returns: A generator of resource provider inventory instances.
|
||||
"""
|
||||
resource_provider_id = resource.Resource._get_id(resource_provider)
|
||||
return self._list(
|
||||
_resource_provider_inventory.ResourceProviderInventory,
|
||||
resource_provider_id=resource_provider_id,
|
||||
**query,
|
||||
)
|
||||
|
193
openstack/placement/v1/resource_provider_inventory.py
Normal file
193
openstack/placement/v1/resource_provider_inventory.py
Normal file
@ -0,0 +1,193 @@
|
||||
# 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 exceptions
|
||||
from openstack import resource
|
||||
|
||||
|
||||
class ResourceProviderInventory(resource.Resource):
|
||||
resource_key = None
|
||||
resources_key = None
|
||||
base_path = '/resource_providers/%(resource_provider_id)s/inventories'
|
||||
|
||||
_query_mapping = {}
|
||||
|
||||
# Capabilities
|
||||
|
||||
allow_create = True
|
||||
allow_fetch = True
|
||||
allow_commit = True
|
||||
allow_delete = True
|
||||
allow_list = True
|
||||
|
||||
# Properties
|
||||
|
||||
#: The UUID of a resource provider.
|
||||
resource_provider_id = resource.URI('resource_provider_id')
|
||||
#: The name of the resource class.
|
||||
resource_class = resource.Body('resource_class', alternate_id=True)
|
||||
#: A consistent view marker that assists with the management of concurrent
|
||||
#: resource provider updates.
|
||||
resource_provider_generation = resource.Body(
|
||||
'resource_provider_generation',
|
||||
type=int,
|
||||
)
|
||||
|
||||
#: It is used in determining whether consumption of the resource of the
|
||||
#: provider can exceed physical constraints.
|
||||
allocation_ratio = resource.Body('allocation_ratio', type=float)
|
||||
#: A maximum amount any single allocation against an inventory can have.
|
||||
max_unit = resource.Body('max_unit', type=int)
|
||||
#: A minimum amount any single allocation against an inventory can have.
|
||||
min_unit = resource.Body('min_unit', type=int)
|
||||
#: The amount of the resource a provider has reserved for its own use.
|
||||
reserved = resource.Body('reserved', type=int)
|
||||
#: A representation of the divisible amount of the resource that may be
|
||||
#: requested. For example, step_size = 5 means that only values divisible
|
||||
#: by 5 (5, 10, 15, etc.) can be requested.
|
||||
step_size = resource.Body('step_size', type=int)
|
||||
#: The actual amount of the resource that the provider can accommodate.
|
||||
total = resource.Body('total', type=int)
|
||||
|
||||
def commit(
|
||||
self,
|
||||
session,
|
||||
prepend_key=True,
|
||||
has_body=True,
|
||||
retry_on_conflict=None,
|
||||
base_path=None,
|
||||
*,
|
||||
microversion=None,
|
||||
**kwargs,
|
||||
):
|
||||
# resource_provider_generation must always be provided on update, but
|
||||
# it will appear to be identical (by design) so we strip it. Prevent
|
||||
# tihs happening.
|
||||
self._body._dirty.add('resource_provider_generation')
|
||||
return super().commit(
|
||||
session,
|
||||
prepend_key=prepend_key,
|
||||
has_body=has_body,
|
||||
retry_on_conflict=retry_on_conflict,
|
||||
base_path=base_path,
|
||||
microversion=microversion,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
# TODO(stephenfin): It would be nicer if we could do this in Resource
|
||||
# itself since the logic is also found elsewhere (e.g.
|
||||
# openstack.identity.v2.extension.Extension) but that code is a bit of a
|
||||
# rat's nest right now and needs a spring clean
|
||||
@classmethod
|
||||
def list(
|
||||
cls,
|
||||
session,
|
||||
paginated=True,
|
||||
base_path=None,
|
||||
allow_unknown_params=False,
|
||||
*,
|
||||
microversion=None,
|
||||
**params,
|
||||
):
|
||||
"""This method is a generator which yields resource objects.
|
||||
|
||||
A re-implementation of :meth:`~openstack.resource.Resource.list` that
|
||||
handles placement's single, unpaginated list implementation.
|
||||
|
||||
Refer to :meth:`~openstack.resource.Resource.list` for full
|
||||
documentation including parameter, exception and return type
|
||||
documentation.
|
||||
"""
|
||||
session = cls._get_session(session)
|
||||
|
||||
if microversion is None:
|
||||
microversion = cls._get_microversion(session, action='list')
|
||||
|
||||
if base_path is None:
|
||||
base_path = cls.base_path
|
||||
|
||||
# There is no server-side filtering, only client-side
|
||||
client_filters = {}
|
||||
# Gather query parameters which are not supported by the server
|
||||
for k, v in params.items():
|
||||
if (
|
||||
# Known attr
|
||||
hasattr(cls, k)
|
||||
# Is real attr property
|
||||
and isinstance(getattr(cls, k), resource.Body)
|
||||
# not included in the query_params
|
||||
and k not in cls._query_mapping._mapping.keys()
|
||||
):
|
||||
client_filters[k] = v
|
||||
|
||||
uri = base_path % params
|
||||
uri_params = {}
|
||||
|
||||
for k, v in params.items():
|
||||
# We need to gather URI parts to set them on the resource later
|
||||
if hasattr(cls, k) and isinstance(getattr(cls, k), resource.URI):
|
||||
uri_params[k] = v
|
||||
|
||||
def _dict_filter(f, d):
|
||||
"""Dict param based filtering"""
|
||||
if not d:
|
||||
return False
|
||||
for key in f.keys():
|
||||
if isinstance(f[key], dict):
|
||||
if not _dict_filter(f[key], d.get(key, None)):
|
||||
return False
|
||||
elif d.get(key, None) != f[key]:
|
||||
return False
|
||||
return True
|
||||
|
||||
response = session.get(
|
||||
uri,
|
||||
headers={"Accept": "application/json"},
|
||||
params={},
|
||||
microversion=microversion,
|
||||
)
|
||||
exceptions.raise_from_response(response)
|
||||
data = response.json()
|
||||
|
||||
for resource_class, resource_data in data['inventories'].items():
|
||||
resource_inventory = {
|
||||
'resource_class': resource_class,
|
||||
'resource_provider_generation': data[
|
||||
'resource_provider_generation'
|
||||
], # noqa: E501
|
||||
**resource_data,
|
||||
**uri_params,
|
||||
}
|
||||
value = cls.existing(
|
||||
microversion=microversion,
|
||||
connection=session._get_connection(),
|
||||
**resource_inventory,
|
||||
)
|
||||
|
||||
filters_matched = True
|
||||
# Iterate over client filters and return only if matching
|
||||
for key in client_filters.keys():
|
||||
if isinstance(client_filters[key], dict):
|
||||
if not _dict_filter(
|
||||
client_filters[key],
|
||||
value.get(key, None),
|
||||
):
|
||||
filters_matched = False
|
||||
break
|
||||
elif value.get(key, None) != client_filters[key]:
|
||||
filters_matched = False
|
||||
break
|
||||
|
||||
if filters_matched:
|
||||
yield value
|
||||
|
||||
return None
|
@ -350,7 +350,7 @@ class QueryParameters:
|
||||
client-side parameter name or server side name.
|
||||
:param base_path: Formatted python string of the base url path for
|
||||
the resource.
|
||||
: param allow_unknown_params: Exclude query params not known by the
|
||||
:param allow_unknown_params: Exclude query params not known by the
|
||||
resource.
|
||||
|
||||
:returns: Filtered collection of the supported QueryParameters
|
||||
@ -2018,17 +2018,19 @@ class Resource(dict):
|
||||
raise exceptions.MethodNotSupported(cls, 'list')
|
||||
|
||||
session = cls._get_session(session)
|
||||
|
||||
if microversion is None:
|
||||
microversion = cls._get_microversion(session, action='list')
|
||||
|
||||
if base_path is None:
|
||||
base_path = cls.base_path
|
||||
|
||||
api_filters = cls._query_mapping._validate(
|
||||
params,
|
||||
base_path=base_path,
|
||||
allow_unknown_params=True,
|
||||
)
|
||||
client_filters = dict()
|
||||
client_filters = {}
|
||||
# Gather query parameters which are not supported by the server
|
||||
for k, v in params.items():
|
||||
if (
|
||||
|
@ -0,0 +1,163 @@
|
||||
# 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.
|
||||
|
||||
import uuid
|
||||
|
||||
from openstack.placement.v1 import resource_class as _resource_class
|
||||
from openstack.placement.v1 import resource_provider as _resource_provider
|
||||
from openstack.placement.v1 import (
|
||||
resource_provider_inventory as _resource_provider_inventory,
|
||||
)
|
||||
from openstack.tests.functional import base
|
||||
|
||||
|
||||
class TestResourceProviderInventory(base.BaseFunctionalTest):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
if not self.operator_cloud.has_service('placement'):
|
||||
self.skipTest('placement service not supported by cloud')
|
||||
|
||||
self.resource_provider_name = self.getUniqueString()
|
||||
self.resource_class_name = f'CUSTOM_{uuid.uuid4().hex.upper()}'
|
||||
|
||||
resource_class = self.operator_cloud.placement.create_resource_class(
|
||||
name=self.resource_class_name,
|
||||
)
|
||||
self.assertIsInstance(resource_class, _resource_class.ResourceClass)
|
||||
self.assertEqual(self.resource_class_name, resource_class.name)
|
||||
|
||||
resource_provider = (
|
||||
self.operator_cloud.placement.create_resource_provider(
|
||||
name=self.resource_provider_name,
|
||||
)
|
||||
)
|
||||
self.assertIsInstance(
|
||||
resource_provider,
|
||||
_resource_provider.ResourceProvider,
|
||||
)
|
||||
self.assertEqual(self.resource_provider_name, resource_provider.name)
|
||||
|
||||
self.resource_provider = resource_provider
|
||||
self.resource_class = resource_class
|
||||
|
||||
def tearDown(self):
|
||||
self.operator_cloud.placement.delete_resource_provider(
|
||||
self.resource_provider,
|
||||
)
|
||||
self.operator_cloud.placement.delete_resource_class(
|
||||
self.resource_class,
|
||||
)
|
||||
super().tearDown()
|
||||
|
||||
def test_resource_provider_inventory(self):
|
||||
# create the resource provider inventory
|
||||
|
||||
resource_provider_inventory = (
|
||||
self.operator_cloud.placement.create_resource_provider_inventory(
|
||||
self.resource_provider,
|
||||
resource_class=self.resource_class,
|
||||
total=10,
|
||||
step_size=1,
|
||||
)
|
||||
)
|
||||
self.assertIsInstance(
|
||||
resource_provider_inventory,
|
||||
_resource_provider_inventory.ResourceProviderInventory,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.resource_class.name,
|
||||
resource_provider_inventory.resource_class,
|
||||
)
|
||||
self.assertEqual(10, resource_provider_inventory.total)
|
||||
|
||||
# list all resource provider inventories (there should only be one)
|
||||
|
||||
resource_provider_inventories = list(
|
||||
self.operator_cloud.placement.resource_provider_inventories(
|
||||
self.resource_provider
|
||||
)
|
||||
)
|
||||
self.assertIsInstance(
|
||||
resource_provider_inventories[0],
|
||||
_resource_provider_inventory.ResourceProviderInventory,
|
||||
)
|
||||
self.assertIn(
|
||||
self.resource_class.name,
|
||||
{rpi.id for rpi in resource_provider_inventories},
|
||||
)
|
||||
|
||||
# update the resource provider inventory
|
||||
|
||||
resource_provider_inventory = self.operator_cloud.placement.update_resource_provider_inventory(
|
||||
resource_provider_inventory,
|
||||
total=20,
|
||||
resource_provider_generation=resource_provider_inventory.resource_provider_generation,
|
||||
)
|
||||
self.assertIsInstance(
|
||||
resource_provider_inventory,
|
||||
_resource_provider_inventory.ResourceProviderInventory,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.resource_class.name,
|
||||
resource_provider_inventory.id,
|
||||
)
|
||||
self.assertEqual(20, resource_provider_inventory.total)
|
||||
|
||||
# retrieve details of the (updated) resource provider inventory
|
||||
|
||||
resource_provider_inventory = (
|
||||
self.operator_cloud.placement.get_resource_provider_inventory(
|
||||
resource_provider_inventory,
|
||||
)
|
||||
)
|
||||
self.assertIsInstance(
|
||||
resource_provider_inventory,
|
||||
_resource_provider_inventory.ResourceProviderInventory,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.resource_class.name,
|
||||
resource_provider_inventory.id,
|
||||
)
|
||||
self.assertEqual(20, resource_provider_inventory.total)
|
||||
|
||||
# retrieve details of the resource provider inventory using IDs
|
||||
# (requires us to provide the resource provider also)
|
||||
|
||||
resource_provider_inventory = (
|
||||
self.operator_cloud.placement.get_resource_provider_inventory(
|
||||
resource_provider_inventory.id,
|
||||
self.resource_provider,
|
||||
)
|
||||
)
|
||||
self.assertIsInstance(
|
||||
resource_provider_inventory,
|
||||
_resource_provider_inventory.ResourceProviderInventory,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.resource_class.name,
|
||||
resource_provider_inventory.id,
|
||||
)
|
||||
self.assertEqual(20, resource_provider_inventory.total)
|
||||
|
||||
# (no find_resource_provider_inventory method)
|
||||
|
||||
# delete the resource provider inventory
|
||||
|
||||
result = (
|
||||
self.operator_cloud.placement.delete_resource_provider_inventory(
|
||||
resource_provider_inventory,
|
||||
self.resource_provider,
|
||||
ignore_missing=False,
|
||||
)
|
||||
)
|
||||
self.assertIsNone(result)
|
@ -13,6 +13,7 @@
|
||||
from openstack.placement.v1 import _proxy
|
||||
from openstack.placement.v1 import resource_class
|
||||
from openstack.placement.v1 import resource_provider
|
||||
from openstack.placement.v1 import resource_provider_inventory
|
||||
from openstack.tests.unit import test_proxy_base as test_proxy_base
|
||||
|
||||
|
||||
@ -22,8 +23,7 @@ class TestPlacementProxy(test_proxy_base.TestProxyBase):
|
||||
self.proxy = _proxy.Proxy(self.session)
|
||||
|
||||
|
||||
# resource classes
|
||||
class TestPlacementResourceClass:
|
||||
class TestPlacementResourceClass(TestPlacementProxy):
|
||||
def test_resource_class_create(self):
|
||||
self.verify_create(
|
||||
self.proxy.create_resource_class,
|
||||
@ -57,8 +57,7 @@ class TestPlacementResourceClass:
|
||||
)
|
||||
|
||||
|
||||
# resource providers
|
||||
class TestPlacementResourceProvider:
|
||||
class TestPlacementResourceProvider(TestPlacementProxy):
|
||||
def test_resource_provider_create(self):
|
||||
self.verify_create(
|
||||
self.proxy.create_resource_provider,
|
||||
@ -90,3 +89,60 @@ class TestPlacementResourceProvider:
|
||||
self.proxy.resource_providers,
|
||||
resource_provider.ResourceProvider,
|
||||
)
|
||||
|
||||
|
||||
class TestPlacementResourceProviderInventory(TestPlacementProxy):
|
||||
def test_resource_provider_inventory_create(self):
|
||||
self.verify_create(
|
||||
self.proxy.create_resource_provider_inventory,
|
||||
resource_provider_inventory.ResourceProviderInventory,
|
||||
method_kwargs={
|
||||
'resource_provider': 'test_id',
|
||||
'resource_class': 'CUSTOM_FOO',
|
||||
'total': 20,
|
||||
},
|
||||
expected_kwargs={
|
||||
'resource_provider_id': 'test_id',
|
||||
'resource_class': 'CUSTOM_FOO',
|
||||
'total': 20,
|
||||
},
|
||||
)
|
||||
|
||||
def test_resource_provider_inventory_delete(self):
|
||||
self.verify_delete(
|
||||
self.proxy.delete_resource_provider_inventory,
|
||||
resource_provider_inventory.ResourceProviderInventory,
|
||||
ignore_missing=False,
|
||||
method_kwargs={'resource_provider': 'test_id'},
|
||||
expected_kwargs={'resource_provider_id': 'test_id'},
|
||||
)
|
||||
|
||||
def test_resource_provider_inventory_update(self):
|
||||
self.verify_update(
|
||||
self.proxy.update_resource_provider_inventory,
|
||||
resource_provider_inventory.ResourceProviderInventory,
|
||||
method_kwargs={
|
||||
'resource_provider': 'test_id',
|
||||
'resource_provider_generation': 1,
|
||||
},
|
||||
expected_kwargs={
|
||||
'resource_provider_id': 'test_id',
|
||||
'resource_provider_generation': 1,
|
||||
},
|
||||
)
|
||||
|
||||
def test_resource_provider_inventory_get(self):
|
||||
self.verify_get(
|
||||
self.proxy.get_resource_provider_inventory,
|
||||
resource_provider_inventory.ResourceProviderInventory,
|
||||
method_kwargs={'resource_provider': 'test_id'},
|
||||
expected_kwargs={'resource_provider_id': 'test_id'},
|
||||
)
|
||||
|
||||
def test_resource_provider_inventories(self):
|
||||
self.verify_list(
|
||||
self.proxy.resource_provider_inventories,
|
||||
resource_provider_inventory.ResourceProviderInventory,
|
||||
method_kwargs={'resource_provider': 'test_id'},
|
||||
expected_kwargs={'resource_provider_id': 'test_id'},
|
||||
)
|
||||
|
@ -0,0 +1,51 @@
|
||||
# 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_provider_inventory
|
||||
from openstack.tests.unit import base
|
||||
|
||||
FAKE = {
|
||||
'allocation_ratio': 1.0,
|
||||
'max_unit': 35,
|
||||
'min_unit': 1,
|
||||
'reserved': 0,
|
||||
'step_size': 1,
|
||||
'total': 35,
|
||||
}
|
||||
|
||||
|
||||
class TestResourceProviderInventory(base.TestCase):
|
||||
def test_basic(self):
|
||||
sot = resource_provider_inventory.ResourceProviderInventory()
|
||||
self.assertIsNone(sot.resource_key)
|
||||
self.assertIsNone(sot.resources_key)
|
||||
self.assertEqual(
|
||||
'/resource_providers/%(resource_provider_id)s/inventories',
|
||||
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({}, sot._query_mapping)
|
||||
|
||||
def test_make_it(self):
|
||||
sot = resource_provider_inventory.ResourceProviderInventory(**FAKE)
|
||||
self.assertEqual(FAKE['allocation_ratio'], sot.allocation_ratio)
|
||||
self.assertEqual(FAKE['max_unit'], sot.max_unit)
|
||||
self.assertEqual(FAKE['min_unit'], sot.min_unit)
|
||||
self.assertEqual(FAKE['reserved'], sot.reserved)
|
||||
self.assertEqual(FAKE['step_size'], sot.step_size)
|
||||
self.assertEqual(FAKE['total'], sot.total)
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added support for the ``ResourceProviderInventory`` Placement resource.
|
Loading…
x
Reference in New Issue
Block a user