diff options
author | Zuul <zuul@review.opendev.org> | 2023-02-27 15:11:25 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2023-02-27 15:11:25 +0000 |
commit | d443f8e4c4f12cdca947e36b443db5d8a230926e (patch) | |
tree | f5cc4cae644fd54f69481b6a7eaa13120432af85 | |
parent | 3e5742253fe283a890dae873e72cded53d235e13 (diff) | |
parent | 646fc51732b60b46385ceff0c7ea2c23372bbd72 (diff) | |
download | nova-d443f8e4c4f12cdca947e36b443db5d8a230926e.tar.gz |
Merge "Transport context to all threads"
-rw-r--r-- | nova/compute/manager.py | 7 | ||||
-rw-r--r-- | nova/conductor/manager.py | 4 | ||||
-rw-r--r-- | nova/tests/unit/compute/test_compute_mgr.py | 8 | ||||
-rw-r--r-- | nova/utils.py | 47 |
4 files changed, 37 insertions, 29 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 952ab3e199..efcdece81a 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -8913,7 +8913,8 @@ class ComputeManager(manager.Manager): # in order to be able to track and abort it in the future. self._waiting_live_migrations[instance.uuid] = (None, None) try: - future = self._live_migration_executor.submit( + future = nova.utils.pass_context( + self._live_migration_executor.submit, self._do_live_migration, context, dest, instance, block_migration, migration, migrate_data) self._waiting_live_migrations[instance.uuid] = (migration, future) @@ -10197,7 +10198,9 @@ class ComputeManager(manager.Manager): else: LOG.debug('Triggering sync for uuid %s', uuid) self._syncs_in_progress[uuid] = True - self._sync_power_pool.spawn_n(_sync, db_instance) + nova.utils.pass_context(self._sync_power_pool.spawn_n, + _sync, + db_instance) def _query_driver_power_state_and_sync(self, context, db_instance): if db_instance.task_state is not None: diff --git a/nova/conductor/manager.py b/nova/conductor/manager.py index 8177519331..4b34b8339c 100644 --- a/nova/conductor/manager.py +++ b/nova/conductor/manager.py @@ -2096,8 +2096,8 @@ class ComputeTaskManager: skipped_host(target_ctxt, host, image_ids) continue - fetch_pool.spawn_n(wrap_cache_images, target_ctxt, host, - image_ids) + utils.pass_context(fetch_pool.spawn_n, wrap_cache_images, + target_ctxt, host, image_ids) # Wait until all those things finish fetch_pool.waitall() diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py index 16de724a42..1c69cd8f1c 100644 --- a/nova/tests/unit/compute/test_compute_mgr.py +++ b/nova/tests/unit/compute/test_compute_mgr.py @@ -9648,9 +9648,15 @@ class ComputeManagerMigrationTestCase(test.NoDBTestCase, self.assertEqual(driver_console.get_connection_info.return_value, console) + @mock.patch('nova.utils.pass_context') @mock.patch('nova.compute.manager.ComputeManager.' '_do_live_migration') - def _test_max_concurrent_live(self, mock_lm): + def _test_max_concurrent_live(self, mock_lm, mock_pass_context): + # pass_context wraps the function, which doesn't work with a mock + # So we simply mock it too + def _mock_pass_context(runner, func, *args, **kwargs): + return runner(func, *args, **kwargs) + mock_pass_context.side_effect = _mock_pass_context @mock.patch('nova.objects.Migration.save') def _do_it(mock_mig_save): diff --git a/nova/utils.py b/nova/utils.py index 664056a09f..b5d45c58b5 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -632,15 +632,13 @@ def _serialize_profile_info(): return trace_info -def spawn(func, *args, **kwargs): - """Passthrough method for eventlet.spawn. - - This utility exists so that it can be stubbed for testing without - interfering with the service spawns. +def pass_context(runner, func, *args, **kwargs): + """Generalised passthrough method - It will also grab the context from the threadlocal store and add it to - the store on the new thread. This allows for continuity in logging the - context when using this method to spawn a new thread. + It will grab the context from the threadlocal store and add it to + the store on the runner. This allows for continuity in logging the + context when using this method to spawn a new thread through the + runner function """ _context = common_context.get_current() profiler_info = _serialize_profile_info() @@ -655,11 +653,11 @@ def spawn(func, *args, **kwargs): profiler.init(**profiler_info) return func(*args, **kwargs) - return eventlet.spawn(context_wrapper, *args, **kwargs) + return runner(context_wrapper, *args, **kwargs) -def spawn_n(func, *args, **kwargs): - """Passthrough method for eventlet.spawn_n. +def spawn(func, *args, **kwargs): + """Passthrough method for eventlet.spawn. This utility exists so that it can be stubbed for testing without interfering with the service spawns. @@ -668,25 +666,26 @@ def spawn_n(func, *args, **kwargs): the store on the new thread. This allows for continuity in logging the context when using this method to spawn a new thread. """ - _context = common_context.get_current() - profiler_info = _serialize_profile_info() - @functools.wraps(func) - def context_wrapper(*args, **kwargs): - # NOTE: If update_store is not called after spawn_n it won't be - # available for the logger to pull from threadlocal storage. - if _context is not None: - _context.update_store() - if profiler_info and profiler: - profiler.init(**profiler_info) - func(*args, **kwargs) + return pass_context(eventlet.spawn, func, *args, **kwargs) + + +def spawn_n(func, *args, **kwargs): + """Passthrough method for eventlet.spawn_n. + + This utility exists so that it can be stubbed for testing without + interfering with the service spawns. - eventlet.spawn_n(context_wrapper, *args, **kwargs) + It will also grab the context from the threadlocal store and add it to + the store on the new thread. This allows for continuity in logging the + context when using this method to spawn a new thread. + """ + pass_context(eventlet.spawn_n, func, *args, **kwargs) def tpool_execute(func, *args, **kwargs): """Run func in a native thread""" - tpool.execute(func, *args, **kwargs) + return pass_context(tpool.execute, func, *args, **kwargs) def is_none_string(val): |