Merge "Allow services to start with threading"
This commit is contained in:
@@ -188,11 +188,3 @@ openstackdocs_projects = [
|
||||
'watcher',
|
||||
]
|
||||
# -- Custom extensions --------------------------------------------------------
|
||||
|
||||
# NOTE(mdbooth): (2019-03-20) Sphinx loads policies defined in setup.cfg, which
|
||||
# includes the placement policy at nova/api/openstack/placement/policies.py.
|
||||
# Loading this imports nova/api/openstack/__init__.py, which imports
|
||||
# nova.monkey_patch, which will do eventlet monkey patching to the sphinx
|
||||
# process. As well as being unnecessary and a bad idea, this breaks on
|
||||
# python3.6 (but not python3.7), so don't do that.
|
||||
os.environ['OS_NOVA_DISABLE_EVENTLET_PATCHING'] = '1'
|
||||
|
||||
+40
-8
@@ -29,7 +29,8 @@ def is_patched():
|
||||
|
||||
def _monkey_patch():
|
||||
if is_patched():
|
||||
return
|
||||
return False
|
||||
|
||||
# NOTE(mdbooth): Anything imported here will not be monkey patched. It is
|
||||
# important to take care not to import anything here which requires monkey
|
||||
# patching.
|
||||
@@ -68,14 +69,45 @@ def _monkey_patch():
|
||||
"importing and not executing nova code.",
|
||||
', '.join(problems))
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def patch():
|
||||
# NOTE(mdbooth): This workaround is required to avoid breaking sphinx. See
|
||||
# separate comment in doc/source/conf.py. It may also be useful for other
|
||||
# non-nova utilities. Ideally the requirement for this workaround will be
|
||||
# removed as soon as possible, so do not rely on, or extend it.
|
||||
if (os.environ.get('OS_NOVA_DISABLE_EVENTLET_PATCHING', '').lower()
|
||||
not in ('1', 'true', 'yes')):
|
||||
_monkey_patch()
|
||||
global MONKEY_PATCHED
|
||||
MONKEY_PATCHED = True
|
||||
|
||||
if _monkey_patch():
|
||||
global MONKEY_PATCHED
|
||||
MONKEY_PATCHED = True
|
||||
|
||||
import oslo_service.backend as service
|
||||
service.init_backend(service.BackendType.EVENTLET)
|
||||
from oslo_log import log as logging
|
||||
LOG = logging.getLogger(__name__)
|
||||
LOG.info("Service is starting with Eventlet based service backend")
|
||||
else:
|
||||
# We asked not to monkey patch so we will run in native threading mode
|
||||
import oslo_service.backend as service
|
||||
# NOTE(gibi): This will raise if the backend is already initialized
|
||||
# with Eventlet
|
||||
service.init_backend(service.BackendType.THREADING)
|
||||
|
||||
# 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
|
||||
|
||||
from oslo_log import log as logging
|
||||
LOG = logging.getLogger(__name__)
|
||||
LOG.warning(
|
||||
"Service is starting with native threading. This is currently "
|
||||
"experimental. Do not use it in production.")
|
||||
|
||||
+3
-1
@@ -25,6 +25,7 @@ import nova.conf
|
||||
import nova.context
|
||||
import nova.exception
|
||||
from nova.i18n import _
|
||||
from nova import utils
|
||||
|
||||
__all__ = [
|
||||
'init',
|
||||
@@ -217,10 +218,11 @@ def get_server(target, endpoints, serializer=None):
|
||||
else:
|
||||
serializer = RequestContextSerializer(serializer)
|
||||
access_policy = dispatcher.DefaultRPCAccessPolicy
|
||||
exc = "threading" if utils.concurrency_mode_threading() else "eventlet"
|
||||
return messaging.get_rpc_server(TRANSPORT,
|
||||
target,
|
||||
endpoints,
|
||||
executor='eventlet',
|
||||
executor=exc,
|
||||
serializer=serializer,
|
||||
access_policy=access_policy)
|
||||
|
||||
|
||||
@@ -250,6 +250,29 @@ class TestRPC(test.NoDBTestCase):
|
||||
access_policy=access_policy)
|
||||
self.assertEqual('server', server)
|
||||
|
||||
@mock.patch(
|
||||
'nova.utils.concurrency_mode_threading',
|
||||
new=mock.Mock(return_value=True))
|
||||
@mock.patch.object(rpc, 'TRANSPORT')
|
||||
@mock.patch.object(rpc, 'profiler', None)
|
||||
@mock.patch.object(rpc, 'RequestContextSerializer')
|
||||
@mock.patch.object(messaging, 'get_rpc_server')
|
||||
def test_get_server_threading(self, mock_get, mock_ser, mock_TRANSPORT):
|
||||
ser = mock.Mock()
|
||||
tgt = mock.Mock()
|
||||
ends = mock.Mock()
|
||||
mock_ser.return_value = ser
|
||||
mock_get.return_value = 'server'
|
||||
|
||||
server = rpc.get_server(tgt, ends, serializer='foo')
|
||||
|
||||
mock_ser.assert_called_once_with('foo')
|
||||
access_policy = dispatcher.DefaultRPCAccessPolicy
|
||||
mock_get.assert_called_once_with(mock_TRANSPORT, tgt, ends,
|
||||
executor='threading', serializer=ser,
|
||||
access_policy=access_policy)
|
||||
self.assertEqual('server', server)
|
||||
|
||||
@mock.patch.object(rpc, 'TRANSPORT')
|
||||
@mock.patch.object(rpc, 'profiler', mock.Mock())
|
||||
@mock.patch.object(rpc, 'ProfilerRequestContextSerializer')
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
import datetime
|
||||
import hashlib
|
||||
import os
|
||||
import threading
|
||||
from unittest import mock
|
||||
|
||||
@@ -26,11 +27,13 @@ from openstack import exceptions as sdk_exc
|
||||
from oslo_config import cfg
|
||||
from oslo_context import context as common_context
|
||||
from oslo_context import fixture as context_fixture
|
||||
import oslo_service.backend as oslo_backend
|
||||
from oslo_utils import encodeutils
|
||||
from oslo_utils import fixture as utils_fixture
|
||||
|
||||
from nova import context
|
||||
from nova import exception
|
||||
from nova import monkey_patch
|
||||
from nova.objects import base as obj_base
|
||||
from nova.objects import instance as instance_obj
|
||||
from nova.objects import service as service_obj
|
||||
@@ -1651,3 +1654,40 @@ class ExecutorStatsTestCase(test.NoDBTestCase):
|
||||
|
||||
utils.spawn(self._task_finishes).result()
|
||||
mock_info.assert_not_called()
|
||||
|
||||
|
||||
class OsloServiceBackendSelectionTestCase(test.NoDBTestCase):
|
||||
def setUp(self):
|
||||
# NOTE(gibi): We need this as the base test class would trigger
|
||||
# monkey patching and would prevent us to test the threading code path
|
||||
self.useFixture(
|
||||
fixtures.MonkeyPatch(
|
||||
"nova.monkey_patch._monkey_patch", lambda: True))
|
||||
super().setUp()
|
||||
origi = monkey_patch.MONKEY_PATCHED
|
||||
monkey_patch.MONKEY_PATCHED = False
|
||||
|
||||
def reset():
|
||||
monkey_patch.MONKEY_PATCHED = origi
|
||||
self.addCleanup(reset)
|
||||
|
||||
@mock.patch('oslo_service.backend.init_backend')
|
||||
def test_eventlet_selected(self, init_backend):
|
||||
monkey_patch.patch()
|
||||
|
||||
init_backend.assert_called_once_with(oslo_backend.BackendType.EVENTLET)
|
||||
|
||||
@mock.patch('oslo_service.backend.init_backend')
|
||||
@mock.patch.dict(os.environ, {"OS_NOVA_DISABLE_EVENTLET_PATCHING": "true"})
|
||||
def test_threading_selected_monkey_patching_poisoned(self, init_backend):
|
||||
monkey_patch.patch()
|
||||
|
||||
init_backend.assert_called_once_with(
|
||||
oslo_backend.BackendType.THREADING)
|
||||
import eventlet
|
||||
ex = self.assertRaises(RuntimeError, eventlet.monkey_patch)
|
||||
self.assertEqual(
|
||||
"The service is started with native threading via "
|
||||
"OS_NOVA_DISABLE_EVENTLET_PATCHING set to 'true', but then the "
|
||||
"service tried to call eventlet.monkey_patch(). This is a bug.",
|
||||
str(ex))
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
The nova-scheduler now can be run in native threading mode instead
|
||||
of with eventlet. This is an experimental feature that is disabled by
|
||||
default. Please read the
|
||||
`concurrency <https://docs.openstack.org/nova/latest/admin/concurrency.html>`__
|
||||
guide for more details.
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ oslo.messaging>=14.1.0 # Apache-2.0
|
||||
oslo.policy>=4.5.0 # Apache-2.0
|
||||
oslo.privsep>=2.6.2 # Apache-2.0
|
||||
oslo.i18n>=5.1.0 # Apache-2.0
|
||||
oslo.service>=2.8.0 # Apache-2.0
|
||||
oslo.service[threading]>=4.2.0 # Apache-2.0
|
||||
rfc3986>=1.2.0 # Apache-2.0
|
||||
oslo.middleware>=3.31.0 # Apache-2.0
|
||||
psutil>=3.2.2 # BSD
|
||||
|
||||
Reference in New Issue
Block a user