#include <sys/prctl.h>
+#include "sd-bus.h"
#include "sd-varlink.h"
#include "alloc-util.h"
#include "architecture.h"
#include "bitfield.h"
#include "build.h"
+#include "bus-error.h"
#include "bus-polkit.h"
#include "confidential-virt.h"
#include "errno-util.h"
log_info("Queuing reload/restart jobs for marked units%s", glyph(GLYPH_ELLIPSIS));
- _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL, *reply = NULL;
Unit *u;
char *k;
int ret = 0;
HASHMAP_FOREACH_KEY(u, k, manager->units) {
+ _cleanup_(sd_bus_error_free) sd_bus_error bus_error = SD_BUS_ERROR_NULL;
+ const char *error_id = NULL;
uint32_t job_id = 0; /* silence 'maybe-uninitialized' compiler warning */
/* ignore aliases */
continue;
r = mac_selinux_unit_access_check_varlink(u, link, job_type_to_access_method(JOB_TRY_RESTART));
- if (r >= 0)
+ if (r < 0)
+ error_id = SD_VARLINK_ERROR_PERMISSION_DENIED;
+ else
r = varlink_unit_queue_job_one(
- link,
u,
JOB_TRY_RESTART,
JOB_FAIL,
/* reload_if_possible= */ !BIT_SET(u->markers, UNIT_MARKER_NEEDS_RESTART),
- &job_id);
+ &job_id,
+ &bus_error);
if (ERRNO_IS_NEG_RESOURCE(r))
return r;
- RET_GATHER(ret, r);
- if (r >= 0) {
- r = sd_json_variant_append_arrayb(&array, SD_JSON_BUILD_UNSIGNED(job_id));
- if (r < 0)
- return r;
- }
+ if (r < 0)
+ RET_GATHER(ret, log_unit_warning_errno(u, r, "Failed to enqueue marked job: %s",
+ bus_error_message(&bus_error, r)));
+
+ if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
+ continue;
+
+ if (r < 0) {
+ if (!error_id)
+ error_id = varlink_error_id_from_bus_error(&bus_error);
+
+ const char *error_msg = bus_error.message ?: error_id ? NULL : STRERROR(r);
+
+ r = sd_varlink_notifybo(link,
+ SD_JSON_BUILD_PAIR_STRING("unitID", u->id),
+ JSON_BUILD_PAIR_STRING_NON_EMPTY("error", error_id),
+ JSON_BUILD_PAIR_STRING_NON_EMPTY("errorMessage", error_msg));
+ } else
+ r = sd_varlink_notifybo(link,
+ SD_JSON_BUILD_PAIR_STRING("unitID", u->id),
+ SD_JSON_BUILD_PAIR_INTEGER("jobID", job_id));
+ if (r < 0)
+ return r;
}
if (ret < 0)
return ret;
- /* Return parameter is not nullable, build empty array if there's nothing to return */
- if (array)
- r = sd_json_buildo(&reply, SD_JSON_BUILD_PAIR_VARIANT("JobIDs", array));
- else
- r = sd_json_buildo(&reply, SD_JSON_BUILD_PAIR_EMPTY_ARRAY("JobIDs"));
- if (r < 0)
- return r;
-
- return sd_varlink_reply(link, reply);
+ return sd_varlink_reply(link, NULL);
}
}
int varlink_unit_queue_job_one(
- sd_varlink *link,
Unit *u,
JobType type,
JobMode mode,
bool reload_if_possible,
- uint32_t *ret_job_id) {
+ uint32_t *ret_job_id,
+ sd_bus_error *reterr_bus_error) {
- _cleanup_(sd_bus_error_free) sd_bus_error bus_error = SD_BUS_ERROR_NULL;
int r;
assert(u);
- r = unit_queue_job_check_and_mangle_type(u, &type, reload_if_possible, &bus_error);
- if (r < 0) {
- const char *error_id = varlink_error_id_from_bus_error(&bus_error);
- if (error_id)
- return sd_varlink_error(link, error_id);
-
+ r = unit_queue_job_check_and_mangle_type(u, &type, reload_if_possible, reterr_bus_error);
+ if (r < 0)
return r;
- }
Job *j;
- r = manager_add_job(u->manager, type, u, mode, /* reterr_error= */ NULL, &j);
+ r = manager_add_job(u->manager, type, u, mode, reterr_bus_error, &j);
if (r < 0)
return r;
static SD_VARLINK_DEFINE_METHOD(
Reload);
-static SD_VARLINK_DEFINE_METHOD(
+static SD_VARLINK_DEFINE_METHOD_FULL(
EnqueueMarkedJobs,
- SD_VARLINK_FIELD_COMMENT("IDs of enqueued jobs"),
- SD_VARLINK_DEFINE_OUTPUT(JobIDs, SD_VARLINK_INT, SD_VARLINK_ARRAY));
+ SD_VARLINK_SUPPORTS_MORE,
+ SD_VARLINK_FIELD_COMMENT("Enqueued unit ID"),
+ SD_VARLINK_DEFINE_OUTPUT(unitID, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("ID of enqueued job (if successful)"),
+ SD_VARLINK_DEFINE_OUTPUT(jobID, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Varlink error ID (on failure)"),
+ SD_VARLINK_DEFINE_OUTPUT(error, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Job enqueue error message (on failure)"),
+ SD_VARLINK_DEFINE_OUTPUT(errorMessage, SD_VARLINK_STRING, SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_ERROR(RateLimitReached);