summaryrefslogtreecommitdiff
path: root/src/core/dbus-manager.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-01-30 19:44:15 +0100
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-02-15 20:49:14 +0100
commit70666e28a1affe241a9c4a6fb26aecdf7ce5d167 (patch)
tree5bb61031c25ac92554755139c4acb121adf38a94 /src/core/dbus-manager.c
parent0dd3c0907f42774dccd79658d744a5a75c72ef58 (diff)
downloadsystemd-70666e28a1affe241a9c4a6fb26aecdf7ce5d167.tar.gz
core: add EnqueueMarkedJobs method to reload/restart marked units
We support two return types for methods that start jobs. EnqueueJob support the full-monty mode with affected jobs. I didn't do this here, since it seems unlikely to be used. In the common case there'd be a huge list of jobs and affected jobs. EnqueueMarkedJobs() just returns a list of jobs that we can wait upon. The name of the method is generic in case we decide to add something other than just reload/restart later on. When errors occur, resource errors are treated as fatal, but for other error types we queue up other jobs, and only return an error at the end. The assumption is that the caller will ignore the result error anyway, so it's better to try to reload/restart as much as possible.
Diffstat (limited to 'src/core/dbus-manager.c')
-rw-r--r--src/core/dbus-manager.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 9053d48149..c4b7aa427b 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -1807,6 +1807,75 @@ static int method_get_dynamic_users(sd_bus_message *message, void *userdata, sd_
return sd_bus_send(NULL, reply, NULL);
}
+static int method_enqueue_marked_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+ int r;
+
+ assert(message);
+ assert(m);
+
+ r = mac_selinux_access_check(message, "start", error);
+ if (r < 0)
+ return r;
+
+ r = bus_verify_manage_units_async(m, message, error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+
+ log_info("Queuing reload/restart jobs for marked units…");
+
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ r = sd_bus_message_new_method_return(message, &reply);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(reply, 'a', "o");
+ if (r < 0)
+ return r;
+
+ Unit *u;
+ char *k;
+ int ret = 0;
+ HASHMAP_FOREACH_KEY(u, k, m->units) {
+ /* ignore aliases */
+ if (u->id != k)
+ continue;
+
+ BusUnitQueueFlags flags;
+ if (FLAGS_SET(u->markers, 1u << UNIT_MARKER_NEEDS_RESTART))
+ flags = 0;
+ else if (FLAGS_SET(u->markers, 1u << UNIT_MARKER_NEEDS_RELOAD))
+ flags = BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE;
+ else
+ continue;
+
+ r = mac_selinux_unit_access_check(u, message, "start", error);
+ if (r >= 0)
+ r = bus_unit_queue_job_one(message, u,
+ JOB_TRY_RESTART, JOB_FAIL, flags,
+ reply, error);
+ if (r < 0) {
+ if (ERRNO_IS_RESOURCE(r))
+ return r;
+ if (ret >= 0)
+ ret = r;
+ sd_bus_error_free(error);
+ }
+ }
+
+ if (ret < 0)
+ return sd_bus_error_set_errnof(error, ret,
+ "Failed to enqueue some jobs, see logs for details: %m");
+
+ r = sd_bus_message_close_container(reply);
+ if (r < 0)
+ return r;
+
+ return sd_bus_send(NULL, reply, NULL);
+}
+
static int list_unit_files_by_patterns(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states, char **patterns) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = userdata;
@@ -3007,6 +3076,12 @@ const sd_bus_vtable bus_manager_vtable[] = {
NULL,,
method_unset_and_set_environment,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("EnqueueMarkedJobs",
+ NULL,,
+ "ao",
+ SD_BUS_PARAM(jobs),
+ method_enqueue_marked_jobs,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("ListUnitFiles",
NULL,,
"a(ss)",