Add a Usage and UsageList object
These encapsulate the Usage information associated with the inventories of a resource provider. A single UsageList holds all the Usage for all resource classes provided by that provider. Just resource class and usage. Putting this in place to make further headway on the placement API, which needs to represent Usage info in this form. This change intentionally tries to keep the new objects relatively lightweight. Partially-Implements: blueprint generic-resource-pools Change-Id: Ie5eddae4d0cb51bccc815a932a3eefcd5d9ea687
This commit is contained in:
parent
83d2eeff77
commit
51afe54246
@ -14,6 +14,7 @@ import six
|
|||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
from sqlalchemy.orm import contains_eager
|
from sqlalchemy.orm import contains_eager
|
||||||
|
from sqlalchemy import sql
|
||||||
|
|
||||||
from nova.db.sqlalchemy import api as db_api
|
from nova.db.sqlalchemy import api as db_api
|
||||||
from nova.db.sqlalchemy import api_models as models
|
from nova.db.sqlalchemy import api_models as models
|
||||||
@ -626,3 +627,63 @@ class AllocationList(base.ObjectListBase, base.NovaObject):
|
|||||||
context, rp_uuid)
|
context, rp_uuid)
|
||||||
return base.obj_make_list(
|
return base.obj_make_list(
|
||||||
context, cls(context), objects.Allocation, db_allocation_list)
|
context, cls(context), objects.Allocation, db_allocation_list)
|
||||||
|
|
||||||
|
|
||||||
|
@base.NovaObjectRegistry.register
|
||||||
|
class Usage(base.NovaObject):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
|
fields = {
|
||||||
|
'resource_class': fields.ResourceClassField(read_only=True),
|
||||||
|
'usage': fields.NonNegativeIntegerField(),
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _from_db_object(context, target, source):
|
||||||
|
for field in target.fields:
|
||||||
|
if field not in ('resource_class'):
|
||||||
|
setattr(target, field, source[field])
|
||||||
|
|
||||||
|
if 'resource_class' not in target:
|
||||||
|
target.resource_class = (
|
||||||
|
target.fields['resource_class'].from_index(
|
||||||
|
source['resource_class_id']))
|
||||||
|
|
||||||
|
target._context = context
|
||||||
|
target.obj_reset_changes()
|
||||||
|
return target
|
||||||
|
|
||||||
|
|
||||||
|
@base.NovaObjectRegistry.register
|
||||||
|
class UsageList(base.ObjectListBase, base.NovaObject):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
|
fields = {
|
||||||
|
'objects': fields.ListOfObjectsField('Usage'),
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@db_api.placement_context_manager.reader
|
||||||
|
def _get_all_by_resource_provider_uuid(context, rp_uuid):
|
||||||
|
query = (context.session.query(models.Inventory.resource_class_id,
|
||||||
|
func.coalesce(func.sum(models.Allocation.used), 0))
|
||||||
|
.join(models.ResourceProvider,
|
||||||
|
models.Inventory.resource_provider_id ==
|
||||||
|
models.ResourceProvider.id)
|
||||||
|
.outerjoin(models.Allocation,
|
||||||
|
sql.and_(models.Inventory.resource_provider_id ==
|
||||||
|
models.Allocation.resource_provider_id,
|
||||||
|
models.Inventory.resource_class_id ==
|
||||||
|
models.Allocation.resource_class_id))
|
||||||
|
.filter(models.ResourceProvider.uuid == rp_uuid)
|
||||||
|
.group_by(models.Inventory.resource_class_id))
|
||||||
|
result = [dict(resource_class_id=item[0], usage=item[1])
|
||||||
|
for item in query.all()]
|
||||||
|
return result
|
||||||
|
|
||||||
|
@base.remotable_classmethod
|
||||||
|
def get_all_by_resource_provider_uuid(cls, context, rp_uuid):
|
||||||
|
usage_list = cls._get_all_by_resource_provider_uuid(context, rp_uuid)
|
||||||
|
return base.obj_make_list(context, cls(context), Usage, usage_list)
|
||||||
|
@ -419,14 +419,7 @@ class ResourceProviderTestCase(ResourceProviderBaseCase):
|
|||||||
% rp.uuid, str(error))
|
% rp.uuid, str(error))
|
||||||
|
|
||||||
|
|
||||||
class ResourceProviderListTestCase(test.NoDBTestCase):
|
class ResourceProviderListTestCase(ResourceProviderBaseCase):
|
||||||
|
|
||||||
USES_DB_SELF = True
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(ResourceProviderListTestCase, self).setUp()
|
|
||||||
self.useFixture(fixtures.Database(database='placement'))
|
|
||||||
self.context = context.RequestContext('fake-user', 'fake-project')
|
|
||||||
|
|
||||||
def test_get_all_by_filters(self):
|
def test_get_all_by_filters(self):
|
||||||
for rp_i in ['1', '2']:
|
for rp_i in ['1', '2']:
|
||||||
@ -567,3 +560,70 @@ class TestAllocation(ResourceProviderBaseCase):
|
|||||||
self.assertNotIn(fields.ResourceClass.IPV4_ADDRESS,
|
self.assertNotIn(fields.ResourceClass.IPV4_ADDRESS,
|
||||||
[allocation.resource_class
|
[allocation.resource_class
|
||||||
for allocation in allocations])
|
for allocation in allocations])
|
||||||
|
|
||||||
|
|
||||||
|
class UsageListTestCase(ResourceProviderBaseCase):
|
||||||
|
|
||||||
|
def test_get_all_null(self):
|
||||||
|
for uuid in [uuidsentinel.rp_uuid_1, uuidsentinel.rp_uuid_2]:
|
||||||
|
rp = objects.ResourceProvider(self.context, name=uuid, uuid=uuid)
|
||||||
|
rp.create()
|
||||||
|
|
||||||
|
usage_list = objects.UsageList.get_all_by_resource_provider_uuid(
|
||||||
|
self.context, uuidsentinel.rp_uuid_1)
|
||||||
|
self.assertEqual(0, len(usage_list))
|
||||||
|
|
||||||
|
def test_get_all_one_allocation(self):
|
||||||
|
db_rp, _ = self._make_allocation(rp_uuid=uuidsentinel.rp_uuid)
|
||||||
|
inv = objects.Inventory(resource_provider=db_rp,
|
||||||
|
resource_class=fields.ResourceClass.DISK_GB,
|
||||||
|
total=1024)
|
||||||
|
inv.obj_set_defaults()
|
||||||
|
inv_list = objects.InventoryList(objects=[inv])
|
||||||
|
db_rp.set_inventory(inv_list)
|
||||||
|
|
||||||
|
usage_list = objects.UsageList.get_all_by_resource_provider_uuid(
|
||||||
|
self.context, db_rp.uuid)
|
||||||
|
self.assertEqual(1, len(usage_list))
|
||||||
|
self.assertEqual(2, usage_list[0].usage)
|
||||||
|
self.assertEqual(fields.ResourceClass.DISK_GB,
|
||||||
|
usage_list[0].resource_class)
|
||||||
|
|
||||||
|
def test_get_inventory_no_allocation(self):
|
||||||
|
db_rp = objects.ResourceProvider(self.context,
|
||||||
|
name=uuidsentinel.rp_no_inv,
|
||||||
|
uuid=uuidsentinel.rp_no_inv)
|
||||||
|
db_rp.create()
|
||||||
|
inv = objects.Inventory(resource_provider=db_rp,
|
||||||
|
resource_class=fields.ResourceClass.DISK_GB,
|
||||||
|
total=1024)
|
||||||
|
inv.obj_set_defaults()
|
||||||
|
inv_list = objects.InventoryList(objects=[inv])
|
||||||
|
db_rp.set_inventory(inv_list)
|
||||||
|
|
||||||
|
usage_list = objects.UsageList.get_all_by_resource_provider_uuid(
|
||||||
|
self.context, db_rp.uuid)
|
||||||
|
self.assertEqual(1, len(usage_list))
|
||||||
|
self.assertEqual(0, usage_list[0].usage)
|
||||||
|
self.assertEqual(fields.ResourceClass.DISK_GB,
|
||||||
|
usage_list[0].resource_class)
|
||||||
|
|
||||||
|
def test_get_all_multiple_inv(self):
|
||||||
|
db_rp = objects.ResourceProvider(self.context,
|
||||||
|
name=uuidsentinel.rp_no_inv,
|
||||||
|
uuid=uuidsentinel.rp_no_inv)
|
||||||
|
db_rp.create()
|
||||||
|
disk_inv = objects.Inventory(
|
||||||
|
resource_provider=db_rp,
|
||||||
|
resource_class=fields.ResourceClass.DISK_GB, total=1024)
|
||||||
|
disk_inv.obj_set_defaults()
|
||||||
|
vcpu_inv = objects.Inventory(
|
||||||
|
resource_provider=db_rp,
|
||||||
|
resource_class=fields.ResourceClass.VCPU, total=24)
|
||||||
|
vcpu_inv.obj_set_defaults()
|
||||||
|
inv_list = objects.InventoryList(objects=[disk_inv, vcpu_inv])
|
||||||
|
db_rp.set_inventory(inv_list)
|
||||||
|
|
||||||
|
usage_list = objects.UsageList.get_all_by_resource_provider_uuid(
|
||||||
|
self.context, db_rp.uuid)
|
||||||
|
self.assertEqual(2, len(usage_list))
|
||||||
|
@ -1195,6 +1195,8 @@ object_data = {
|
|||||||
'TaskLogList': '1.0-cc8cce1af8a283b9d28b55fcd682e777',
|
'TaskLogList': '1.0-cc8cce1af8a283b9d28b55fcd682e777',
|
||||||
'Tag': '1.1-8b8d7d5b48887651a0e01241672e2963',
|
'Tag': '1.1-8b8d7d5b48887651a0e01241672e2963',
|
||||||
'TagList': '1.1-55231bdb671ecf7641d6a2e9109b5d8e',
|
'TagList': '1.1-55231bdb671ecf7641d6a2e9109b5d8e',
|
||||||
|
'Usage': '1.0-b78f18c3577a38e7a033e46a9725b09b',
|
||||||
|
'UsageList': '1.0-de53f0fd078c27cc1d43400f4e8bcef8',
|
||||||
'USBDeviceBus': '1.0-e4c7dd6032e46cd74b027df5eb2d4750',
|
'USBDeviceBus': '1.0-e4c7dd6032e46cd74b027df5eb2d4750',
|
||||||
'VirtCPUFeature': '1.0-3310718d8c72309259a6e39bdefe83ee',
|
'VirtCPUFeature': '1.0-3310718d8c72309259a6e39bdefe83ee',
|
||||||
'VirtCPUModel': '1.0-6a5cc9f322729fc70ddc6733bacd57d3',
|
'VirtCPUModel': '1.0-6a5cc9f322729fc70ddc6733bacd57d3',
|
||||||
|
Loading…
Reference in New Issue
Block a user