Merge "RT: Migration resource tracking uses migration context"
This commit is contained in:
commit
a45983d87d
@ -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:
|
||||
|
@ -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))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user