portablectl: use new EnqueueUnitJobMany() when available
This commit is contained in:
+129
-14
@@ -678,22 +678,18 @@ static int maybe_enable_disable(sd_bus *bus, const char *path, bool enable) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int maybe_start_stop_restart(sd_bus *bus, const char *path, const char *method, BusWaitForJobs *wait) {
|
||||
static int maybe_start_stop_restart(sd_bus *bus, const char *name, const char *method, BusWaitForJobs *wait) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_free_ char *name = NULL;
|
||||
const char *job = NULL;
|
||||
int r;
|
||||
|
||||
assert(name);
|
||||
assert(STR_IN_SET(method, "StartUnit", "StopUnit", "RestartUnit"));
|
||||
|
||||
if (!arg_now)
|
||||
return 0;
|
||||
|
||||
r = path_extract_filename(path, &name);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to extract file name from '%s': %m", path);
|
||||
|
||||
r = bus_call_method(
|
||||
bus,
|
||||
bus_systemd_mgr,
|
||||
@@ -704,7 +700,7 @@ static int maybe_start_stop_restart(sd_bus *bus, const char *path, const char *m
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to call %s on the portable service %s: %s",
|
||||
method,
|
||||
path,
|
||||
name,
|
||||
bus_error_message(&error, r));
|
||||
|
||||
r = sd_bus_message_read(reply, "o", &job);
|
||||
@@ -724,8 +720,92 @@ static int maybe_start_stop_restart(sd_bus *bus, const char *path, const char *m
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int maybe_start_stop_restart_units(
|
||||
sd_bus *bus,
|
||||
char * const *names,
|
||||
const char *job_type,
|
||||
BusWaitForJobs *wait) {
|
||||
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
const char *method;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(STR_IN_SET(job_type, "start", "stop", "restart"));
|
||||
|
||||
if (!arg_now || strv_isempty(names))
|
||||
return 0;
|
||||
|
||||
method = streq(job_type, "start") ? "StartUnit" :
|
||||
streq(job_type, "stop") ? "StopUnit" :
|
||||
"RestartUnit";
|
||||
|
||||
/* Prefer the new EnqueueUnitJobMany() method which submits all units in a single transaction.
|
||||
* Falls back to per-unit calls on older managers (UnknownMethod) or when the new method rejects
|
||||
* something about the request (InvalidArgs). */
|
||||
r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "EnqueueUnitJobMany");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append_strv(m, (char**) names);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append(m, "sst", job_type, "replace", UINT64_C(0));
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_call(bus, m, 0, &error, &reply);
|
||||
if (r >= 0) {
|
||||
r = sd_bus_message_enter_container(reply, 'a', "(uosos)");
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
for (;;) {
|
||||
const char *path, *unit_id;
|
||||
uint32_t id;
|
||||
|
||||
r = sd_bus_message_read(reply, "(uosos)", &id, &path, &unit_id, NULL, NULL);
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (!arg_quiet)
|
||||
log_info("Queued %s to call %s on portable service %s.", path, method, unit_id);
|
||||
|
||||
if (wait) {
|
||||
r = bus_wait_for_jobs_add(wait, path);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to watch %s job to call %s on %s: %m",
|
||||
path, method, unit_id);
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_bus_message_exit_container(reply);
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_METHOD, SD_BUS_ERROR_INVALID_ARGS))
|
||||
return log_error_errno(r, "Failed to enqueue jobs for portable services: %s",
|
||||
bus_error_message(&error, r));
|
||||
|
||||
log_debug_errno(r, "EnqueueUnitJobMany() not supported (%s), falling back to per-unit calls.",
|
||||
bus_error_message(&error, r));
|
||||
|
||||
STRV_FOREACH(name, names)
|
||||
(void) maybe_start_stop_restart(bus, *name, method, wait);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int maybe_enable_start(sd_bus *bus, sd_bus_message *reply) {
|
||||
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *wait = NULL;
|
||||
_cleanup_strv_free_ char **start_names = NULL;
|
||||
int r;
|
||||
|
||||
if (!arg_enable && !arg_now)
|
||||
@@ -755,7 +835,15 @@ static int maybe_enable_start(sd_bus *bus, sd_bus_message *reply) {
|
||||
|
||||
if (STR_IN_SET(type, "symlink", "copy") && is_portable_managed(path)) {
|
||||
(void) maybe_enable_disable(bus, path, true);
|
||||
(void) maybe_start_stop_restart(bus, path, "StartUnit", wait);
|
||||
|
||||
_cleanup_free_ char *name = NULL;
|
||||
r = path_extract_filename(path, &name);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to extract file name from '%s': %m", path);
|
||||
|
||||
r = strv_consume(&start_names, TAKE_PTR(name));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,6 +851,8 @@ static int maybe_enable_start(sd_bus *bus, sd_bus_message *reply) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) maybe_start_stop_restart_units(bus, start_names, "start", wait);
|
||||
|
||||
if (!arg_no_block) {
|
||||
r = bus_wait_for_jobs(wait, arg_quiet, NULL);
|
||||
if (r < 0)
|
||||
@@ -774,6 +864,7 @@ static int maybe_enable_start(sd_bus *bus, sd_bus_message *reply) {
|
||||
|
||||
static int maybe_stop_enable_restart(sd_bus *bus, sd_bus_message *reply) {
|
||||
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *wait = NULL;
|
||||
_cleanup_strv_free_ char **stop_names = NULL, **restart_names = NULL;
|
||||
int r;
|
||||
|
||||
if (!arg_enable && !arg_now)
|
||||
@@ -804,14 +895,25 @@ static int maybe_stop_enable_restart(sd_bus *bus, sd_bus_message *reply) {
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (streq(type, "unlink") && is_portable_managed(path))
|
||||
(void) maybe_start_stop_restart(bus, path, "StopUnit", wait);
|
||||
if (streq(type, "unlink") && is_portable_managed(path) && arg_now) {
|
||||
_cleanup_free_ char *name = NULL;
|
||||
|
||||
r = path_extract_filename(path, &name);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to extract file name from '%s': %m", path);
|
||||
|
||||
r = strv_consume(&stop_names, TAKE_PTR(name));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_bus_message_exit_container(reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) maybe_start_stop_restart_units(bus, stop_names, "stop", wait);
|
||||
|
||||
/* Then we get a list of units that were either added or changed, so that we can
|
||||
* enable them and/or restart them if the user asked us to. */
|
||||
r = sd_bus_message_enter_container(reply, 'a', "(sss)");
|
||||
@@ -829,7 +931,15 @@ static int maybe_stop_enable_restart(sd_bus *bus, sd_bus_message *reply) {
|
||||
|
||||
if (STR_IN_SET(type, "symlink", "copy") && is_portable_managed(path)) {
|
||||
(void) maybe_enable_disable(bus, path, true);
|
||||
(void) maybe_start_stop_restart(bus, path, "RestartUnit", wait);
|
||||
|
||||
_cleanup_free_ char *name = NULL;
|
||||
r = path_extract_filename(path, &name);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to extract file name from '%s': %m", path);
|
||||
|
||||
r = strv_consume(&restart_names, TAKE_PTR(name));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -837,6 +947,8 @@ static int maybe_stop_enable_restart(sd_bus *bus, sd_bus_message *reply) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) maybe_start_stop_restart_units(bus, restart_names, "restart", wait);
|
||||
|
||||
if (!arg_no_block) {
|
||||
r = bus_wait_for_jobs(wait, arg_quiet, NULL);
|
||||
if (r < 0)
|
||||
@@ -940,9 +1052,6 @@ static int maybe_stop_disable_clean(sd_bus *bus, char *image, char *argv[]) {
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
(void) maybe_start_stop_restart(bus, name, "StopUnit", wait);
|
||||
(void) maybe_enable_disable(bus, name, false);
|
||||
|
||||
r = strv_extend(&units, name);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
@@ -952,6 +1061,12 @@ static int maybe_stop_disable_clean(sd_bus *bus, char *image, char *argv[]) {
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
(void) maybe_start_stop_restart_units(bus, units, "stop", wait);
|
||||
|
||||
/* Disable after stopping to match the idiomatic stop-then-disable lifecycle order. */
|
||||
STRV_FOREACH(name, units)
|
||||
(void) maybe_enable_disable(bus, *name, false);
|
||||
|
||||
/* Stopping must always block or the detach will fail if the unit is still running */
|
||||
r = bus_wait_for_jobs(wait, arg_quiet, NULL);
|
||||
if (r < 0)
|
||||
|
||||
Reference in New Issue
Block a user