Reduce the number of Instance.get_by_uuid calls
Only call Instance.get_by_uuid once per migration in ResourceTracker._update_usage_from_migrations rather than twice in some cases. Also increased test coverage for ResourceTracker._update_usage_from_migrations to 100%. Closes-Bug: #1385489 Change-Id: Ibc7e48340e103f8dcc502f7e91d8ffd939349486
This commit is contained in:
parent
917932460a
commit
e1e47cb5e6
|
@ -746,36 +746,37 @@ class ResourceTracker(object):
|
|||
self.tracked_migrations[uuid] = (migration, itype)
|
||||
|
||||
def _update_usage_from_migrations(self, context, migrations):
|
||||
|
||||
self.tracked_migrations.clear()
|
||||
|
||||
filtered = {}
|
||||
instances = {}
|
||||
self.tracked_migrations.clear()
|
||||
|
||||
# do some defensive filtering against bad migrations records in the
|
||||
# database:
|
||||
for migration in migrations:
|
||||
uuid = migration.instance_uuid
|
||||
|
||||
try:
|
||||
instance = migration.instance
|
||||
if uuid not in instances:
|
||||
instances[uuid] = migration.instance
|
||||
except exception.InstanceNotFound as e:
|
||||
# migration referencing deleted instance
|
||||
LOG.debug('Migration instance not found: %s', e)
|
||||
continue
|
||||
|
||||
uuid = instance.uuid
|
||||
|
||||
# skip migration if instance isn't in a resize state:
|
||||
if not _instance_in_resize_state(instance):
|
||||
if not _instance_in_resize_state(instances[uuid]):
|
||||
LOG.warning(_LW("Instance not resizing, skipping migration."),
|
||||
instance_uuid=uuid)
|
||||
continue
|
||||
|
||||
# filter to most recently updated migration for each instance:
|
||||
m = filtered.get(uuid, None)
|
||||
if not m or migration.updated_at >= m.updated_at:
|
||||
other_migration = filtered.get(uuid, None)
|
||||
if (not other_migration or
|
||||
migration.updated_at >= other_migration.updated_at):
|
||||
filtered[uuid] = migration
|
||||
|
||||
for migration in filtered.values():
|
||||
instance = migration.instance
|
||||
instance = instances[migration.instance_uuid]
|
||||
try:
|
||||
self._update_usage_from_migration(context, instance, None,
|
||||
migration)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
"""Tests for compute resource tracking."""
|
||||
|
||||
import copy
|
||||
import datetime
|
||||
import six
|
||||
import uuid
|
||||
|
||||
|
@ -1404,3 +1405,105 @@ class StatsInvalidTypeTestCase(BaseTrackerTestCase):
|
|||
self.assertRaises(ValueError,
|
||||
self.tracker.update_available_resource,
|
||||
context=self.context)
|
||||
|
||||
|
||||
class UpdateUsageFromMigrationsTestCase(BaseTrackerTestCase):
|
||||
|
||||
@mock.patch.object(resource_tracker.ResourceTracker,
|
||||
'_update_usage_from_migration')
|
||||
def test_no_migrations(self, mock_update_usage):
|
||||
migrations = []
|
||||
self.tracker._update_usage_from_migrations(self.context, migrations)
|
||||
self.assertFalse(mock_update_usage.called)
|
||||
|
||||
@mock.patch.object(resource_tracker.ResourceTracker,
|
||||
'_update_usage_from_migration')
|
||||
@mock.patch('nova.objects.instance.Instance.get_by_uuid')
|
||||
def test_instance_not_found(self, mock_get_instance, mock_update_usage):
|
||||
mock_get_instance.side_effect = exception.InstanceNotFound(
|
||||
instance_id='some_id',
|
||||
)
|
||||
migration = objects.Migration(
|
||||
context=self.context,
|
||||
instance_uuid='some_uuid',
|
||||
)
|
||||
self.tracker._update_usage_from_migrations(self.context, [migration])
|
||||
mock_get_instance.assert_called_once_with(self.context, 'some_uuid')
|
||||
self.assertFalse(mock_update_usage.called)
|
||||
|
||||
@mock.patch.object(resource_tracker.ResourceTracker,
|
||||
'_update_usage_from_migration')
|
||||
@mock.patch('nova.objects.instance.Instance.get_by_uuid')
|
||||
def test_update_usage_called(self, mock_get_instance, mock_update_usage):
|
||||
instance = self._fake_instance_obj()
|
||||
mock_get_instance.return_value = instance
|
||||
migration = objects.Migration(
|
||||
context=self.context,
|
||||
instance_uuid=instance.uuid,
|
||||
)
|
||||
self.tracker._update_usage_from_migrations(self.context, [migration])
|
||||
mock_get_instance.assert_called_once_with(self.context, instance.uuid)
|
||||
mock_update_usage.assert_called_once_with(
|
||||
self.context, instance, None, migration)
|
||||
|
||||
@mock.patch.object(resource_tracker.ResourceTracker,
|
||||
'_update_usage_from_migration')
|
||||
@mock.patch('nova.objects.instance.Instance.get_by_uuid')
|
||||
def test_flavor_not_found(self, mock_get_instance, mock_update_usage):
|
||||
mock_update_usage.side_effect = exception.FlavorNotFound(flavor_id='')
|
||||
instance = self._fake_instance_obj()
|
||||
mock_get_instance.return_value = instance
|
||||
migration = objects.Migration(
|
||||
context=self.context,
|
||||
instance_uuid=instance.uuid,
|
||||
)
|
||||
self.tracker._update_usage_from_migrations(self.context, [migration])
|
||||
mock_get_instance.assert_called_once_with(self.context, instance.uuid)
|
||||
mock_update_usage.assert_called_once_with(
|
||||
self.context, instance, None, migration)
|
||||
|
||||
@mock.patch.object(resource_tracker.ResourceTracker,
|
||||
'_update_usage_from_migration')
|
||||
@mock.patch('nova.objects.instance.Instance.get_by_uuid')
|
||||
def test_not_resizing_state(self, mock_get_instance, mock_update_usage):
|
||||
instance = self._fake_instance_obj()
|
||||
instance.vm_state = vm_states.ACTIVE
|
||||
instance.task_state = task_states.SUSPENDING
|
||||
mock_get_instance.return_value = instance
|
||||
migration = objects.Migration(
|
||||
context=self.context,
|
||||
instance_uuid=instance.uuid,
|
||||
)
|
||||
self.tracker._update_usage_from_migrations(self.context, [migration])
|
||||
mock_get_instance.assert_called_once_with(self.context, instance.uuid)
|
||||
self.assertFalse(mock_update_usage.called)
|
||||
|
||||
@mock.patch.object(resource_tracker.ResourceTracker,
|
||||
'_update_usage_from_migration')
|
||||
@mock.patch('nova.objects.instance.Instance.get_by_uuid')
|
||||
def test_use_most_recent(self, mock_get_instance, mock_update_usage):
|
||||
instance = self._fake_instance_obj()
|
||||
mock_get_instance.return_value = instance
|
||||
migration_2002 = objects.Migration(
|
||||
id=2002,
|
||||
context=self.context,
|
||||
instance_uuid=instance.uuid,
|
||||
updated_at=datetime.datetime(2002, 1, 1, 0, 0, 0),
|
||||
)
|
||||
migration_2003 = objects.Migration(
|
||||
id=2003,
|
||||
context=self.context,
|
||||
instance_uuid=instance.uuid,
|
||||
updated_at=datetime.datetime(2003, 1, 1, 0, 0, 0),
|
||||
)
|
||||
migration_2001 = objects.Migration(
|
||||
id=2001,
|
||||
context=self.context,
|
||||
instance_uuid=instance.uuid,
|
||||
updated_at=datetime.datetime(2001, 1, 1, 0, 0, 0),
|
||||
)
|
||||
self.tracker._update_usage_from_migrations(
|
||||
self.context, [migration_2002, migration_2003, migration_2001])
|
||||
mock_get_instance.assert_called_once_with(self.context, instance.uuid)
|
||||
mock_update_usage.assert_called_once_with(
|
||||
self.context, instance, None, migration_2003)
|
||||
|
|
Loading…
Reference in New Issue