Merge "Add get_counts() to InstanceMappingList"
This commit is contained in:
commit
22ad5a5709
|
@ -17,6 +17,7 @@ from oslo_utils import versionutils
|
||||||
import six
|
import six
|
||||||
from sqlalchemy.orm import joinedload
|
from sqlalchemy.orm import joinedload
|
||||||
from sqlalchemy.sql import false
|
from sqlalchemy.sql import false
|
||||||
|
from sqlalchemy.sql import func
|
||||||
from sqlalchemy.sql import or_
|
from sqlalchemy.sql import or_
|
||||||
|
|
||||||
from nova import context as nova_context
|
from nova import context as nova_context
|
||||||
|
@ -294,7 +295,8 @@ class InstanceMappingList(base.ObjectListBase, base.NovaObject):
|
||||||
# Version 1.0: Initial version
|
# Version 1.0: Initial version
|
||||||
# Version 1.1: Added get_by_cell_id method.
|
# Version 1.1: Added get_by_cell_id method.
|
||||||
# Version 1.2: Added get_by_instance_uuids method
|
# Version 1.2: Added get_by_instance_uuids method
|
||||||
VERSION = '1.2'
|
# Version 1.3: Added get_counts()
|
||||||
|
VERSION = '1.3'
|
||||||
|
|
||||||
fields = {
|
fields = {
|
||||||
'objects': fields.ListOfObjectsField('InstanceMapping'),
|
'objects': fields.ListOfObjectsField('InstanceMapping'),
|
||||||
|
@ -391,3 +393,42 @@ class InstanceMappingList(base.ObjectListBase, base.NovaObject):
|
||||||
context, cell_uuid, project_id, limit)
|
context, cell_uuid, project_id, limit)
|
||||||
return base.obj_make_list(context, cls(), objects.InstanceMapping,
|
return base.obj_make_list(context, cls(), objects.InstanceMapping,
|
||||||
db_mappings)
|
db_mappings)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@db_api.api_context_manager.reader
|
||||||
|
def _get_counts_in_db(context, project_id, user_id=None):
|
||||||
|
project_query = context.session.query(
|
||||||
|
func.count(api_models.InstanceMapping.id)).\
|
||||||
|
filter_by(queued_for_delete=False).\
|
||||||
|
filter_by(project_id=project_id)
|
||||||
|
project_result = project_query.scalar()
|
||||||
|
counts = {'project': {'instances': project_result}}
|
||||||
|
if user_id:
|
||||||
|
user_result = project_query.filter_by(user_id=user_id).scalar()
|
||||||
|
counts['user'] = {'instances': user_result}
|
||||||
|
return counts
|
||||||
|
|
||||||
|
@base.remotable_classmethod
|
||||||
|
def get_counts(cls, context, project_id, user_id=None):
|
||||||
|
"""Get the counts of InstanceMapping objects in the database.
|
||||||
|
|
||||||
|
The count is used to represent the count of instances for the purpose
|
||||||
|
of counting quota usage. Instances that are queued_for_deleted=True are
|
||||||
|
not included in the count (deleted and SOFT_DELETED instances).
|
||||||
|
Instances that are queued_for_deleted=None are not included in the
|
||||||
|
count because we are not certain about whether or not they are deleted.
|
||||||
|
When counting quota usage, we will fall back on the legacy counting
|
||||||
|
method and count instances, cores, and ram from cell databases if any
|
||||||
|
unmigrated instance mappings (user_id=None or queued_for_delete=None)
|
||||||
|
are detected, to avoid using a potentially inaccurate count.
|
||||||
|
|
||||||
|
:param context: The request context for database access
|
||||||
|
:param project_id: The project_id to count across
|
||||||
|
:param user_id: The user_id to count across
|
||||||
|
:returns: A dict containing the project-scoped counts and user-scoped
|
||||||
|
counts if user_id is specified. For example:
|
||||||
|
|
||||||
|
{'project': {'instances': <count across project>},
|
||||||
|
'user': {'instances': <count across user>}}
|
||||||
|
"""
|
||||||
|
return cls._get_counts_in_db(context, project_id, user_id=user_id)
|
||||||
|
|
|
@ -577,3 +577,31 @@ class InstanceMappingListTestCase(test.NoDBTestCase):
|
||||||
cm.uuid,
|
cm.uuid,
|
||||||
None))
|
None))
|
||||||
self.assertEqual(2, len(ims))
|
self.assertEqual(2, len(ims))
|
||||||
|
|
||||||
|
def test_get_counts(self):
|
||||||
|
create_mapping(project_id='fake-project', user_id='fake-user',
|
||||||
|
queued_for_delete=False)
|
||||||
|
# mapping with another user
|
||||||
|
create_mapping(project_id='fake-project', user_id='other-user',
|
||||||
|
queued_for_delete=False)
|
||||||
|
# mapping in another project
|
||||||
|
create_mapping(project_id='other-project', user_id='fake-user',
|
||||||
|
queued_for_delete=False)
|
||||||
|
# queued_for_delete=True, should not be counted
|
||||||
|
create_mapping(project_id='fake-project', user_id='fake-user',
|
||||||
|
queued_for_delete=True)
|
||||||
|
# queued_for_delete=None (not yet migrated), should not be counted
|
||||||
|
create_mapping(project_id='fake-project', user_id='fake-user',
|
||||||
|
queued_for_delete=None)
|
||||||
|
|
||||||
|
# Count only across a project
|
||||||
|
counts = instance_mapping.InstanceMappingList.get_counts(
|
||||||
|
self.context, 'fake-project')
|
||||||
|
self.assertEqual(2, counts['project']['instances'])
|
||||||
|
self.assertNotIn('user', counts)
|
||||||
|
|
||||||
|
# Count across a project and a user
|
||||||
|
counts = instance_mapping.InstanceMappingList.get_counts(
|
||||||
|
self.context, 'fake-project', user_id='fake-user')
|
||||||
|
self.assertEqual(2, counts['project']['instances'])
|
||||||
|
self.assertEqual(1, counts['user']['instances'])
|
||||||
|
|
|
@ -1086,7 +1086,7 @@ object_data = {
|
||||||
'InstanceInfoCache': '1.5-cd8b96fefe0fc8d4d337243ba0bf0e1e',
|
'InstanceInfoCache': '1.5-cd8b96fefe0fc8d4d337243ba0bf0e1e',
|
||||||
'InstanceList': '2.4-d2c5723da8c1d08e07cb00160edfd292',
|
'InstanceList': '2.4-d2c5723da8c1d08e07cb00160edfd292',
|
||||||
'InstanceMapping': '1.2-3bd375e65c8eb9c45498d2f87b882e03',
|
'InstanceMapping': '1.2-3bd375e65c8eb9c45498d2f87b882e03',
|
||||||
'InstanceMappingList': '1.2-ee638619aa3d8a82a59c0c83bfa64d78',
|
'InstanceMappingList': '1.3-d34b6ebb076d542ae0f8b440534118da',
|
||||||
'InstanceNUMACell': '1.4-7c1eb9a198dee076b4de0840e45f4f55',
|
'InstanceNUMACell': '1.4-7c1eb9a198dee076b4de0840e45f4f55',
|
||||||
'InstanceNUMATopology': '1.3-ec0030cb0402a49c96da7051c037082a',
|
'InstanceNUMATopology': '1.3-ec0030cb0402a49c96da7051c037082a',
|
||||||
'InstancePCIRequest': '1.3-f6d324f1c337fad4f34892ed5f484c9a',
|
'InstancePCIRequest': '1.3-f6d324f1c337fad4f34892ed5f484c9a',
|
||||||
|
|
Loading…
Reference in New Issue