Merge "Add get_counts() to InstanceMappingList"
This commit is contained in:
commit
22ad5a5709
|
@ -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)
|
||||
|
|
|
@ -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'])
|
||||
|
|
|
@ -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',
|
||||
|
|
Loading…
Reference in New Issue