placement/placement/objects/inventory.py

104 lines
3.5 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.
import six
import sqlalchemy as sa
from placement.db.sqlalchemy import models
from placement import db_api
from placement import resource_class_cache as rc_cache
_INV_TBL = models.Inventory.__table__
class Inventory(object):
# kwargs included because some constructors pass resource_class_id
# but it is not used.
def __init__(self, id=None, resource_provider=None, resource_class=None,
total=None, reserved=0, min_unit=1, max_unit=1, step_size=1,
allocation_ratio=1.0, updated_at=None, created_at=None,
**kwargs):
self.id = id
self.resource_provider = resource_provider
self.resource_class = resource_class
self.total = total
self.reserved = reserved
self.min_unit = min_unit
self.max_unit = max_unit
self.step_size = step_size
self.allocation_ratio = allocation_ratio
self.updated_at = updated_at
self.created_at = created_at
@property
def capacity(self):
"""Inventory capacity, adjusted by allocation_ratio."""
return int((self.total - self.reserved) * self.allocation_ratio)
def find(inventories, res_class):
"""Return the inventory record from the list of Inventory records that
matches the supplied resource class, or None.
:param inventories: A list of Inventory objects.
:param res_class: An integer or string representing a resource
class. If the value is a string, the method first
looks up the resource class identifier from the
string.
"""
if not isinstance(res_class, six.string_types):
raise ValueError
for inv_rec in inventories:
if inv_rec.resource_class == res_class:
return inv_rec
def get_all_by_resource_provider(context, rp):
db_inv = _get_inventory_by_provider_id(context, rp.id)
# Build up a list of Inventory objects, setting the Inventory object
# fields to the same-named database record field we got from
# _get_inventory_by_provider_id(). We already have the ResourceProvider
# object so we just pass that object to the Inventory object
# constructor as-is
inv_list = [
Inventory(
resource_provider=rp,
resource_class=rc_cache.RC_CACHE.string_from_id(
rec['resource_class_id']),
**rec)
for rec in db_inv
]
return inv_list
@db_api.placement_context_manager.reader
def _get_inventory_by_provider_id(ctx, rp_id):
inv = sa.alias(_INV_TBL, name="i")
cols = [
inv.c.resource_class_id,
inv.c.total,
inv.c.reserved,
inv.c.min_unit,
inv.c.max_unit,
inv.c.step_size,
inv.c.allocation_ratio,
inv.c.updated_at,
inv.c.created_at,
]
sel = sa.select(cols)
sel = sel.where(inv.c.resource_provider_id == rp_id)
return [dict(r) for r in ctx.session.execute(sel)]