openstacksdk/openstack/placement/v1/resource_provider_inventory.py

196 lines
6.8 KiB
Python

# 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 = resource.QueryParameters(
include_pagination_defaults=False
)
# 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