diff --git a/nova/monkey_patch.py b/nova/monkey_patch.py index 68d1c17faa4c..f97dd8ae32f2 100644 --- a/nova/monkey_patch.py +++ b/nova/monkey_patch.py @@ -94,17 +94,7 @@ def patch(): # NOTE(gibi): We were asked not to monkey patch. Let's enforce it by # removing the possibility to monkey_patch accidentally - def poison(*args, **kwargs): - raise RuntimeError( - "The service is started with native threading via " - "OS_NOVA_DISABLE_EVENTLET_PATCHING set to '%s', but then the " - "service tried to call eventlet.monkey_patch(). This is a " - "bug." - % os.environ.get('OS_NOVA_DISABLE_EVENTLET_PATCHING', '')) - - import eventlet - eventlet.monkey_patch = poison - eventlet.patcher.monkey_patch = poison + poison_eventlet() from oslo_log import log as logging LOG = logging.getLogger(__name__) @@ -112,3 +102,30 @@ def patch(): "Service is starting with native threading. This is currently " "experimental. Do not use it in production without first " "testing it in pre-production.") + + +def _poison(*args, **kwargs): + raise RuntimeError( + "The service is started with native threading via " + "OS_NOVA_DISABLE_EVENTLET_PATCHING set to '%s', but then the " + "service tried to call eventlet.monkey_patch(). This is a bug." + % os.environ.get('OS_NOVA_DISABLE_EVENTLET_PATCHING', '')) + + +def poison_eventlet(): + import eventlet + eventlet.monkey_patch = _poison + eventlet.patcher.monkey_patch = _poison + + # We want to have this but cannot have this yet as we still have common + # code that imports eventlet like nova.utils.tpool + # + # class PoisonEventletImport: + # def find_spec(self, fullname, path, target=None): + # if fullname.startswith('eventlet'): + # raise ImportError( + # "The service started in threading mode so it should " + # "not import eventlet") + + # import sys + # sys.meta_path.insert(0, PoisonEventletImport()) diff --git a/nova/tests/unit/__init__.py b/nova/tests/unit/__init__.py index 5f48fd3ec937..fe940203e21c 100644 --- a/nova/tests/unit/__init__.py +++ b/nova/tests/unit/__init__.py @@ -22,6 +22,21 @@ :platform: Unix """ +# The import order in the test environment is different from the import +# order in a real env. During unit testing nova.test.unit is imported first +# to discover the unit tests, then the modules under it are imported. This +# test discovery import forces the import of oslo.messaging eventually that +# import time run code that uses the oslo.service backend which forces the +# initialization of the backed to the default eventlet. This prevents +# our tests to run with the threading backend. To avoid this we force the +# backend registration early here by using our common monkey_patch mode +# that already does smart backend selection based on env variables. +# The monkey_patching would be used anyhow when nova.test is imported so +# this does not change the end result just the order of imports +# autopep8: off +from nova import monkey_patch ; monkey_patch.patch() # noqa +# autopep8: on + from nova import objects # NOTE(comstud): Make sure we have all of the objects loaded. We do this diff --git a/tox.ini b/tox.ini index 941f3639b183..0908e8d8dd22 100644 --- a/tox.ini +++ b/tox.ini @@ -48,6 +48,9 @@ passenv = PYTHONOPTIMIZE # there is also secret magic in subunit-trace which lets you run in a fail only # mode. To do this define the TRACE_FAILONLY environmental variable. + +# allow running without eventlet + OS_NOVA_DISABLE_EVENTLET_PATCHING commands = stestr run {posargs} env TEST_OSPROFILER=1 stestr run --combine --no-discover 'nova.tests.unit.test_profiler'