]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Add self-contained Python sd_notify example.
authorSimon Fowler <simon.fowler@anu.edu.au>
Tue, 23 Apr 2024 04:27:58 +0000 (14:27 +1000)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 23 Apr 2024 15:03:01 +0000 (17:03 +0200)
This complements the existing C example.

man/notify-selfcontained-example.py [new file with mode: 0644]
man/sd_notify.xml

diff --git a/man/notify-selfcontained-example.py b/man/notify-selfcontained-example.py
new file mode 100644 (file)
index 0000000..a1efb41
--- /dev/null
@@ -0,0 +1,104 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: MIT-0
+#
+# Implement the systemd notify protocol without external dependencies.
+# Supports both readiness notification on startup and on reloading,
+# according to the protocol defined at:
+# https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html
+# This protocol is guaranteed to be stable as per:
+# https://systemd.io/PORTABILITY_AND_STABILITY/
+
+import errno
+import os
+import signal
+import socket
+import sys
+import time
+
+reloading = False
+terminating = False
+
+def notify(message):
+    if not message:
+        raise ValueError("notify() requires a message")
+
+    socket_path = os.environ.get("NOTIFY_SOCKET")
+    if not socket_path:
+        return
+
+    if socket_path[0] not in ("/", "@"):
+        raise OSError(errno.EAFNOSUPPORT, "Unsupported socket type")
+
+    # Handle abstract socket.
+    if socket_path[0] == "@":
+        socket_path = "\0" + socket_path[1:]
+
+    with socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM | socket.SOCK_CLOEXEC) as sock:
+        sock.connect(socket_path)
+        sock.sendall(message)
+
+def notify_ready():
+    notify(b"READY=1")
+
+def notify_reloading():
+    microsecs = time.clock_gettime_ns(time.CLOCK_MONOTONIC) // 1000
+    notify(f"RELOADING=1\nMONOTONIC_USEC={microsecs}".encode())
+
+def notify_stopping():
+    notify(b"STOPPING=1")
+
+def reload(signum, frame):
+    global reloading
+    reloading = True
+
+def terminate(signum, frame):
+    global terminating
+    terminating = True
+
+def main():
+    print("Doing initial setup")
+    global reloading, terminating
+
+    # Set up signal handlers.
+    print("Setting up signal handlers")
+    signal.signal(signal.SIGHUP, reload)
+    signal.signal(signal.SIGINT, terminate)
+    signal.signal(signal.SIGTERM, terminate)
+
+    # Do any other setup work here.
+
+    # Once all setup is done, signal readiness.
+    print("Done setting up")
+    notify_ready()
+
+    print("Starting loop")
+    while not terminating:
+        if reloading:
+            print("Reloading")
+            reloading = False
+
+            # Support notifying the manager when reloading configuration.
+            # This allows accurate state tracking as well as automatically
+            # enabling 'systemctl reload' without needing to manually
+            # specify an ExecReload= line in the unit file.
+
+            notify_reloading()
+
+            # Do some reconfiguration work here.
+
+            print("Done reloading")
+            notify_ready()
+
+        # Do the real work here ...
+
+        print("Sleeping for five seconds")
+        time.sleep(5)
+
+    print("Terminating")
+    notify_stopping()
+
+if __name__ == "__main__":
+    sys.stdout.reconfigure(line_buffering=True)
+    print("Starting app")
+    main()
+    print("Stopped app")
index e1c4073e7fc3292e47b6d0c67f1df5a96ac6edfa..c6490d370cdafec8b117ac61b8e2f947303ee128 100644 (file)
     the guest might try to send malicious notifications to the host, driving it to make destructive decisions
     based on them.</para>
 
-    <para>Note that, while using this library should be preferred in order to avoid code duplication, it is
-    also possible to reimplement the simple readiness notification protocol without external dependencies,
-    as demonstrated in the following self-contained example:
-    <programlisting><xi:include href="notify-selfcontained-example.c" parse="text"/></programlisting></para>
+    <refsect2>
+      <title>Standalone Implementations</title>
+      <para>Note that, while using this library should be preferred in order to avoid code duplication, it is
+      also possible to reimplement the simple readiness notification protocol without external dependencies,
+      as demonstrated in the following self-contained examples from several languages:</para>
+      <refsect3>
+        <title>C</title>
+        <programlisting><xi:include href="notify-selfcontained-example.c" parse="text"/></programlisting>
+      </refsect3>
+      <refsect3>
+        <title>Python</title>
+        <programlisting><xi:include href="notify-selfcontained-example.py" parse="text"/></programlisting>
+      </refsect3>
+    </refsect2>
   </refsect1>
 
   <refsect1>