]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/varlink-manager: report individual job enqueue result if client sets 'more' 40365/head
authorMike Yuan <me@yhndnzj.com>
Fri, 16 Jan 2026 20:58:28 +0000 (21:58 +0100)
committerMike Yuan <me@yhndnzj.com>
Fri, 23 Jan 2026 23:48:03 +0000 (00:48 +0100)
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
src/core/varlink-unit.c
src/core/varlink-unit.h
src/shared/varlink-io.systemd.Manager.c

index 25140bf465c36d063b83bd08b8bf81d6bc252341..9eeeed42ccf9e573740d296a6e9c64a68404c3c1 100644 (file)
@@ -2,12 +2,14 @@
 
 #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"
@@ -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);
 }
index 8e061c0d50f4fbf6df445f12988f36eb9de77a07..7d91c8947f0d7fad92b0a102d1365104a3cf291c 100644 (file)
@@ -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;
 
index 0913d8f00927daeb8954be2882db94e1d7870cd9..73de837940fa5340e3ad7b9b4b87bdf857a6ce45 100644 (file)
 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);
index 79c5c7e7168fbf67067119ba0ba60cf2cd9e98be..cb304f229502964ab17721b0c52d767e759b3c5b 100644 (file)
@@ -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);