From 89026fdbae9b86074e599ee81d136e58190d1206 Mon Sep 17 00:00:00 2001 From: Daniel Bengtsson Date: Tue, 15 Jul 2025 15:31:49 +0200 Subject: [PATCH] Merge common files in one service file. All the files was only used by service. Merged in one file. Rename the common package with underscore to indicate it's private one. Made the same for the eventlet and threading backend. Change-Id: Id81d2737f45695f6ccda4807924615b9673bf376 Signed-off-by: Daniel Bengtsson --- oslo_service/backend/__init__.py | 11 ++++- .../backend/{common => _common}/__init__.py | 0 .../backend/{common => _common}/constants.py | 0 .../signal_utils.py => _common/service.py} | 41 +++++++++++++++++++ .../{eventlet => _eventlet}/__init__.py | 18 ++++---- .../{eventlet => _eventlet}/loopingcall.py | 0 .../{eventlet => _eventlet}/service.py | 21 ++++------ .../{eventlet => _eventlet}/threadgroup.py | 2 +- .../{threading => _threading}/__init__.py | 18 ++++---- .../{threading => _threading}/loopingcall.py | 0 .../{threading => _threading}/service.py | 12 +++--- .../{threading => _threading}/threadgroup.py | 2 +- oslo_service/backend/common/daemon_utils.py | 33 --------------- oslo_service/backend/common/singleton.py | 26 ------------ .../backend/common/validation_utils.py | 23 ----------- .../tests/backend/threading/test_launcher.py | 2 +- ...ubmodules-to-private-63bfa674677c3854.yaml | 19 +++++++++ 17 files changed, 104 insertions(+), 124 deletions(-) rename oslo_service/backend/{common => _common}/__init__.py (100%) rename oslo_service/backend/{common => _common}/constants.py (100%) rename oslo_service/backend/{common/signal_utils.py => _common/service.py} (52%) rename oslo_service/backend/{eventlet => _eventlet}/__init__.py (79%) rename oslo_service/backend/{eventlet => _eventlet}/loopingcall.py (100%) rename oslo_service/backend/{eventlet => _eventlet}/service.py (98%) rename oslo_service/backend/{eventlet => _eventlet}/threadgroup.py (99%) rename oslo_service/backend/{threading => _threading}/__init__.py (79%) rename oslo_service/backend/{threading => _threading}/loopingcall.py (100%) rename oslo_service/backend/{threading => _threading}/service.py (95%) rename oslo_service/backend/{threading => _threading}/threadgroup.py (99%) delete mode 100644 oslo_service/backend/common/daemon_utils.py delete mode 100644 oslo_service/backend/common/singleton.py delete mode 100644 oslo_service/backend/common/validation_utils.py create mode 100644 releasenotes/notes/rename-backend-submodules-to-private-63bfa674677c3854.yaml diff --git a/oslo_service/backend/__init__.py b/oslo_service/backend/__init__.py index 81abb16b..38c1db1e 100644 --- a/oslo_service/backend/__init__.py +++ b/oslo_service/backend/__init__.py @@ -44,6 +44,15 @@ _cached_components: dict[str, Any] | None = None # optional override hook _backend_hook: Callable[[], BackendType] | None = None +__all__ = [ + "get_component", + "init_backend", + "BackendType", + "register_backend_default_hook", + "get_backend_type", + "get_backend" +] + def register_backend_default_hook(hook: Callable[[], BackendType]) -> None: """Register a hook that decides the default backend type. @@ -93,7 +102,7 @@ def init_backend(type_: BackendType) -> None: LOG.info(f"Loading backend: {backend_name}") try: - module_name = f"oslo_service.backend.{backend_name}" + module_name = f"oslo_service.backend._{backend_name}" module = importlib.import_module(module_name) backend_class = getattr(module, f"{backend_name.capitalize()}Backend") diff --git a/oslo_service/backend/common/__init__.py b/oslo_service/backend/_common/__init__.py similarity index 100% rename from oslo_service/backend/common/__init__.py rename to oslo_service/backend/_common/__init__.py diff --git a/oslo_service/backend/common/constants.py b/oslo_service/backend/_common/constants.py similarity index 100% rename from oslo_service/backend/common/constants.py rename to oslo_service/backend/_common/constants.py diff --git a/oslo_service/backend/common/signal_utils.py b/oslo_service/backend/_common/service.py similarity index 52% rename from oslo_service/backend/common/signal_utils.py rename to oslo_service/backend/_common/service.py index 4569fc8c..0903bb08 100644 --- a/oslo_service/backend/common/signal_utils.py +++ b/oslo_service/backend/_common/service.py @@ -12,7 +12,30 @@ # See the License for the specific language governing permissions and # limitations under the License. +import errno +import io +import os import signal +import sys + +from oslo_concurrency import lockutils + +from oslo_service._i18n import _ +from oslo_service.backend.base import ServiceBase + + +def is_daemon(): + try: + return os.getpgrp() != os.tcgetpgrp(sys.stdout.fileno()) + except io.UnsupportedOperation: + return True + except OSError as err: + return err.errno == errno.ENOTTY or False + + +def is_sighup_and_daemon(signo, signal_handler): + return (signal_handler.is_signal_supported('SIGHUP') and + signo == signal.SIGHUP and is_daemon()) def get_signal_mappings(ignore=('SIG_DFL', 'SIG_IGN')): @@ -36,3 +59,21 @@ class SignalExit(SystemExit): def __init__(self, signo, exccode=1): super().__init__(exccode) self.signo = signo + + +def check_service_base(service): + if not isinstance(service, ServiceBase): + raise TypeError( + _("Service %(service)s must be an instance of %(base)s!") + % {'service': service, 'base': ServiceBase}) + + +class Singleton(type): + _instances = {} + _semaphores = lockutils.Semaphores() + + def __call__(cls, *args, **kwargs): + with lockutils.lock('singleton_lock', semaphores=cls._semaphores): + if cls not in cls._instances: + cls._instances[cls] = super().__call__(*args, **kwargs) + return cls._instances[cls] diff --git a/oslo_service/backend/eventlet/__init__.py b/oslo_service/backend/_eventlet/__init__.py similarity index 79% rename from oslo_service/backend/eventlet/__init__.py rename to oslo_service/backend/_eventlet/__init__.py index 7b014f71..ca21d7da 100644 --- a/oslo_service/backend/eventlet/__init__.py +++ b/oslo_service/backend/_eventlet/__init__.py @@ -14,13 +14,11 @@ # limitations under the License. +from oslo_service.backend._common import service as service_common +from oslo_service.backend._eventlet import loopingcall +from oslo_service.backend._eventlet import service +from oslo_service.backend._eventlet import threadgroup from oslo_service.backend.base import BaseBackend -from oslo_service.backend.common import daemon_utils -from oslo_service.backend.common import signal_utils -from oslo_service.backend.common import singleton -from oslo_service.backend.eventlet import loopingcall -from oslo_service.backend.eventlet import service -from oslo_service.backend.eventlet import threadgroup class EventletBackend(BaseBackend): @@ -40,8 +38,8 @@ class EventletBackend(BaseBackend): "Services": service.Services, "ServiceWrapper": service.ServiceWrapper, "SignalHandler": service.SignalHandler, - "SignalExit": signal_utils.SignalExit, - "Singleton": singleton.Singleton, + "SignalExit": service_common.SignalExit, + "Singleton": service_common.Singleton, # Looping call-related classes "LoopingCallBase": loopingcall.LoopingCallBase, @@ -60,6 +58,6 @@ class EventletBackend(BaseBackend): # Functions "launch": service.launch, - "_is_daemon": daemon_utils.is_daemon, - "_is_sighup_and_daemon": daemon_utils.is_sighup_and_daemon, + "_is_daemon": service_common.is_daemon, + "_is_sighup_and_daemon": service_common.is_sighup_and_daemon, } diff --git a/oslo_service/backend/eventlet/loopingcall.py b/oslo_service/backend/_eventlet/loopingcall.py similarity index 100% rename from oslo_service/backend/eventlet/loopingcall.py rename to oslo_service/backend/_eventlet/loopingcall.py diff --git a/oslo_service/backend/eventlet/service.py b/oslo_service/backend/_eventlet/service.py similarity index 98% rename from oslo_service/backend/eventlet/service.py rename to oslo_service/backend/_eventlet/service.py index 9aec56b1..b76d526b 100644 --- a/oslo_service/backend/eventlet/service.py +++ b/oslo_service/backend/_eventlet/service.py @@ -34,20 +34,17 @@ from eventlet import tpool from oslo_service._i18n import _ from oslo_service import _options -from oslo_service.backend.base import ServiceBase -from oslo_service.backend.common.constants import \ +from oslo_service.backend._common.constants import \ _LAUNCHER_RESTART_METHODS -from oslo_service.backend.common.daemon_utils import \ +from oslo_service.backend._common.service \ + import check_service_base as _check_service_base +from oslo_service.backend._common.service import get_signal_mappings +from oslo_service.backend._common.service import \ is_sighup_and_daemon as _is_sighup_and_daemon -from oslo_service.backend.common.signal_utils import \ - get_signal_mappings -from oslo_service.backend.common.signal_utils import \ - SignalExit -from oslo_service.backend.common.singleton import \ - Singleton -from oslo_service.backend.common.validation_utils import \ - check_service_base as _check_service_base -from oslo_service.backend.eventlet import threadgroup +from oslo_service.backend._common.service import SignalExit +from oslo_service.backend._common.service import Singleton +from oslo_service.backend._eventlet import threadgroup +from oslo_service.backend.base import ServiceBase from oslo_service import eventlet_backdoor from oslo_service import systemd diff --git a/oslo_service/backend/eventlet/threadgroup.py b/oslo_service/backend/_eventlet/threadgroup.py similarity index 99% rename from oslo_service/backend/eventlet/threadgroup.py rename to oslo_service/backend/_eventlet/threadgroup.py index a1dcc234..c386340e 100644 --- a/oslo_service/backend/eventlet/threadgroup.py +++ b/oslo_service/backend/_eventlet/threadgroup.py @@ -21,7 +21,7 @@ from debtcollector import removals import eventlet from eventlet import greenpool -from oslo_service.backend.eventlet import loopingcall +from oslo_service.backend._eventlet import loopingcall from oslo_utils import timeutils LOG = logging.getLogger(__name__) diff --git a/oslo_service/backend/threading/__init__.py b/oslo_service/backend/_threading/__init__.py similarity index 79% rename from oslo_service/backend/threading/__init__.py rename to oslo_service/backend/_threading/__init__.py index a31c73f9..e2f877f8 100644 --- a/oslo_service/backend/threading/__init__.py +++ b/oslo_service/backend/_threading/__init__.py @@ -12,13 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +from oslo_service.backend._common import service as service_common +from oslo_service.backend._threading import loopingcall +from oslo_service.backend._threading import service +from oslo_service.backend._threading import threadgroup from oslo_service.backend.base import BaseBackend -from oslo_service.backend.common import daemon_utils -from oslo_service.backend.common import signal_utils -from oslo_service.backend.common import singleton -from oslo_service.backend.threading import loopingcall -from oslo_service.backend.threading import service -from oslo_service.backend.threading import threadgroup class ThreadingBackend(BaseBackend): @@ -37,9 +35,9 @@ class ThreadingBackend(BaseBackend): "Service": service.Service, "Services": service.Services, "ServiceWrapper": service.ServiceWrapper, - "SignalExit": signal_utils.SignalExit, + "SignalExit": service_common.SignalExit, "SignalHandler": service.SignalHandler, - "Singleton": singleton.Singleton, + "Singleton": service_common.Singleton, # Looping call-related classes "LoopingCallBase": loopingcall.LoopingCallBase, "LoopingCallDone": loopingcall.LoopingCallDone, @@ -54,7 +52,7 @@ class ThreadingBackend(BaseBackend): "ThreadGroup": threadgroup.ThreadGroup, "Thread": threadgroup.Thread, # Functions - "_is_daemon": daemon_utils.is_daemon, - "_is_sighup_and_daemon": daemon_utils.is_sighup_and_daemon, + "_is_daemon": service_common.is_daemon, + "_is_sighup_and_daemon": service_common.is_sighup_and_daemon, "launch": service.launch, } diff --git a/oslo_service/backend/threading/loopingcall.py b/oslo_service/backend/_threading/loopingcall.py similarity index 100% rename from oslo_service/backend/threading/loopingcall.py rename to oslo_service/backend/_threading/loopingcall.py diff --git a/oslo_service/backend/threading/service.py b/oslo_service/backend/_threading/service.py similarity index 95% rename from oslo_service/backend/threading/service.py rename to oslo_service/backend/_threading/service.py index e210e7e0..ea427f85 100644 --- a/oslo_service/backend/threading/service.py +++ b/oslo_service/backend/_threading/service.py @@ -24,13 +24,13 @@ import cotyledon from cotyledon import oslo_config_glue from oslo_service._i18n import _ +from oslo_service.backend._common.constants import _LAUNCHER_RESTART_METHODS +from oslo_service.backend._common.service \ + import check_service_base as _check_service_base +from oslo_service.backend._common.service import get_signal_mappings +from oslo_service.backend._common.service import Singleton +from oslo_service.backend._threading import threadgroup from oslo_service.backend.base import ServiceBase -from oslo_service.backend.common.constants import _LAUNCHER_RESTART_METHODS -from oslo_service.backend.common.signal_utils import get_signal_mappings -from oslo_service.backend.common.singleton import Singleton -from oslo_service.backend.common.validation_utils import \ - check_service_base as _check_service_base -from oslo_service.backend.threading import threadgroup LOG = logging.getLogger(__name__) diff --git a/oslo_service/backend/threading/threadgroup.py b/oslo_service/backend/_threading/threadgroup.py similarity index 99% rename from oslo_service/backend/threading/threadgroup.py rename to oslo_service/backend/_threading/threadgroup.py index a2f674fc..5b4a3f8d 100644 --- a/oslo_service/backend/threading/threadgroup.py +++ b/oslo_service/backend/_threading/threadgroup.py @@ -18,7 +18,7 @@ import threading import time import warnings -from oslo_service.backend.threading import loopingcall +from oslo_service.backend._threading import loopingcall LOG = logging.getLogger(__name__) diff --git a/oslo_service/backend/common/daemon_utils.py b/oslo_service/backend/common/daemon_utils.py deleted file mode 100644 index 06a67aba..00000000 --- a/oslo_service/backend/common/daemon_utils.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (C) 2025 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import errno -import io -import os -import signal -import sys - - -def is_daemon(): - try: - return os.getpgrp() != os.tcgetpgrp(sys.stdout.fileno()) - except io.UnsupportedOperation: - return True - except OSError as err: - return err.errno == errno.ENOTTY or False - - -def is_sighup_and_daemon(signo, signal_handler): - return (signal_handler.is_signal_supported('SIGHUP') and - signo == signal.SIGHUP and is_daemon()) diff --git a/oslo_service/backend/common/singleton.py b/oslo_service/backend/common/singleton.py deleted file mode 100644 index 2b2909fc..00000000 --- a/oslo_service/backend/common/singleton.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (C) 2025 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from oslo_concurrency import lockutils - - -class Singleton(type): - _instances = {} - _semaphores = lockutils.Semaphores() - - def __call__(cls, *args, **kwargs): - with lockutils.lock('singleton_lock', semaphores=cls._semaphores): - if cls not in cls._instances: - cls._instances[cls] = super().__call__(*args, **kwargs) - return cls._instances[cls] diff --git a/oslo_service/backend/common/validation_utils.py b/oslo_service/backend/common/validation_utils.py deleted file mode 100644 index bca18237..00000000 --- a/oslo_service/backend/common/validation_utils.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2025 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from oslo_service._i18n import _ -from oslo_service.backend.base import ServiceBase - - -def check_service_base(service): - if not isinstance(service, ServiceBase): - raise TypeError( - _("Service %(service)s must be an instance of %(base)s!") - % {'service': service, 'base': ServiceBase}) diff --git a/oslo_service/tests/backend/threading/test_launcher.py b/oslo_service/tests/backend/threading/test_launcher.py index 7a1ed503..3dcceef0 100644 --- a/oslo_service/tests/backend/threading/test_launcher.py +++ b/oslo_service/tests/backend/threading/test_launcher.py @@ -18,7 +18,7 @@ from unittest import TestCase from oslo_config import cfg -from oslo_service.backend.threading import service +from oslo_service.backend._threading import service class DummyService(service.ServiceBase): diff --git a/releasenotes/notes/rename-backend-submodules-to-private-63bfa674677c3854.yaml b/releasenotes/notes/rename-backend-submodules-to-private-63bfa674677c3854.yaml new file mode 100644 index 00000000..b35265b6 --- /dev/null +++ b/releasenotes/notes/rename-backend-submodules-to-private-63bfa674677c3854.yaml @@ -0,0 +1,19 @@ +--- +upgrade: + - | + Internal backend modules have been renamed to **explicitly indicate that + they are** private: + + * ``oslo_service.backend.common`` → ``oslo_service.backend._common`` + * ``oslo_service.backend.threading`` → ``oslo_service.backend._threading`` + * ``oslo_service.backend.eventlet`` → ``oslo_service.backend._eventlet`` + + These modules were never intended to be used directly. **This change makes + it clearer** that they are internal to ``oslo_service.backend``. Projects + should only interact with the backend system via the public interface + provided in ``oslo_service.backend.__init__``—**specifically through + functions like** ``get_component()``, ``get_backend()``, and + ``init_backend()``. + + **If your project was** directly importing any of these modules, please + update the imports to use the public API instead.