diff --git a/src/core/varlink-manager.c b/src/core/varlink-manager.c index 25140bf465..9eeeed42cc 100644 --- a/src/core/varlink-manager.c +++ b/src/core/varlink-manager.c @@ -2,12 +2,14 @@ #include +#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" @@ -330,11 +332,12 @@ int vl_method_enqueue_marked_jobs_manager(sd_varlink *link, sd_json_variant *par 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 */ @@ -345,34 +348,45 @@ int vl_method_enqueue_marked_jobs_manager(sd_varlink *link, sd_json_variant *par 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); } diff --git a/src/core/varlink-unit.c b/src/core/varlink-unit.c index 8e061c0d50..7d91c8947f 100644 --- a/src/core/varlink-unit.c +++ b/src/core/varlink-unit.c @@ -507,29 +507,23 @@ int vl_method_list_units(sd_varlink *link, sd_json_variant *parameters, sd_varli } 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; diff --git a/src/core/varlink-unit.h b/src/core/varlink-unit.h index 0913d8f009..73de837940 100644 --- a/src/core/varlink-unit.h +++ b/src/core/varlink-unit.h @@ -10,11 +10,11 @@ int vl_method_list_units(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); 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); int varlink_error_no_such_unit(sd_varlink *v, const char *name); diff --git a/src/shared/varlink-io.systemd.Manager.c b/src/shared/varlink-io.systemd.Manager.c index 79c5c7e716..cb304f2295 100644 --- a/src/shared/varlink-io.systemd.Manager.c +++ b/src/shared/varlink-io.systemd.Manager.c @@ -181,10 +181,17 @@ static SD_VARLINK_DEFINE_METHOD( 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);