dcavalca / rpms / systemd

Forked from rpms/systemd 2 years ago
Clone
Anita Zhang 3e5297
From a63d5d320f81c1cbae07897a401ed5cc5374e0bf Mon Sep 17 00:00:00 2001
Anita Zhang 3e5297
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Anita Zhang 3e5297
Date: Wed, 7 Jul 2021 14:37:57 +0200
Anita Zhang 3e5297
Subject: [PATCH 4/5] rpm: restart user services at the end of the transaction
Anita Zhang 3e5297
Anita Zhang 3e5297
This closes an important gap: so far we would reexecute the system manager and
Anita Zhang 3e5297
restart system services that were configured to do so, but we wouldn't do the
Anita Zhang 3e5297
same for user managers or user services.
Anita Zhang 3e5297
Anita Zhang 3e5297
The scheme used for user managers is very similar to the system one, except
Anita Zhang 3e5297
that there can be multiple user managers running, so we query the system
Anita Zhang 3e5297
manager to get a list of them, and then tell each one to do the equivalent
Anita Zhang 3e5297
operations: daemon-reload, disable --now, set-property Markers=+needs-restart,
Anita Zhang 3e5297
reload-or-restart --marked.
Anita Zhang 3e5297
Anita Zhang 3e5297
The total time that can be spend on this is bounded: we execute the commands in
Anita Zhang 3e5297
parallel over user managers and units, and additionally set SYSTEMD_BUS_TIMEOUT
Anita Zhang 3e5297
to a lower value (15 s by default). User managers should not have too many
Anita Zhang 3e5297
units running, and they should be able to do all those operations very
Anita Zhang 3e5297
quickly (<< 1s). The final restart operation may take longer, but it's done
Anita Zhang 3e5297
asynchronously, so we only wait for the queuing to happen.
Anita Zhang 3e5297
Anita Zhang 3e5297
The advantage of doing this synchronously is that we can wait for each step to
Anita Zhang 3e5297
happen, and for example daemon-reloads can finish before we execute the service
Anita Zhang 3e5297
restarts, etc. We can also order various steps wrt. to the phases in the rpm
Anita Zhang 3e5297
transaction.
Anita Zhang 3e5297
Anita Zhang 3e5297
When this was initially proposed, we discussed a more relaxed scheme with bus
Anita Zhang 3e5297
property notifications. Such an approach would be more complex because a bunch
Anita Zhang 3e5297
of infrastructure would have to be added to system manager to propagate
Anita Zhang 3e5297
appropriate notifications to the user managers, and then the user managers
Anita Zhang 3e5297
would have to wait for them. Instead, now there is no new code in the managers,
Anita Zhang 3e5297
all new functionality is contained in src/rpm/. The ability to call 'systemctl
Anita Zhang 3e5297
--user user@' makes this approach very easy. Also, it would be very hard to
Anita Zhang 3e5297
order the user manager steps and the rpm transaction steps.
Anita Zhang 3e5297
Anita Zhang 3e5297
Note: 'systemctl --user disable' is only called for a user managers that are
Anita Zhang 3e5297
running. I don't see a nice way around this, and it shouldn't matter too much:
Anita Zhang 3e5297
we'll just leave a dangling symlink in the case where the user enabled the
Anita Zhang 3e5297
service manually.
Anita Zhang 3e5297
Anita Zhang 3e5297
A follow-up for https://bugzilla.redhat.com/show_bug.cgi?id=1792468 and
Anita Zhang 3e5297
fa97d2fcf64e0558054bee673f734f523373b146.
Anita Zhang 3e5297
Anita Zhang 3e5297
(cherry picked from commit 36d55958ccc75fa3c91bdd7354d74c910f2f6cc7)
Anita Zhang 3e5297
---
Anita Zhang 3e5297
 meson.build                      |  1 +
Anita Zhang 3e5297
 meson_options.txt                |  2 ++
Anita Zhang 3e5297
 src/rpm/macros.systemd.in        |  6 +++-
Anita Zhang 3e5297
 src/rpm/systemd-update-helper.in | 47 ++++++++++++++++++++++++++++++++
Anita Zhang 3e5297
 src/rpm/triggers.systemd.in      | 28 ++++++++++++++++++-
Anita Zhang 3e5297
 src/rpm/triggers.systemd.sh.in   | 13 ++++++++-
Anita Zhang 3e5297
 6 files changed, 94 insertions(+), 3 deletions(-)
Anita Zhang 3e5297
Anita Zhang 3e5297
diff --git a/meson.build b/meson.build
Anita Zhang 3e5297
index fb986e84f7..d898d9ccd0 100644
Anita Zhang 3e5297
--- a/meson.build
Anita Zhang 3e5297
+++ b/meson.build
Anita Zhang 3e5297
@@ -270,6 +270,7 @@ conf.set_quoted('TMPFILES_DIR',                               tmpfilesdir)
Anita Zhang 3e5297
 conf.set_quoted('UDEVLIBEXECDIR',                             udevlibexecdir)
Anita Zhang 3e5297
 conf.set_quoted('UDEV_HWDB_DIR',                              udevhwdbdir)
Anita Zhang 3e5297
 conf.set_quoted('UDEV_RULES_DIR',                             udevrulesdir)
Anita Zhang 3e5297
+conf.set_quoted('UPDATE_HELPER_USER_TIMEOUT',                 get_option('update-helper-user-timeout'))
Anita Zhang 3e5297
 conf.set_quoted('USER_CONFIG_UNIT_DIR',                       join_paths(pkgsysconfdir, 'user'))
Anita Zhang 3e5297
 conf.set_quoted('USER_DATA_UNIT_DIR',                         userunitdir)
Anita Zhang 3e5297
 conf.set_quoted('USER_ENV_GENERATOR_DIR',                     userenvgeneratordir)
Anita Zhang 3e5297
diff --git a/meson_options.txt b/meson_options.txt
Anita Zhang 3e5297
index 163c8df87d..9383c7da6a 100644
Anita Zhang 3e5297
--- a/meson_options.txt
Anita Zhang 3e5297
+++ b/meson_options.txt
Anita Zhang 3e5297
@@ -182,6 +182,8 @@ option('xinitrcdir', type : 'string', value : '',
Anita Zhang 3e5297
        description : 'directory for xinitrc files')
Anita Zhang 3e5297
 option('rpmmacrosdir', type : 'string', value : 'lib/rpm/macros.d',
Anita Zhang 3e5297
        description : 'directory for rpm macros ["no" disables]')
Anita Zhang 3e5297
+option('update-helper-user-timeout', type : 'string', value : '15s',
Anita Zhang 3e5297
+       description : 'how long to wait for user manager operations')
Anita Zhang 3e5297
 option('pamlibdir', type : 'string',
Anita Zhang 3e5297
        description : 'directory for PAM modules')
Anita Zhang 3e5297
 option('pamconfdir', type : 'string',
Anita Zhang 3e5297
diff --git a/src/rpm/macros.systemd.in b/src/rpm/macros.systemd.in
Anita Zhang 3e5297
index bbdf036da7..caa2e45595 100644
Anita Zhang 3e5297
--- a/src/rpm/macros.systemd.in
Anita Zhang 3e5297
+++ b/src/rpm/macros.systemd.in
Anita Zhang 3e5297
@@ -93,7 +93,11 @@ fi \
Anita Zhang 3e5297
 %{nil}
Anita Zhang 3e5297
 
Anita Zhang 3e5297
 %systemd_user_postun_with_restart() \
Anita Zhang 3e5297
-%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_postun_with_restart}} \
Anita Zhang 3e5297
+%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_user_postun_with_restart}} \
Anita Zhang 3e5297
+if [ $1 -ge 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \
Anita Zhang 3e5297
+    # Package upgrade, not uninstall \
Anita Zhang 3e5297
+    {{SYSTEMD_UPDATE_HELPER_PATH}} mark-restart-user-units %{?*} || : \
Anita Zhang 3e5297
+fi \
Anita Zhang 3e5297
 %{nil}
Anita Zhang 3e5297
 
Anita Zhang 3e5297
 %udev_hwdb_update() %{nil}
Anita Zhang 3e5297
diff --git a/src/rpm/systemd-update-helper.in b/src/rpm/systemd-update-helper.in
Anita Zhang 3e5297
index f3c75b75fa..f3466ab3c0 100755
Anita Zhang 3e5297
--- a/src/rpm/systemd-update-helper.in
Anita Zhang 3e5297
+++ b/src/rpm/systemd-update-helper.in
Anita Zhang 3e5297
@@ -26,6 +26,15 @@ case "$command" in
Anita Zhang 3e5297
 
Anita Zhang 3e5297
     remove-user-units)
Anita Zhang 3e5297
         systemctl --global disable "$@"
Anita Zhang 3e5297
+
Anita Zhang 3e5297
+        [ -d /run/systemd/system ] || exit 0
Anita Zhang 3e5297
+
Anita Zhang 3e5297
+        users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')
Anita Zhang 3e5297
+        for user in $users; do
Anita Zhang 3e5297
+            SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
Anita Zhang 3e5297
+                    systemctl --user -M "$user@" disable --now "$@" &
Anita Zhang 3e5297
+        done
Anita Zhang 3e5297
+        wait
Anita Zhang 3e5297
         ;;
Anita Zhang 3e5297
 
Anita Zhang 3e5297
     mark-restart-system-units)
Anita Zhang 3e5297
@@ -37,6 +46,17 @@ case "$command" in
Anita Zhang 3e5297
         wait
Anita Zhang 3e5297
         ;;
Anita Zhang 3e5297
 
Anita Zhang 3e5297
+    mark-restart-user-units)
Anita Zhang 3e5297
+        [ -d /run/systemd/system ] || exit 0
Anita Zhang 3e5297
+
Anita Zhang 3e5297
+        users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')
Anita Zhang 3e5297
+        for user in $users; do
Anita Zhang 3e5297
+            SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
Anita Zhang 3e5297
+                    systemctl --user -M "$user@" set-property "$unit" Markers=+needs-restart &
Anita Zhang 3e5297
+        done
Anita Zhang 3e5297
+        wait
Anita Zhang 3e5297
+        ;;
Anita Zhang 3e5297
+
Anita Zhang 3e5297
     system-reload-restart|system-reload|system-restart)
Anita Zhang 3e5297
         if [ -n "$*" ]; then
Anita Zhang 3e5297
             echo "Unexpected arguments for '$command': $*"
Anita Zhang 3e5297
@@ -54,6 +74,33 @@ case "$command" in
Anita Zhang 3e5297
         fi
Anita Zhang 3e5297
         ;;
Anita Zhang 3e5297
 
Anita Zhang 3e5297
+    user-reload-restart|user-reload|user-restart)
Anita Zhang 3e5297
+        if [ -n "$*" ]; then
Anita Zhang 3e5297
+            echo "Unexpected arguments for '$command': $*"
Anita Zhang 3e5297
+            exit 2
Anita Zhang 3e5297
+        fi
Anita Zhang 3e5297
+
Anita Zhang 3e5297
+        [ -d /run/systemd/system ] || exit 0
Anita Zhang 3e5297
+
Anita Zhang 3e5297
+        users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')
Anita Zhang 3e5297
+
Anita Zhang 3e5297
+        if [[ "$command" =~ reload ]]; then
Anita Zhang 3e5297
+            for user in $users; do
Anita Zhang 3e5297
+                SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
Anita Zhang 3e5297
+                        systemctl --user -M "$user@" daemon-reload &
Anita Zhang 3e5297
+            done
Anita Zhang 3e5297
+            wait
Anita Zhang 3e5297
+        fi
Anita Zhang 3e5297
+
Anita Zhang 3e5297
+        if [[ "$command" =~ restart ]]; then
Anita Zhang 3e5297
+            for user in $users; do
Anita Zhang 3e5297
+                SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
Anita Zhang 3e5297
+                        systemctl --user -M "$user@" reload-or-restart --marked &
Anita Zhang 3e5297
+            done
Anita Zhang 3e5297
+            wait
Anita Zhang 3e5297
+        fi
Anita Zhang 3e5297
+        ;;
Anita Zhang 3e5297
+
Anita Zhang 3e5297
     *)
Anita Zhang 3e5297
         echo "Unknown verb '$command'"
Anita Zhang 3e5297
         exit 3
Anita Zhang 3e5297
diff --git a/src/rpm/triggers.systemd.in b/src/rpm/triggers.systemd.in
Anita Zhang 3e5297
index d29cc33dfd..8aeb2049c1 100644
Anita Zhang 3e5297
--- a/src/rpm/triggers.systemd.in
Anita Zhang 3e5297
+++ b/src/rpm/triggers.systemd.in
Anita Zhang 3e5297
@@ -20,6 +20,14 @@ elseif pid > 0 then
Anita Zhang 3e5297
     posix.wait(pid)
Anita Zhang 3e5297
 end
Anita Zhang 3e5297
 
Anita Zhang 3e5297
+%transfiletriggerin -P 900899 -p <lua> -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
Anita Zhang 3e5297
+pid = posix.fork()
Anita Zhang 3e5297
+if pid == 0 then
Anita Zhang 3e5297
+    assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload-restart"))
Anita Zhang 3e5297
+elseif pid > 0 then
Anita Zhang 3e5297
+    posix.wait(pid)
Anita Zhang 3e5297
+end
Anita Zhang 3e5297
+
Anita Zhang 3e5297
 %transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
Anita Zhang 3e5297
 -- On removal, we need to run daemon-reload after any units have been
Anita Zhang 3e5297
 -- removed.
Anita Zhang 3e5297
@@ -33,8 +41,17 @@ elseif pid > 0 then
Anita Zhang 3e5297
     posix.wait(pid)
Anita Zhang 3e5297
 end
Anita Zhang 3e5297
 
Anita Zhang 3e5297
+%transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
Anita Zhang 3e5297
+-- Execute daemon-reload in user managers.
Anita Zhang 3e5297
+pid = posix.fork()
Anita Zhang 3e5297
+if pid == 0 then
Anita Zhang 3e5297
+    assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload"))
Anita Zhang 3e5297
+elseif pid > 0 then
Anita Zhang 3e5297
+    posix.wait(pid)
Anita Zhang 3e5297
+end
Anita Zhang 3e5297
+
Anita Zhang 3e5297
 %transfiletriggerpostun -P 10000 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
Anita Zhang 3e5297
--- We restart remaining services that should be restarted here.
Anita Zhang 3e5297
+-- We restart remaining system services that should be restarted here.
Anita Zhang 3e5297
 pid = posix.fork()
Anita Zhang 3e5297
 if pid == 0 then
Anita Zhang 3e5297
     assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-restart"))
Anita Zhang 3e5297
@@ -42,6 +59,15 @@ elseif pid > 0 then
Anita Zhang 3e5297
     posix.wait(pid)
Anita Zhang 3e5297
 end
Anita Zhang 3e5297
 
Anita Zhang 3e5297
+%transfiletriggerpostun -P 9999 -p <lua> -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
Anita Zhang 3e5297
+-- We restart remaining user services that should be restarted here.
Anita Zhang 3e5297
+pid = posix.fork()
Anita Zhang 3e5297
+if pid == 0 then
Anita Zhang 3e5297
+    assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-restart"))
Anita Zhang 3e5297
+elseif pid > 0 then
Anita Zhang 3e5297
+    posix.wait(pid)
Anita Zhang 3e5297
+end
Anita Zhang 3e5297
+
Anita Zhang 3e5297
 %transfiletriggerin -P 100700 -p <lua> -- {{SYSUSERS_DIR}}
Anita Zhang 3e5297
 -- This script will process files installed in {{SYSUSERS_DIR}} to create
Anita Zhang 3e5297
 -- specified users automatically. The priority is set such that it
Anita Zhang 3e5297
diff --git a/src/rpm/triggers.systemd.sh.in b/src/rpm/triggers.systemd.sh.in
Anita Zhang 3e5297
index 83cd7617f8..694cd94e8d 100644
Anita Zhang 3e5297
--- a/src/rpm/triggers.systemd.sh.in
Anita Zhang 3e5297
+++ b/src/rpm/triggers.systemd.sh.in
Anita Zhang 3e5297
@@ -16,6 +16,9 @@
Anita Zhang 3e5297
 # so sometimes we will reload needlessly.
Anita Zhang 3e5297
 {{SYSTEMD_UPDATE_HELPER_PATH}} system-reload-restart || :
Anita Zhang 3e5297
 
Anita Zhang 3e5297
+%transfiletriggerin -P 900899 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
Anita Zhang 3e5297
+{{SYSTEMD_UPDATE_HELPER_PATH}} user-reload-restart || :
Anita Zhang 3e5297
+
Anita Zhang 3e5297
 %transfiletriggerpostun -P 1000100 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
Anita Zhang 3e5297
 # On removal, we need to run daemon-reload after any units have been
Anita Zhang 3e5297
 # removed.
Anita Zhang 3e5297
@@ -24,10 +27,18 @@
Anita Zhang 3e5297
 # executed.
Anita Zhang 3e5297
 {{SYSTEMD_UPDATE_HELPER_PATH}} system-reload || :
Anita Zhang 3e5297
 
Anita Zhang 3e5297
+%transfiletriggerpostun -P 1000099 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
Anita Zhang 3e5297
+# Execute daemon-reload in user managers.
Anita Zhang 3e5297
+{{SYSTEMD_UPDATE_HELPER_PATH}} user-reload || :
Anita Zhang 3e5297
+
Anita Zhang 3e5297
 %transfiletriggerpostun -P 10000 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
Anita Zhang 3e5297
-# We restart remaining services that should be restarted here.
Anita Zhang 3e5297
+# We restart remaining system services that should be restarted here.
Anita Zhang 3e5297
 {{SYSTEMD_UPDATE_HELPER_PATH}} system-restart || :
Anita Zhang 3e5297
 
Anita Zhang 3e5297
+%transfiletriggerpostun -P  9999 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
Anita Zhang 3e5297
+# We restart remaining user services that should be restarted here.
Anita Zhang 3e5297
+{{SYSTEMD_UPDATE_HELPER_PATH}} user-restart || :
Anita Zhang 3e5297
+
Anita Zhang 3e5297
 %transfiletriggerin -P 1000700 -- {{SYSUSERS_DIR}}
Anita Zhang 3e5297
 # This script will process files installed in {{SYSUSERS_DIR}} to create
Anita Zhang 3e5297
 # specified users automatically. The priority is set such that it
Anita Zhang 3e5297
-- 
Anita Zhang 3e5297
2.31.1
Anita Zhang 3e5297