From: Lennart Poettering Date: Tue, 12 Mar 2024 15:08:13 +0000 (+0100) Subject: core: notify supervisor over targets we reach, as we reach them X-Git-Tag: v256-rc1~521^2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b2d6bb5b34c89f6db65273bd42ec54c97efa33d8;p=thirdparty%2Fsystemd.git core: notify supervisor over targets we reach, as we reach them Let's inform the the supervisor about various happenings of our service manager, specifically the boot milestones we reach. We so far have only a singular READY=1 message, to inform about bootup completion. But sometimes it is interesting to have something for finegrained, in particular something that indicates optional components that have been activated. Usecase for this: in a later PR I intend to introduce a generic "ssh.target" that is supposed to be activated when SSH becomes available on a host. A supervisor (i.e. a VMM/hypervisor/container mgr/…) can watch for that, and know two things: 1. that SSH is generally available in the system 2. when it is available In order to not flood the supervisor with events I only send these out for target units. We could open this up later, in theory, but I think it makes sense to tell people instead to define clear milestone target units if they want a supervisor to be able to track system state. --- diff --git a/src/core/manager.c b/src/core/manager.c index 2ef8ad90daa..da510cd04ec 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -3424,6 +3424,27 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) { "Failed to communicate with plymouth: %m"); } +void manager_send_unit_supervisor(Manager *m, Unit *u, bool active) { + assert(m); + assert(u); + + /* Notify a "supervisor" process about our progress, i.e. a container manager, hypervisor, or + * surrounding service manager. */ + + if (MANAGER_IS_RELOADING(m)) + return; + + if (!UNIT_VTABLE(u)->notify_supervisor) + return; + + if (in_initrd()) /* Only send these once we left the initrd */ + return; + + (void) sd_notifyf(/* unset_environment= */ false, + active ? "X_SYSTEMD_UNIT_ACTIVE=%s" : "X_SYSTEMD_UNIT_INACTIVE=%s", + u->id); +} + usec_t manager_get_watchdog(Manager *m, WatchdogType t) { assert(m); diff --git a/src/core/manager.h b/src/core/manager.h index 9f1a21b22db..4d82c4a6a0d 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -575,6 +575,7 @@ void manager_reset_failed(Manager *m); void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success); void manager_send_unit_plymouth(Manager *m, Unit *u); +void manager_send_unit_supervisor(Manager *m, Unit *u, bool active); bool manager_unit_inactive_or_pending(Manager *m, const char *name); diff --git a/src/core/target.c b/src/core/target.c index 8f2a331f92b..3851f21442d 100644 --- a/src/core/target.c +++ b/src/core/target.c @@ -213,4 +213,6 @@ const UnitVTable target_vtable = { [JOB_DONE] = "Stopped target %s.", }, }, + + .notify_supervisor = true, }; diff --git a/src/core/unit.c b/src/core/unit.c index 2c6a0b3e572..c0f802a1375 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2678,12 +2678,14 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su unit_emit_audit_start(u); manager_send_unit_plymouth(m, u); + manager_send_unit_supervisor(m, u, /* active= */ true); } if (UNIT_IS_INACTIVE_OR_FAILED(ns) && !UNIT_IS_INACTIVE_OR_FAILED(os)) { /* This unit just stopped/failed. */ unit_emit_audit_stop(u, ns); + manager_send_unit_supervisor(m, u, /* active= */ false); unit_log_resources(u); } diff --git a/src/core/unit.h b/src/core/unit.h index b1cc2c2d013..7134d362fe1 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -731,6 +731,9 @@ typedef struct UnitVTable { /* If true, we'll notify plymouth about this unit */ bool notify_plymouth; + /* If true, we'll notify a surrounding VMM/container manager about this unit becoming available */ + bool notify_supervisor; + /* The audit events to generate on start + stop (or 0 if none shall be generated) */ int audit_start_message_type; int audit_stop_message_type;