Do not fork compute workers in native threading mode

Force running the Compute Service within the main Process with native
threading to keep the baseline behavior.

In eventlet mode with workers=1 or workers=None it is oslo.service's
default behavior[1]. But with native threading we need to explicitly
pass no_fork=True to oslo to get this behavior instead of forking a
single worker [2].

Forking a single worker for compute would also be problematic as compute
initializes the conductor RPC client before such fork and the rabbitmq
oslo.messaging driver does not support forking with a connected client
[3].

Patch bumps the minimum oslo.service version to 4.4.1 to pick up the fix
https://review.opendev.org/c/openstack/oslo.service/+/966458 nova now
depends on.

[1] https://github.com/openstack/oslo.service/blob/37b90521ea01baa0c8e6412453c42972a28e3b12/oslo_service/backend/_eventlet/service.py#L749C1-L753
[2] https://github.com/openstack/oslo.service/blob/37b90521ea01baa0c8e6412453c42972a28e3b12/oslo_service/backend/_threading/service.py#L296-L300
[3] https://docs.openstack.org/oslo.messaging/latest/reference/transport.html#forking-processes-and-oslo-messaging-transport-objects

Change-Id: If6daffc25d737f53b1a478d42fd85a0446b09e6d
Signed-off-by: Balazs Gibizer <gibi@redhat.com>
This commit is contained in:
Balazs Gibizer
2025-10-31 10:43:20 +01:00
committed by Ghanshyam Maan
parent d6d87696b9
commit 0498e2ad76
4 changed files with 20 additions and 6 deletions
+2 -1
View File
@@ -61,5 +61,6 @@ def main():
objects.Service.enable_min_version_cache()
server = service.Service.create(binary='nova-compute',
topic=compute_rpcapi.RPC_TOPIC)
service.serve(server)
# Compute service should never fork worker processes
service.serve(server, workers=1, no_fork=True)
service.wait()
+2 -2
View File
@@ -322,13 +322,13 @@ class Service(service.Service):
_launcher = None
def serve(server, workers=None):
def serve(server, workers=None, no_fork=False):
global _launcher
if _launcher:
raise RuntimeError(_('serve() can only be called once'))
_launcher = service.launch(CONF, server, workers=workers,
restart_method='mutate')
restart_method='mutate', no_fork=no_fork)
def wait():
+15 -2
View File
@@ -324,7 +324,8 @@ class TestLauncher(test.NoDBTestCase):
mock_launch.assert_called_once_with(mock.ANY,
mock.sentinel.service,
workers=None,
restart_method='mutate')
restart_method='mutate',
no_fork=False)
@mock.patch.object(_service, 'launch')
def test_launch_app_with_workers(self, mock_launch):
@@ -333,7 +334,19 @@ class TestLauncher(test.NoDBTestCase):
mock_launch.assert_called_once_with(mock.ANY,
mock.sentinel.service,
workers=mock.sentinel.workers,
restart_method='mutate')
restart_method='mutate',
no_fork=False)
@mock.patch.object(_service, 'launch')
def test_launch_app_with_workers_no_fork(self, mock_launch):
service._launcher = None
service.serve(
mock.sentinel.service, workers=mock.sentinel.workers, no_fork=True)
mock_launch.assert_called_once_with(mock.ANY,
mock.sentinel.service,
workers=mock.sentinel.workers,
restart_method='mutate',
no_fork=True)
@mock.patch.object(_service, 'launch')
def test_launch_app_more_than_once_raises(self, mock_launch):
+1 -1
View File
@@ -43,7 +43,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[threading]>=4.2.0 # Apache-2.0
oslo.service[threading]>=4.4.1 # Apache-2.0
rfc3986>=1.2.0 # Apache-2.0
oslo.middleware>=3.31.0 # Apache-2.0
psutil>=3.2.2 # BSD