Merge "Add get_counts() to InstanceMappingList"

This commit is contained in:
Zuul 2019-05-30 05:33:40 +00:00 committed by Gerrit Code Review
commit 22ad5a5709
3 changed files with 71 additions and 2 deletions

View File

@ -17,6 +17,7 @@ from oslo_utils import versionutils
import six
from sqlalchemy.orm import joinedload
from sqlalchemy.sql import false
from sqlalchemy.sql import func
from sqlalchemy.sql import or_
from nova import context as nova_context
@ -294,7 +295,8 @@ class InstanceMappingList(base.ObjectListBase, base.NovaObject):
# Version 1.0: Initial version
# Version 1.1: Added get_by_cell_id method.
# Version 1.2: Added get_by_instance_uuids method
VERSION = '1.2'
# Version 1.3: Added get_counts()
VERSION = '1.3'
fields = {
'objects': fields.ListOfObjectsField('InstanceMapping'),
@ -391,3 +393,42 @@ class InstanceMappingList(base.ObjectListBase, base.NovaObject):
context, cell_uuid, project_id, limit)
return base.obj_make_list(context, cls(), objects.InstanceMapping,
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)

View File

@ -577,3 +577,31 @@ class InstanceMappingListTestCase(test.NoDBTestCase):
cm.uuid,
None))
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'])

View File

@ -1086,7 +1086,7 @@ object_data = {
'InstanceInfoCache': '1.5-cd8b96fefe0fc8d4d337243ba0bf0e1e',
'InstanceList': '2.4-d2c5723da8c1d08e07cb00160edfd292',
'InstanceMapping': '1.2-3bd375e65c8eb9c45498d2f87b882e03',
'InstanceMappingList': '1.2-ee638619aa3d8a82a59c0c83bfa64d78',
'InstanceMappingList': '1.3-d34b6ebb076d542ae0f8b440534118da',
'InstanceNUMACell': '1.4-7c1eb9a198dee076b4de0840e45f4f55',
'InstanceNUMATopology': '1.3-ec0030cb0402a49c96da7051c037082a',
'InstancePCIRequest': '1.3-f6d324f1c337fad4f34892ed5f484c9a',