Merge "Set instance host and drop migration under lock" into stable/ussuri
This commit is contained in:
		@@ -3441,19 +3441,11 @@ class ComputeManager(manager.Manager):
 | 
				
			|||||||
                self._notify_instance_rebuild_error(context, instance, e, bdms)
 | 
					                self._notify_instance_rebuild_error(context, instance, e, bdms)
 | 
				
			||||||
                raise
 | 
					                raise
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                instance.apply_migration_context()
 | 
					                # NOTE(gibi): Let the resource tracker set the instance
 | 
				
			||||||
                # NOTE (ndipanov): This save will now update the host and node
 | 
					                # host and drop the migration context as we need to hold the
 | 
				
			||||||
                # attributes making sure that next RT pass is consistent since
 | 
					                # COMPUTE_RESOURCE_SEMAPHORE to avoid the race with
 | 
				
			||||||
                # it will be based on the instance and not the migration DB
 | 
					                # _update_available_resources. See bug 1896463.
 | 
				
			||||||
                # entry.
 | 
					                self.rt.finish_evacuation(instance, scheduled_node, migration)
 | 
				
			||||||
                instance.host = self.host
 | 
					 | 
				
			||||||
                instance.node = scheduled_node
 | 
					 | 
				
			||||||
                instance.save()
 | 
					 | 
				
			||||||
                instance.drop_migration_context()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                # NOTE (ndipanov): Mark the migration as done only after we
 | 
					 | 
				
			||||||
                # mark the instance as belonging to this host.
 | 
					 | 
				
			||||||
                self._set_migration_status(migration, 'done')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _do_rebuild_instance_with_claim(
 | 
					    def _do_rebuild_instance_with_claim(
 | 
				
			||||||
            self, context, instance, orig_image_ref, image_meta,
 | 
					            self, context, instance, orig_image_ref, image_meta,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1786,3 +1786,21 @@ class ResourceTracker(object):
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        self.pci_tracker.free_instance_claims(context, instance)
 | 
					        self.pci_tracker.free_instance_claims(context, instance)
 | 
				
			||||||
        self.pci_tracker.save(context)
 | 
					        self.pci_tracker.save(context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @utils.synchronized(COMPUTE_RESOURCE_SEMAPHORE, fair=True)
 | 
				
			||||||
 | 
					    def finish_evacuation(self, instance, node, migration):
 | 
				
			||||||
 | 
					        instance.apply_migration_context()
 | 
				
			||||||
 | 
					        # NOTE (ndipanov): This save will now update the host and node
 | 
				
			||||||
 | 
					        # attributes making sure that next RT pass is consistent since
 | 
				
			||||||
 | 
					        # it will be based on the instance and not the migration DB
 | 
				
			||||||
 | 
					        # entry.
 | 
				
			||||||
 | 
					        instance.host = self.host
 | 
				
			||||||
 | 
					        instance.node = node
 | 
				
			||||||
 | 
					        instance.save()
 | 
				
			||||||
 | 
					        instance.drop_migration_context()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # NOTE (ndipanov): Mark the migration as done only after we
 | 
				
			||||||
 | 
					        # mark the instance as belonging to this host.
 | 
				
			||||||
 | 
					        if migration:
 | 
				
			||||||
 | 
					            migration.status = 'done'
 | 
				
			||||||
 | 
					            migration.save()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -221,13 +221,4 @@ class TestEvacuateResourceTrackerRace(
 | 
				
			|||||||
            server, {'OS-EXT-SRV-ATTR:host': 'host2', 'status': 'ACTIVE'})
 | 
					            server, {'OS-EXT-SRV-ATTR:host': 'host2', 'status': 'ACTIVE'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._assert_pci_device_allocated(server['id'], self.compute1_id)
 | 
					        self._assert_pci_device_allocated(server['id'], self.compute1_id)
 | 
				
			||||||
 | 
					        self._assert_pci_device_allocated(server['id'], self.compute2_id)
 | 
				
			||||||
        # This is bug #1896463 as the PCI allocation was deleted by the racing
 | 
					 | 
				
			||||||
        # _update_available_resource periodic task.
 | 
					 | 
				
			||||||
        self._assert_pci_device_allocated(
 | 
					 | 
				
			||||||
            server['id'], self.compute2_id, num=0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # FIXME(gibi): When this bug is fixed (or if you remove the sleeps
 | 
					 | 
				
			||||||
        # above to avoid the race condition) then we expect that the PCI
 | 
					 | 
				
			||||||
        # allocation exists on the destination host too.
 | 
					 | 
				
			||||||
        # self._assert_pci_device_allocated(server['id'], self.compute2_id)
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5180,18 +5180,21 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
 | 
				
			|||||||
        node = uuidutils.generate_uuid()  # ironic node uuid
 | 
					        node = uuidutils.generate_uuid()  # ironic node uuid
 | 
				
			||||||
        instance = fake_instance.fake_instance_obj(self.context, node=node)
 | 
					        instance = fake_instance.fake_instance_obj(self.context, node=node)
 | 
				
			||||||
        instance.migration_context = None
 | 
					        instance.migration_context = None
 | 
				
			||||||
 | 
					        migration = objects.Migration(status='accepted')
 | 
				
			||||||
        with test.nested(
 | 
					        with test.nested(
 | 
				
			||||||
            mock.patch.object(self.compute, '_get_compute_info'),
 | 
					            mock.patch.object(self.compute, '_get_compute_info'),
 | 
				
			||||||
            mock.patch.object(self.compute, '_do_rebuild_instance_with_claim'),
 | 
					            mock.patch.object(self.compute, '_do_rebuild_instance_with_claim'),
 | 
				
			||||||
            mock.patch.object(objects.Instance, 'save'),
 | 
					            mock.patch.object(objects.Instance, 'save'),
 | 
				
			||||||
            mock.patch.object(self.compute, '_set_migration_status'),
 | 
					            mock.patch.object(migration, 'save'),
 | 
				
			||||||
        ) as (mock_get, mock_rebuild, mock_save, mock_set):
 | 
					        ) as (mock_get, mock_rebuild, mock_save, mock_migration_save):
 | 
				
			||||||
            self.compute.rebuild_instance(self.context, instance, None, None,
 | 
					            self.compute.rebuild_instance(
 | 
				
			||||||
                                          None, None, None, None, False,
 | 
					                self.context, instance, None, None,
 | 
				
			||||||
                                          False, False, None, None, {}, None)
 | 
					                None, None, None, None, False,
 | 
				
			||||||
 | 
					                False, False, migration, None, {}, None)
 | 
				
			||||||
            self.assertFalse(mock_get.called)
 | 
					            self.assertFalse(mock_get.called)
 | 
				
			||||||
            self.assertEqual(node, instance.node)
 | 
					            self.assertEqual(node, instance.node)
 | 
				
			||||||
            mock_set.assert_called_once_with(None, 'done')
 | 
					            self.assertEqual('done', migration.status)
 | 
				
			||||||
 | 
					            mock_migration_save.assert_called_once_with()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_rebuild_node_updated_if_recreate(self):
 | 
					    def test_rebuild_node_updated_if_recreate(self):
 | 
				
			||||||
        dead_node = uuidutils.generate_uuid()
 | 
					        dead_node = uuidutils.generate_uuid()
 | 
				
			||||||
@@ -5204,16 +5207,15 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
 | 
				
			|||||||
        with test.nested(
 | 
					        with test.nested(
 | 
				
			||||||
            mock.patch.object(self.compute, '_get_compute_info'),
 | 
					            mock.patch.object(self.compute, '_get_compute_info'),
 | 
				
			||||||
            mock.patch.object(self.compute, '_do_rebuild_instance'),
 | 
					            mock.patch.object(self.compute, '_do_rebuild_instance'),
 | 
				
			||||||
            mock.patch.object(objects.Instance, 'save'),
 | 
					        ) as (mock_get, mock_rebuild):
 | 
				
			||||||
            mock.patch.object(self.compute, '_set_migration_status'),
 | 
					 | 
				
			||||||
        ) as (mock_get, mock_rebuild, mock_save, mock_set):
 | 
					 | 
				
			||||||
            mock_get.return_value.hypervisor_hostname = 'new-node'
 | 
					            mock_get.return_value.hypervisor_hostname = 'new-node'
 | 
				
			||||||
            self.compute.rebuild_instance(self.context, instance, None, None,
 | 
					            self.compute.rebuild_instance(
 | 
				
			||||||
                                          None, None, None, None, True,
 | 
					                self.context, instance, None, None, None, None, None,
 | 
				
			||||||
                                          False, False, None, None, {}, None)
 | 
					                None, True, False, False, mock.sentinel.migration, None, {},
 | 
				
			||||||
 | 
					                None)
 | 
				
			||||||
            mock_get.assert_called_once_with(mock.ANY, self.compute.host)
 | 
					            mock_get.assert_called_once_with(mock.ANY, self.compute.host)
 | 
				
			||||||
            self.assertEqual('new-node', instance.node)
 | 
					            mock_rt.finish_evacuation.assert_called_once_with(
 | 
				
			||||||
            mock_set.assert_called_once_with(None, 'done')
 | 
					                instance, 'new-node', mock.sentinel.migration)
 | 
				
			||||||
            # Make sure the rebuild_claim was called with the proper image_meta
 | 
					            # Make sure the rebuild_claim was called with the proper image_meta
 | 
				
			||||||
            # from the instance.
 | 
					            # from the instance.
 | 
				
			||||||
            mock_rt.rebuild_claim.assert_called_once()
 | 
					            mock_rt.rebuild_claim.assert_called_once()
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user