From 50bf252250a35f7d9d09c75243f80a4ec0a0fc39 Mon Sep 17 00:00:00 2001 From: melanie witt Date: Thu, 7 Oct 2021 23:47:13 +0000 Subject: [PATCH] Make the CellDatabases fixture work with fasteners >= 0.15 As of fasteners >= 0.15, the workaround code to use eventlet.getcurrent if eventlet patching is detected has been removed and threading.current_thread is being used instead [1]. Although we are running in a greenlet in our test environment, we are not running in a greenlet of type GreenThread. A GreenThread is created by calling eventlet.spawn and spawn is not used to run our tests. At the time of this writing, the eventlet patched threading.current_thread method falls back to the original unpatched current_thread method if it is not called from a GreenThead [2] and that breaks our tests involving this fixture. We can work around this by patching threading.current_thread with eventlet.getcurrent during creation of the lock object. [1] https://github.com/harlowja/fasteners/commit/467ed75ee1e9465ebff8b5edf452770befb93913 [2] https://github.com/eventlet/eventlet/blob/v0.32.0/eventlet/green/threading.py#L128 Change-Id: I168fffac8002f274a905cfd53ac4f6c9abe18803 --- nova/tests/fixtures/nova.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/nova/tests/fixtures/nova.py b/nova/tests/fixtures/nova.py index b1f4b5bbd274..4d2b955e2128 100644 --- a/nova/tests/fixtures/nova.py +++ b/nova/tests/fixtures/nova.py @@ -17,6 +17,7 @@ """Fixtures for Nova tests.""" import collections +import contextlib from contextlib import contextmanager import functools import logging as std_logging @@ -406,7 +407,24 @@ class CellDatabases(fixtures.Fixture): # to point to a cell, we need to take an exclusive lock to # prevent any other calls to get_context_manager() until we # reset to the default. - self._cell_lock = lockutils.ReaderWriterLock() + # NOTE(melwitt): As of fasteners >= 0.15, the workaround code to use + # eventlet.getcurrent if eventlet patching is detected has been removed + # and threading.current_thread is being used instead. Although we are + # running in a greenlet in our test environment, we are not running in + # a greenlet of type GreenThread. A GreenThread is created by calling + # eventlet.spawn and spawn is not used to run our tests. At the time of + # this writing, the eventlet patched threading.current_thread method + # falls back to the original unpatched current_thread method if it is + # not called from a GreenThead [1] and that breaks our tests involving + # this fixture. + # We can work around this by patching threading.current_thread with + # eventlet.getcurrent during creation of the lock object. + # [1] https://github.com/eventlet/eventlet/blob/v0.32.0/eventlet/green/threading.py#L128 # noqa + eventlet_patched = eventlet.patcher.is_monkey_patched('thread') + with (contextlib.ExitStack() if not eventlet_patched else + fixtures.MonkeyPatch('threading.current_thread', + eventlet.getcurrent)): + self._cell_lock = lockutils.ReaderWriterLock() def _cache_schema(self, connection_str): # NOTE(melwitt): See the regular Database fixture for why