]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
controller: change to notify_socket.py module docs-python-contr-ub4loz/deployments/9676 python-controller-notify
authorAleš Mrázek <ales.mrazek@nic.cz>
Wed, 29 Jul 2026 15:03:52 +0000 (17:03 +0200)
committerAleš Mrázek <ales.mrazek@nic.cz>
Wed, 29 Jul 2026 21:36:26 +0000 (23:36 +0200)
Store original NOTIFY_SOCKET value.
Remove obsolete systemd_notify.py module from utils.

python/knot_resolver/controller/supervisord/plugin/manager_integration.py
python/knot_resolver/controller/supervisord/plugin/sd_notify.py
python/knot_resolver/manager/server.py
python/knot_resolver/utils/systemd_notify.py [deleted file]

index 6c575b956a932d5039865aa30fb7476438da5283..05647896250845f2b9cac1b5ba7e44d69a7da9dc 100644 (file)
@@ -12,11 +12,14 @@ from supervisor.process import Subprocess
 from supervisor.states import SupervisorStates
 from supervisor.supervisord import Supervisor
 
-from knot_resolver.utils.systemd_notify import systemd_notify
+from .notify_socket import send_notify_socket_message, NOTIFY_SOCKET
 
 superd: Optional[Supervisor] = None
 
 
+SYSTEMD_NOTIFY_SOCKET: Optional[str] = os.environ.get(NOTIFY_SOCKET)
+
+
 def check_for_fatal_manager(event: ProcessStateFatalEvent) -> None:
     assert superd is not None
 
@@ -38,7 +41,7 @@ def check_for_starting_manager(event: ProcessStateStartingEvent) -> None:
     processname = as_string(proc.config.name)
     if processname == "manager":
         # manager has sucessfully started, report it upstream
-        systemd_notify(STATUS="Starting services...")
+        send_notify_socket_message(SYSTEMD_NOTIFY_SOCKET, STATUS="Starting services...")
 
 
 def check_for_runnning_manager(event: ProcessStateRunningEvent) -> None:
@@ -48,7 +51,7 @@ def check_for_runnning_manager(event: ProcessStateRunningEvent) -> None:
     processname = as_string(proc.config.name)
     if processname == "manager":
         # manager has sucessfully started, report it upstream
-        systemd_notify(READY="1", STATUS="Ready")
+        send_notify_socket_message(SYSTEMD_NOTIFY_SOCKET, READY="1", STATUS="Ready")
 
 
 def get_server_options_signal(self):
@@ -69,7 +72,7 @@ def inject(supervisord: Supervisor, **_config: Any) -> Any:  # pylint: disable=u
     # This status notification here unsets the env variable $NOTIFY_SOCKET provided by systemd
     # and stores it locally. Therefore, it shouldn't clash with $NOTIFY_SOCKET we are providing
     # downstream
-    systemd_notify(STATUS="Initializing supervisord...")
+    send_notify_socket_message(SYSTEMD_NOTIFY_SOCKET, STATUS="Initializing supervisord...")
 
     # register events
     subscribe(ProcessStateFatalEvent, check_for_fatal_manager)
index dea4ed8e7a6244287f9abf8f85a3433ec2d4d2c4..4973924563271aa49b0019aaacab7bb64478bcc3 100644 (file)
@@ -9,6 +9,7 @@ if NOTIFY_SUPPORT:
     import signal
     import time
     from functools import partial
+    from pathlib import Path
     from typing import Any, Callable, Dict, List, Optional, Tuple, TypeVar
 
     from supervisor.events import ProcessStateEvent, ProcessStateStartingEvent, subscribe
@@ -17,7 +18,12 @@ if NOTIFY_SUPPORT:
     from supervisor.states import ProcessStates
     from supervisor.supervisord import Supervisor
 
-    from knot_resolver.controller.supervisord.plugin import notify
+    from knot_resolver.controller.supervisord.plugin.notify_socket import (
+        init_notify_socket,
+        read_notify_socket,
+        NOTIFY_SOCKET,
+        NOTIFY_SOCKET_NAME,
+    )
 
     starting_processes: List[Subprocess] = []
 
@@ -34,7 +40,7 @@ if NOTIFY_SUPPORT:
         def __init__(self, supervisor: Supervisor, fd: int):
             self._supervisor = supervisor
             self.fd = fd
-            self.closed = False  # True if close() has been called
+            self.closed: bool = False  # True if close() has been called
 
         def __repr__(self):
             return f"<{self.__class__.__name__} with fd={self.fd}>"
@@ -48,10 +54,11 @@ if NOTIFY_SUPPORT:
         def handle_read_event(self):
             logger: Any = self._supervisor.options.logger
 
-            res: Optional[Tuple[int, bytes]] = notify.read_message(self.fd)
-            if res is None:
+            result: tuple[int, bytes, None] = read_notify_socket(self.fd)
+            if result is None:
                 return  # there was some junk
-            pid, data = res
+
+            pid, data = result
 
             # pylint: disable=undefined-loop-variable
             for proc in starting_processes:
@@ -162,7 +169,7 @@ if NOTIFY_SUPPORT:
     def supervisord_get_process_map(supervisord: Any, mp: Dict[Any, Any]) -> Dict[Any, Any]:
         global notify_dispatcher
         if notify_dispatcher is None:
-            notify_dispatcher = NotifySocketDispatcher(supervisord, notify.init_socket())
+            notify_dispatcher = NotifySocketDispatcher(supervisord, init_notify_socket())
             supervisord.options.logger.info("notify: injected $NOTIFY_SOCKET into event loop")
 
         # add our dispatcher to the result
@@ -173,7 +180,7 @@ if NOTIFY_SUPPORT:
 
     def process_spawn_as_child_add_env(slf: Subprocess, *args: Any) -> Tuple[Any, ...]:
         if is_type_notify(slf):
-            slf.config.environment["NOTIFY_SOCKET"] = os.getcwd() + "/supervisor-notify-socket"
+            slf.config.environment[NOTIFY_SOCKET] = str(Path.cwd() / NOTIFY_SOCKET_NAME)
         return (slf, *args)
 
     T = TypeVar("T")
index 0c907230f439bc861ac7ceeb2b339296f1bb7e33..1c57bbdc52a39781ebc5bef3ca34c3a2b3e3f17d 100644 (file)
@@ -23,6 +23,7 @@ from knot_resolver.controller import get_best_controller_implementation
 from knot_resolver.controller.exceptions import KresSubprocessControllerError, KresSubprocessControllerExec
 from knot_resolver.controller.interface import SubprocessType
 from knot_resolver.controller.registered_workers import command_single_registered_worker
+from knot_resolver.controller.supervisord.plugin.notify_socket import send_notify_socket_message
 from knot_resolver.datamodel import kres_config_json_schema
 from knot_resolver.datamodel.cache_schema import CacheClearRPCSchema
 from knot_resolver.datamodel.config_schema import KresConfig, get_rundir_without_validation
@@ -40,7 +41,6 @@ from knot_resolver.utils.modeling.exceptions import AggregateDataValidationError
 from knot_resolver.utils.modeling.parsing import DataFormat, data_combine, try_to_parse
 from knot_resolver.utils.modeling.query import query
 from knot_resolver.utils.modeling.types import NoneType
-from knot_resolver.utils.systemd_notify import systemd_notify
 
 from .config_store import ConfigStore
 from .constants import PID_FILE_NAME, init_user_constants
@@ -172,9 +172,9 @@ class Server:
 
     async def sighup_handler(self) -> None:
         logger.info("Received SIGHUP, reloading configuration file")
-        systemd_notify(RELOADING="1")
+        send_notify_socket_message(RELOADING="1")
         await self._reload_config()
-        systemd_notify(READY="1")
+        send_notify_socket_message(READY="1")
 
     @staticmethod
     def all_handled_signals() -> Set[signal.Signals]:
@@ -681,12 +681,12 @@ async def start_server(config: List[str]) -> int:  # noqa: C901, PLR0915
     logger.info(f"Manager fully initialized and running in {round(time() - start_time, 3)} seconds")
 
     # notify systemd/anything compatible that we are ready
-    systemd_notify(READY="1")
+    send_notify_socket_message(READY="1")
 
     await server.wait_for_shutdown()
 
     # notify systemd that we are shutting down
-    systemd_notify(STOPPING="1")
+    send_notify_socket_message(STOPPING="1")
 
     # Ok, now we are tearing everything down.
 
diff --git a/python/knot_resolver/utils/systemd_notify.py b/python/knot_resolver/utils/systemd_notify.py
deleted file mode 100644 (file)
index bf0221c..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-import logging
-import os
-import socket
-
-logger = logging.getLogger(__name__)
-
-
-def systemd_notify(**values: str) -> None:
-    """
-    Send systemd notify message to notify socket.
-
-    Notify socket location (unix socket) should be saved in $NOTIFY_SOCKET environment variable.
-    It is typically set by the processes supervisor (supervisord).
-    If $NOTIFY_SOCKET is not configured, it is not possible to send a notification and the operation will fail.
-    """
-    socket_addr = os.getenv("NOTIFY_SOCKET")
-    if socket_addr is None:
-        logger.warning("Failed to get $NOTIFY_SOCKET environment variable")
-        return
-
-    if socket_addr.startswith("@"):
-        socket_addr = socket_addr.replace("@", "\0", 1)
-
-    try:
-        notify_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
-        notify_socket.connect(socket_addr)
-    except OSError:
-        logger.exception("Failed to connect to $NOTIFY_SOCKET at '%s'", socket_addr)
-        return
-
-    payload = "\n".join((f"{key}={value}" for key, value in values.items()))
-    try:
-        notify_socket.send(payload.encode("utf8"))
-    except OSError:
-        logger.exception("Failed to send systemd notification to $NOTIFY_SOCKET at '%s'", socket_addr)
-
-    notify_socket.close()