UnsetEnvironment(in as names);
UnsetAndSetEnvironment(in as names,
in as assignments);
+ EnqueueMarkedJobs(out ao jobs);
ListUnitFiles(out a(ss) unit_files);
ListUnitFilesByPatterns(in as states,
in as patterns,
<variablelist class="dbus-method" generated="True" extra-ref="UnsetAndSetEnvironment()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="EnqueueMarkedJobs()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="ListUnitFiles()"/>
<variablelist class="dbus-method" generated="True" extra-ref="ListUnitFilesByPatterns()"/>
the "Try" flavor is used in which case a service that isn't running is not affected by the restart. The
"ReloadOrRestart" flavors attempt a reload if the unit supports it and use a restart otherwise.</para>
+ <para><function>EnqueueMarkedJobs()</function> creates reload/restart jobs for units which have been
+ appropriately marked, see <varname>Marks</varname> property above. This is equivalent to calling
+ <function>TryRestartUnit()</function> or <function>ReloadOrTryRestartUnit()</function> for the marked
+ units.</para>
+
<para><function>BindMountUnit()</function> can be used to bind mount new files or directories into
a running service mount namespace.</para>
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;
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)",
log_unit_debug_errno(u, r, "Failed to send unit remove signal for %s: %m", u->id);
}
-int bus_unit_queue_job(
+int bus_unit_queue_job_one(
sd_bus_message *message,
Unit *u,
JobType type,
JobMode mode,
BusUnitQueueFlags flags,
+ sd_bus_message *reply,
sd_bus_error *error) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_free_ char *job_path = NULL, *unit_path = NULL;
_cleanup_set_free_ Set *affected = NULL;
+ _cleanup_free_ char *job_path = NULL, *unit_path = NULL;
Job *j, *a;
int r;
- assert(message);
- assert(u);
- assert(type >= 0 && type < _JOB_TYPE_MAX);
- assert(mode >= 0 && mode < _JOB_MODE_MAX);
-
- r = mac_selinux_unit_access_check(
- u, message,
- job_type_to_access_method(type),
- error);
- if (r < 0)
- return r;
-
- if (FLAGS_SET(flags, BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE) && unit_can_reload(u)) {
- if (type == JOB_RESTART)
- type = JOB_RELOAD_OR_START;
- else if (type == JOB_TRY_RESTART)
- type = JOB_TRY_RELOAD;
- }
-
- if (type == JOB_STOP &&
- IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_ERROR, UNIT_BAD_SETTING) &&
- unit_active_state(u) == UNIT_INACTIVE)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
-
- if ((type == JOB_START && u->refuse_manual_start) ||
- (type == JOB_STOP && u->refuse_manual_stop) ||
- (IN_SET(type, JOB_RESTART, JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) ||
- (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start))
- return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).", u->id);
-
if (FLAGS_SET(flags, BUS_UNIT_QUEUE_VERBOSE_REPLY)) {
affected = set_new(NULL);
if (!affected)
/* The classic response is just a job object path */
if (!FLAGS_SET(flags, BUS_UNIT_QUEUE_VERBOSE_REPLY))
- return sd_bus_reply_method_return(message, "o", job_path);
+ return sd_bus_message_append(reply, "o", job_path);
/* In verbose mode respond with the anchor job plus everything that has been affected */
- r = sd_bus_message_new_method_return(message, &reply);
- if (r < 0)
- return r;
unit_path = unit_dbus_path(j->unit);
if (!unit_path)
return r;
SET_FOREACH(a, affected) {
-
if (a->id == j->id)
continue;
return r;
}
- r = sd_bus_message_close_container(reply);
+ return sd_bus_message_close_container(reply);
+}
+
+int bus_unit_queue_job(
+ sd_bus_message *message,
+ Unit *u,
+ JobType type,
+ JobMode mode,
+ BusUnitQueueFlags flags,
+ sd_bus_error *error) {
+
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ int r;
+
+ assert(message);
+ assert(u);
+ assert(type >= 0 && type < _JOB_TYPE_MAX);
+ assert(mode >= 0 && mode < _JOB_MODE_MAX);
+
+ r = mac_selinux_unit_access_check(
+ u, message,
+ job_type_to_access_method(type),
+ error);
+ if (r < 0)
+ return r;
+
+ if (FLAGS_SET(flags, BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE) && unit_can_reload(u)) {
+ if (type == JOB_RESTART)
+ type = JOB_RELOAD_OR_START;
+ else if (type == JOB_TRY_RESTART)
+ type = JOB_TRY_RELOAD;
+ }
+
+ if (type == JOB_STOP &&
+ IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_ERROR, UNIT_BAD_SETTING) &&
+ unit_active_state(u) == UNIT_INACTIVE)
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
+
+ if ((type == JOB_START && u->refuse_manual_start) ||
+ (type == JOB_STOP && u->refuse_manual_stop) ||
+ (IN_SET(type, JOB_RESTART, JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) ||
+ (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start))
+ return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).", u->id);
+
+ r = sd_bus_message_new_method_return(message, &reply);
+ if (r < 0)
+ return r;
+
+ r = bus_unit_queue_job_one(message, u, type, mode, flags, reply, error);
if (r < 0)
return r;