From f7823fdae085e303baf1233d6d5c5056014bd6e8 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Fri, 16 Jan 2026 21:58:28 +0100 Subject: [PATCH] core/varlink-manager: report individual job enqueue result if client sets 'more' One nice property varlink has is that we can nicely report result of individual operations on each unit, through the 'more' mechanism. Hence do so for the EnqueueMarkedJobs() method. Also, apply 502d6f4bc9b96009627f923dcc0ab53e5a181d78 for varlink method too. While at it, use lowerCamelCase for method reply fields, as requested in https://github.com/systemd/systemd/pull/40365#discussion_r2702344239. --- src/core/varlink-manager.c | 52 ++++++++++++++++--------- src/core/varlink-unit.c | 16 +++----- src/core/varlink-unit.h | 4 +- src/shared/varlink-io.systemd.Manager.c | 13 +++++-- 4 files changed, 50 insertions(+), 35 deletions(-) diff --git a/src/core/varlink-manager.c b/src/core/varlink-manager.c index 25140bf465c..9eeeed42ccf 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 8e061c0d50f..7d91c8947f0 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 0913d8f0092..73de837940f 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 79c5c7e7168..cb304f22950 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); -- 2.47.3