]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
manager: supervisord plugins: using sd_notify to report state upstream
authorVasek Sraier <git@vakabus.cz>
Tue, 12 Jul 2022 11:33:51 +0000 (13:33 +0200)
committerVasek Sraier <git@vakabus.cz>
Sun, 31 Jul 2022 15:26:39 +0000 (17:26 +0200)
manager/knot-resolver.service
manager/knot_resolver_manager/kresd_controller/supervisord/plugin/manager_lifecycle_monitor.py [new file with mode: 0644]
manager/knot_resolver_manager/kresd_controller/supervisord/plugin/stop_when_manager_fatal.py [deleted file]
manager/knot_resolver_manager/kresd_controller/supervisord/supervisord.conf.j2

index 9abbfba58696a2d116e052207ac160fddb64d47e..8295f3668406590cd8e304061ba09cdf2913ae5d 100644 (file)
@@ -2,6 +2,8 @@
 Description=Knot Resolver Manager
 
 [Service]
+Type=notify
+TimeoutStartSec=10s
 ExecStart=/usr/bin/env python3 -m knot_resolver_manager --config=/etc/knot-resolver/config.yml
 KillSignal=SIGINT
 # See systemd.service(5) for explanation, why we should replace this with a blocking request
diff --git a/manager/knot_resolver_manager/kresd_controller/supervisord/plugin/manager_lifecycle_monitor.py b/manager/knot_resolver_manager/kresd_controller/supervisord/plugin/manager_lifecycle_monitor.py
new file mode 100644 (file)
index 0000000..024badc
--- /dev/null
@@ -0,0 +1,69 @@
+# type: ignore
+# pylint: disable=protected-access
+import atexit
+import os
+from typing import Any, Optional
+
+from supervisor.compat import as_string
+from supervisor.events import ProcessStateFatalEvent, ProcessStateRunningEvent, ProcessStateStartingEvent, subscribe
+from supervisor.process import Subprocess
+from supervisor.states import SupervisorStates
+from supervisor.supervisord import Supervisor
+
+from knot_resolver_manager.utils.systemd_notify import systemd_notify
+
+superd: Optional[Supervisor] = None
+
+
+def check_for_fatal_manager(event: ProcessStateFatalEvent) -> None:
+    assert superd is not None
+
+    proc: Subprocess = event.process
+    processname = as_string(proc.config.name)
+    if processname == "manager":
+        # stop the whole supervisord gracefully
+        superd.options.logger.critical("manager process entered FATAL state! Shutting down")
+        superd.options.mood = SupervisorStates.SHUTDOWN
+
+        # force the interpreter to exit with exit code 1
+        atexit.register(lambda: os._exit(1))
+
+
+def check_for_starting_manager(event: ProcessStateStartingEvent) -> None:
+    assert superd is not None
+
+    proc: Subprocess = event.process
+    processname = as_string(proc.config.name)
+    if processname == "manager":
+        # manager has sucessfully started, report it upstream
+        systemd_notify(STATUS="Starting services...")
+
+
+def check_for_runnning_manager(event: ProcessStateRunningEvent) -> None:
+    assert superd is not None
+
+    proc: Subprocess = event.process
+    processname = as_string(proc.config.name)
+    if processname == "manager":
+        # manager has sucessfully started, report it upstream
+        systemd_notify(READY="1", STATUS="Ready")
+
+
+def make_rpcinterface(supervisord: Supervisor, **_config: Any) -> Any:  # pylint: disable=useless-return
+    global superd
+    superd = supervisord
+
+    # 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...")
+
+    # register events
+    subscribe(ProcessStateFatalEvent, check_for_fatal_manager)
+    subscribe(ProcessStateStartingEvent, check_for_starting_manager)
+    subscribe(ProcessStateRunningEvent, check_for_runnning_manager)
+
+    # this method is called by supervisord when loading the plugin,
+    # it should return XML-RPC object, which we don't care about
+    # That's why why are returning just None
+    return None
diff --git a/manager/knot_resolver_manager/kresd_controller/supervisord/plugin/stop_when_manager_fatal.py b/manager/knot_resolver_manager/kresd_controller/supervisord/plugin/stop_when_manager_fatal.py
deleted file mode 100644 (file)
index ff1973a..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-# type: ignore
-# pylint: disable=protected-access
-import atexit
-import os
-from typing import Any, Optional
-
-from supervisor.compat import as_string
-from supervisor.events import ProcessStateFatalEvent, subscribe
-from supervisor.process import Subprocess
-from supervisor.states import SupervisorStates
-from supervisor.supervisord import Supervisor
-
-superd: Optional[Supervisor] = None
-
-
-def check_for_fatal_manager(event: ProcessStateFatalEvent) -> None:
-    assert superd is not None
-
-    proc: Subprocess = event.process
-    processname = as_string(proc.config.name)
-    if processname == "manager":
-        # stop the whole supervisord gracefully
-        superd.options.logger.critical("manager process entered FATAL state! Shutting down")
-        superd.options.mood = SupervisorStates.SHUTDOWN
-
-        # force the interpreter to exit with exit code 1
-        atexit.register(lambda: os._exit(1))
-
-
-def make_rpcinterface(supervisord: Supervisor, **_config: Any) -> Any:  # pylint: disable=useless-return
-    global superd
-    superd = supervisord
-    subscribe(ProcessStateFatalEvent, check_for_fatal_manager)
-
-    # this method is called by supervisord when loading the plugin,
-    # it should return XML-RPC object, which we don't care about
-    # That's why why are returning just None
-    return None
index 394776e22d63cf96246bb6f4c2b9657d7ba9b701..c77913eaa534c85e100b2e0026282abd44b854ee 100644 (file)
@@ -22,11 +22,12 @@ supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
 supervisor.rpcinterface_factory = knot_resolver_manager.kresd_controller.supervisord.plugin.fast_rpcinterface:make_main_rpcinterface
 
 {# Extensions to changing the supervisord behavior #}
+[rpcinterface:manager_lifecycle_monitor]
+supervisor.rpcinterface_factory = knot_resolver_manager.kresd_controller.supervisord.plugin.manager_lifecycle_monitor:make_rpcinterface
+
 [rpcinterface:notify]
 supervisor.rpcinterface_factory = knot_resolver_manager.kresd_controller.supervisord.plugin:make_rpcinterface
 
-[rpcinterface:fatal_manager]
-supervisor.rpcinterface_factory = knot_resolver_manager.kresd_controller.supervisord.plugin.stop_when_manager_fatal:make_rpcinterface
 
 [program:manager]
 redirect_stderr=false