We have a way to notify systemd when we're done starting the daemon.
Systemd supports many more notifications, however, and many of them
are quite relevant to our needs:
https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html
This renames the existing notification API to better reflect its
semantics, and adds new APIs for reporting
* Initiation of config file reload
* Initiation of daemon shutdown process
* Adhoc progress status messages
* Request to extend service shutdown timeout
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
src/libvirt_private.syms | 6 +++++-
src/rpc/virnetdaemon.c | 2 +-
src/util/virsystemd.c | 44 +++++++++++++++++++++++++++++++++++++---
src/util/virsystemd.h | 6 +++++-
4 files changed, 52 insertions(+), 6 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6888f6b599..4eca252b2a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -3531,7 +3531,11 @@ virSystemdHasResolved;
virSystemdHasResolvedResetCachedValue;
virSystemdMakeScopeName;
virSystemdMakeSliceName;
-virSystemdNotifyStartup;
+virSystemdNotifyExtendTimeout;
+virSystemdNotifyReady;
+virSystemdNotifyReload;
+virSystemdNotifyStatus;
+virSystemdNotifyStopping;
virSystemdResolvedRegisterNameServer;
virSystemdTerminateMachine;
diff --git a/src/rpc/virnetdaemon.c b/src/rpc/virnetdaemon.c
index f647cf60ba..e6bdfe0f88 100644
--- a/src/rpc/virnetdaemon.c
+++ b/src/rpc/virnetdaemon.c
@@ -753,7 +753,7 @@ virNetDaemonRun(virNetDaemon *dmn)
/* We are accepting connections now. Notify systemd
* so it can start dependent services. */
- virSystemdNotifyStartup();
+ virSystemdNotifyReady();
VIR_DEBUG("dmn=%p quit=%d", dmn, dmn->quit);
while (!dmn->finished) {
diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c
index d46e5f74fc..bbcf77a41f 100644
--- a/src/util/virsystemd.c
+++ b/src/util/virsystemd.c
@@ -624,12 +624,11 @@ int virSystemdTerminateMachine(const char *name)
return 0;
}
-void
-virSystemdNotifyStartup(void)
+static void
+virSystemdNotify(const char *msg)
{
#ifndef WIN32
const char *path;
- const char *msg = "READY=1";
int fd;
struct sockaddr_un un = {
.sun_family = AF_UNIX,
@@ -644,6 +643,8 @@ virSystemdNotifyStartup(void)
.msg_iovlen = 1,
};
+ VIR_DEBUG("Notify '%s'", msg);
+
if (!(path = getenv("NOTIFY_SOCKET"))) {
VIR_DEBUG("Skipping systemd notify, not requested");
return;
@@ -674,6 +675,43 @@ virSystemdNotifyStartup(void)
#endif /* !WIN32 */
}
+void virSystemdNotifyReady(void)
+{
+ virSystemdNotify("READY=1");
+}
+
+void virSystemdNotifyReload(void)
+{
+ gint64 now = g_get_monotonic_time();
+ g_autofree char *msg = g_strdup_printf(
+ "RELOADING=1\nMONOTONIC_USEC=%lld", (long long int)now);
+ virSystemdNotify(msg);
+}
+
+void virSystemdNotifyStopping(void)
+{
+ virSystemdNotify("STOPPING=1");
+}
+
+void virSystemdNotifyExtendTimeout(int secs)
+{
+ g_autofree char *msg = g_strdup_printf("EXTEND_TIMEOUT_USEC=%llu",
+ secs * 1000ull * 1000ul);
+ virSystemdNotify(msg);
+}
+
+void virSystemdNotifyStatus(const char *fmt, ...)
+{
+ g_autofree char *msg1 = NULL;
+ g_autofree char *msg2 = NULL;
+ va_list ap;
+ va_start(ap, fmt);
+ msg1 = g_strdup_vprintf(fmt, ap);
+ va_end(ap);
+ msg2 = g_strdup_printf("STATUS=%s", msg1);
+ virSystemdNotify(msg2);
+}
+
static int
virSystemdPMSupportTarget(const char *methodName, bool *result)
{
diff --git a/src/util/virsystemd.h b/src/util/virsystemd.h
index b7fdaf67df..98460dbc3a 100644
--- a/src/util/virsystemd.h
+++ b/src/util/virsystemd.h
@@ -44,7 +44,11 @@ int virSystemdCreateMachine(const char *name,
int virSystemdTerminateMachine(const char *name);
-void virSystemdNotifyStartup(void);
+void virSystemdNotifyReady(void);
+void virSystemdNotifyReload(void);
+void virSystemdNotifyStopping(void);
+void virSystemdNotifyExtendTimeout(int secs);
+void virSystemdNotifyStatus(const char *fmt, ...) G_GNUC_PRINTF(1, 2);
int virSystemdHasMachined(void);
--
2.47.1
On Wed, Feb 12, 2025 at 15:46:41 +0000, Daniel P. Berrangé wrote:
> We have a way to notify systemd when we're done starting the daemon.
>
> Systemd supports many more notifications, however, and many of them
> are quite relevant to our needs:
>
> https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html
>
> This renames the existing notification API to better reflect its
> semantics, and adds new APIs for reporting
>
> * Initiation of config file reload
> * Initiation of daemon shutdown process
> * Adhoc progress status messages
> * Request to extend service shutdown timeout
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
> src/libvirt_private.syms | 6 +++++-
> src/rpc/virnetdaemon.c | 2 +-
> src/util/virsystemd.c | 44 +++++++++++++++++++++++++++++++++++++---
> src/util/virsystemd.h | 6 +++++-
> 4 files changed, 52 insertions(+), 6 deletions(-)
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 6888f6b599..4eca252b2a 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -3531,7 +3531,11 @@ virSystemdHasResolved;
> virSystemdHasResolvedResetCachedValue;
> virSystemdMakeScopeName;
> virSystemdMakeSliceName;
> -virSystemdNotifyStartup;
> +virSystemdNotifyExtendTimeout;
> +virSystemdNotifyReady;
> +virSystemdNotifyReload;
> +virSystemdNotifyStatus;
> +virSystemdNotifyStopping;
> virSystemdResolvedRegisterNameServer;
> virSystemdTerminateMachine;
>
> diff --git a/src/rpc/virnetdaemon.c b/src/rpc/virnetdaemon.c
> index f647cf60ba..e6bdfe0f88 100644
> --- a/src/rpc/virnetdaemon.c
> +++ b/src/rpc/virnetdaemon.c
> @@ -753,7 +753,7 @@ virNetDaemonRun(virNetDaemon *dmn)
>
> /* We are accepting connections now. Notify systemd
> * so it can start dependent services. */
> - virSystemdNotifyStartup();
> + virSystemdNotifyReady();
>
> VIR_DEBUG("dmn=%p quit=%d", dmn, dmn->quit);
> while (!dmn->finished) {
> diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c
> index d46e5f74fc..bbcf77a41f 100644
> --- a/src/util/virsystemd.c
> +++ b/src/util/virsystemd.c
> @@ -624,12 +624,11 @@ int virSystemdTerminateMachine(const char *name)
> return 0;
> }
>
> -void
> -virSystemdNotifyStartup(void)
> +static void
> +virSystemdNotify(const char *msg)
> {
> #ifndef WIN32
> const char *path;
> - const char *msg = "READY=1";
> int fd;
> struct sockaddr_un un = {
> .sun_family = AF_UNIX,
> @@ -644,6 +643,8 @@ virSystemdNotifyStartup(void)
> .msg_iovlen = 1,
> };
>
> + VIR_DEBUG("Notify '%s'", msg);
> +
> if (!(path = getenv("NOTIFY_SOCKET"))) {
> VIR_DEBUG("Skipping systemd notify, not requested");
> return;
> @@ -674,6 +675,43 @@ virSystemdNotifyStartup(void)
> #endif /* !WIN32 */
> }
>
> +void virSystemdNotifyReady(void)
> +{
> + virSystemdNotify("READY=1");
> +}
> +
> +void virSystemdNotifyReload(void)
> +{
> + gint64 now = g_get_monotonic_time();
> + g_autofree char *msg = g_strdup_printf(
> + "RELOADING=1\nMONOTONIC_USEC=%lld", (long long int)now);
> + virSystemdNotify(msg);
> +}
> +
> +void virSystemdNotifyStopping(void)
> +{
> + virSystemdNotify("STOPPING=1");
> +}
> +
> +void virSystemdNotifyExtendTimeout(int secs)
> +{
> + g_autofree char *msg = g_strdup_printf("EXTEND_TIMEOUT_USEC=%llu",
> + secs * 1000ull * 1000ul);
'ull' in the second 1000
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
© 2016 - 2025 Red Hat, Inc.