Merge "RT: Migration resource tracking uses migration context"

This commit is contained in:
Jenkins 2015-09-15 19:26:17 +00:00 committed by Gerrit Code Review
commit a45983d87d
2 changed files with 77 additions and 19 deletions

View File

@ -326,10 +326,9 @@ class ResourceTracker(object):
elif not isinstance(image_meta, objects.ImageMeta):
image_meta = objects.ImageMeta.from_dict(image_meta)
if (instance_type is not None and
instance_type.id == itype['id']):
numa_topology = hardware.numa_get_constraints(
itype, image_meta)
if (instance_type is not None and instance_type.id == itype['id']):
numa_topology = self._get_migration_context_resource(
'numa_topology', instance)
usage = self._get_usage_dict(
itype, numa_topology=numa_topology)
if self.pci_tracker:
@ -677,6 +676,14 @@ class ResourceTracker(object):
# those for now to avoid them being included in below calculations.
return migration.migration_type in ('resize', 'migration')
def _get_migration_context_resource(self, resource, instance,
prefix='new_', itype=None):
migration_context = instance.migration_context
if migration_context:
return getattr(migration_context, prefix + resource)
else:
return None
def _update_usage_from_migration(self, context, instance, image_meta,
migration):
"""Update usage for a single migration. The record may
@ -696,6 +703,7 @@ class ResourceTracker(object):
record = self.tracked_instances.get(uuid, None)
itype = None
numa_topology = None
if same_node:
# same node resize. record usage for whichever instance type the
@ -704,21 +712,29 @@ class ResourceTracker(object):
migration.old_instance_type_id):
itype = self._get_instance_type(context, instance, 'new_',
migration.new_instance_type_id)
numa_topology = self._get_migration_context_resource(
'numa_topology', instance)
else:
# instance record already has new flavor, hold space for a
# possible revert to the old instance type:
itype = self._get_instance_type(context, instance, 'old_',
migration.old_instance_type_id)
numa_topology = self._get_migration_context_resource(
'numa_topology', instance, prefix='old_')
elif incoming and not record:
# instance has not yet migrated here:
itype = self._get_instance_type(context, instance, 'new_',
migration.new_instance_type_id)
numa_topology = self._get_migration_context_resource(
'numa_topology', instance)
elif outbound and not record:
# instance migrated, but record usage for a possible revert:
itype = self._get_instance_type(context, instance, 'old_',
migration.old_instance_type_id)
numa_topology = self._get_migration_context_resource(
'numa_topology', instance, prefix='old_')
if image_meta is None:
image_meta = objects.ImageMeta.from_instance(instance)
@ -728,14 +744,6 @@ class ResourceTracker(object):
image_meta = objects.ImageMeta.from_dict(image_meta)
if itype:
host_topology = self.compute_node.get('numa_topology')
if host_topology:
host_topology = objects.NUMATopology.obj_from_db_obj(
host_topology)
numa_topology = hardware.numa_get_constraints(itype, image_meta)
numa_topology = (
hardware.numa_fit_instance_to_host(
host_topology, numa_topology))
usage = self._get_usage_dict(
itype, numa_topology=numa_topology)
if self.pci_tracker:

View File

@ -246,7 +246,7 @@ _MIGRATION_INSTANCE_FIXTURES = {
vcpus=_INSTANCE_TYPE_FIXTURES[1]['vcpus'],
root_gb=_INSTANCE_TYPE_FIXTURES[1]['root_gb'],
ephemeral_gb=_INSTANCE_TYPE_FIXTURES[1]['ephemeral_gb'],
numa_topology=None,
numa_topology=_INSTANCE_NUMA_TOPOLOGIES['2mb'],
instance_type_id=1,
vm_state=vm_states.ACTIVE,
power_state=power_state.RUNNING,
@ -315,6 +315,16 @@ _MIGRATION_CONTEXT_FIXTURES = {
migration_id=3,
new_numa_topology=None,
old_numa_topology=None),
'f15ecfb0-9bf6-42db-9837-706eb2c4bf08': objects.MigrationContext(
instance_uuid='f15ecfb0-9bf6-42db-9837-706eb2c4bf08',
migration_id=1,
new_numa_topology=None,
old_numa_topology=_INSTANCE_NUMA_TOPOLOGIES['2mb']),
'f6ed631a-8645-4b12-8e1e-2fff55795765': objects.MigrationContext(
instance_uuid='f6ed631a-8645-4b12-8e1e-2fff55795765',
migration_id=2,
new_numa_topology=_INSTANCE_NUMA_TOPOLOGIES['2mb'],
old_numa_topology=None),
}
@ -629,7 +639,9 @@ class TestUpdateAvailableResources(BaseTestCase):
# processing code, and this property calls
# objects.Instance.get_by_uuid, so we have the migration return
inst_uuid = migr_obj.instance_uuid
get_inst_mock.return_value = _MIGRATION_INSTANCE_FIXTURES[inst_uuid]
instance = _MIGRATION_INSTANCE_FIXTURES[inst_uuid].obj_clone()
get_inst_mock.return_value = instance
instance.migration_context = _MIGRATION_CONTEXT_FIXTURES[inst_uuid]
update_mock = self._update_available_resources()
@ -686,8 +698,10 @@ class TestUpdateAvailableResources(BaseTestCase):
migr_obj = _MIGRATION_FIXTURES['dest-only']
migr_mock.return_value = [migr_obj]
inst_uuid = migr_obj.instance_uuid
get_inst_mock.return_value = _MIGRATION_INSTANCE_FIXTURES[inst_uuid]
instance = _MIGRATION_INSTANCE_FIXTURES[inst_uuid].obj_clone()
get_inst_mock.return_value = instance
get_cn_mock.return_value = _COMPUTE_NODE_FIXTURES[0]
instance.migration_context = _MIGRATION_CONTEXT_FIXTURES[inst_uuid]
update_mock = self._update_available_resources()
@ -721,13 +735,16 @@ class TestUpdateAvailableResources(BaseTestCase):
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
self.rt.compute_node))
@mock.patch('nova.objects.MigrationContext.get_by_instance_uuid',
return_value=None)
@mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename')
@mock.patch('nova.objects.MigrationList.get_in_progress_by_host_and_node')
@mock.patch('nova.objects.Instance.get_by_uuid')
@mock.patch('nova.objects.InstanceList.get_by_host_and_node')
def test_some_instances_source_and_dest_migration(self, get_mock,
get_inst_mock, migr_mock,
get_cn_mock):
get_cn_mock,
get_mig_ctxt_mock):
# We test the behavior of update_available_resource() when
# there is an active migration that involves this compute node
# as the destination host AND the source host, and the resource
@ -744,7 +761,9 @@ class TestUpdateAvailableResources(BaseTestCase):
inst_uuid = migr_obj.instance_uuid
# The resizing instance has already had its instance type
# changed to the *new* instance type (the bigger one, instance type 2)
resizing_instance = _MIGRATION_INSTANCE_FIXTURES[inst_uuid]
resizing_instance = _MIGRATION_INSTANCE_FIXTURES[inst_uuid].obj_clone()
resizing_instance.migration_context = (
_MIGRATION_CONTEXT_FIXTURES[resizing_instance.uuid])
all_instances = _INSTANCE_FIXTURES + [resizing_instance]
get_mock.return_value = all_instances
get_inst_mock.return_value = resizing_instance
@ -1257,6 +1276,7 @@ class TestMoveClaim(BaseTestCase):
self.driver_mock.get_host_ip_addr.return_value = "fake-ip"
flavor_mock.return_value = objects.Flavor(**self.flavor)
mig_context_obj = _MIGRATION_CONTEXT_FIXTURES[self.instance.uuid]
self.instance.migration_context = mig_context_obj
expected = copy.deepcopy(self.rt.compute_node)
self.adjust_expected(expected, self.flavor)
@ -1288,6 +1308,7 @@ class TestMoveClaim(BaseTestCase):
self.instance = _MIGRATION_INSTANCE_FIXTURES[migr_obj['instance_uuid']]
self.instance._context = self.ctx
mig_context_obj = _MIGRATION_CONTEXT_FIXTURES[self.instance.uuid]
self.instance.migration_context = mig_context_obj
with mock.patch.object(self.instance, 'save'):
self.rt.instance_claim(self.ctx, self.instance, None)
@ -1327,11 +1348,19 @@ class TestMoveClaim(BaseTestCase):
# Get our migrations, instances and itypes in a row
src_migr = _MIGRATION_FIXTURES['source-only']
src_instance = _MIGRATION_INSTANCE_FIXTURES[src_migr['instance_uuid']]
src_instance = (
_MIGRATION_INSTANCE_FIXTURES[src_migr['instance_uuid']].obj_clone()
)
src_instance.migration_context = (
_MIGRATION_CONTEXT_FIXTURES[src_instance.uuid])
old_itype = _INSTANCE_TYPE_FIXTURES[src_migr['old_instance_type_id']]
dst_migr = _MIGRATION_FIXTURES['dest-only']
dst_instance = _MIGRATION_INSTANCE_FIXTURES[dst_migr['instance_uuid']]
dst_instance = (
_MIGRATION_INSTANCE_FIXTURES[dst_migr['instance_uuid']].obj_clone()
)
new_itype = _INSTANCE_TYPE_FIXTURES[dst_migr['new_instance_type_id']]
dst_instance.migration_context = (
_MIGRATION_CONTEXT_FIXTURES[dst_instance.uuid])
# Set up the destination resource tracker
# update_available_resource to initialise extensible resource trackers
@ -1377,6 +1406,25 @@ class TestMoveClaim(BaseTestCase):
self.assertTrue(obj_base.obj_equal_prims(expected,
src_rt.compute_node))
def test_update_available_resources_migration_no_context(self, pci_mock,
inst_list_mock, inst_by_uuid, migr_mock, inst_save_mock):
"""When migrating onto older nodes - it is possible for the
migration_context record to be missing. Confirm resource audit works
regardless.
"""
self.register_mocks(pci_mock, inst_list_mock, inst_by_uuid, migr_mock,
inst_save_mock)
migr_obj = _MIGRATION_FIXTURES['source-and-dest']
self.instance = _MIGRATION_INSTANCE_FIXTURES[migr_obj['instance_uuid']]
self.instance.migration_context = None
expected = copy.deepcopy(self.rt.compute_node)
self.adjust_expected(expected, self.flavor)
self.audit(self.rt, [], [migr_obj], self.instance)
self.assertTrue(obj_base.obj_equal_prims(expected,
self.rt.compute_node))
def test_dupe_filter(self, pci_mock, inst_list_mock, inst_by_uuid,
migr_mock, inst_save_mock):
self.register_mocks(pci_mock, inst_list_mock, inst_by_uuid, migr_mock,
@ -1386,6 +1434,8 @@ class TestMoveClaim(BaseTestCase):
# This is good enough to prevent a lazy-load; value is unimportant
migr_obj['updated_at'] = None
self.instance = _MIGRATION_INSTANCE_FIXTURES[migr_obj['instance_uuid']]
self.instance.migration_context = (
_MIGRATION_CONTEXT_FIXTURES[self.instance.uuid])
self.audit(self.rt, [], [migr_obj, migr_obj], self.instance)
self.assertEqual(1, len(self.rt.tracked_migrations))