]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
systemctl: add "reload-or-restart --marked"
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 5 Feb 2021 12:54:33 +0000 (13:54 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 15 Feb 2021 19:49:14 +0000 (20:49 +0100)
This is almost equivalent to 'busctl call-method org.freedesktop.systemd1
/org/freedesktop/systemd1 org.freedesktop.systemd1.Manager EnqueueMarkedJobs',
but waits for the jobs to finish.

man/systemctl.xml
src/systemctl/systemctl-start-unit.c
src/systemctl/systemctl.c
src/systemctl/systemctl.h

index db4e2b2c65c551d37990cf53ac888e569d087ef5..642a5ecf2d15df446780c10b1082e7d4c7a70d79 100644 (file)
@@ -2316,6 +2316,18 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
         a directory, but a regular file, device node, socket or FIFO.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--marked</option></term>
+
+        <listitem><para>Only allowed with <command>reload-or-restart</command>. Enqueues restart jobs for all
+        units that have the <literal>needs-restart</literal> mark, and reload jobs for units that have the
+        <literal>needs-reload</literal> mark. When a unit marked for reload does not support reload, restart
+        will be queued. Those properties can be set using <command>set-property Marks</command>.</para>
+
+        <para>Unless <option>--no-block</option> is used, <command>systemctl</command> will wait for the
+        queued jobs to finish.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--read-only</option></term>
 
index d08e363c9fa006a959ba1eca13ed9c410b6a840a..c40e807212d9d48bddd41ee929bc74e410307069 100644 (file)
@@ -176,6 +176,43 @@ fail:
         return r;
 }
 
+static int enqueue_marked_jobs(
+                sd_bus *bus,
+                BusWaitForJobs *w) {
+
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        int r;
+
+        log_debug("%s dbus call org.freedesktop.systemd1.Manager EnqueueMarkedJobs()",
+                  arg_dry_run ? "Would execute" : "Executing");
+
+        if (arg_dry_run)
+                return 0;
+
+        r = bus_call_method(bus, bus_systemd_mgr, "EnqueueMarkedJobs", &error, &reply, NULL);
+        if (r < 0)
+                return log_error_errno(r, "Failed to start jobs: %s", bus_error_message(&error, r));
+
+        _cleanup_strv_free_ char **paths = NULL;
+        r = sd_bus_message_read_strv(reply, &paths);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        if (w) {
+                char **path;
+
+                STRV_FOREACH(path, paths) {
+                        log_debug("Adding %s to the set", *path);
+                        r = bus_wait_for_jobs_add(w, *path);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to watch job %s: %m", *path);
+                }
+        }
+
+        return 0;
+}
+
 const struct action_metadata action_table[_ACTION_MAX] = {
         [ACTION_HALT]                   = { SPECIAL_HALT_TARGET,                   "halt",                   "replace-irreversibly" },
         [ACTION_POWEROFF]               = { SPECIAL_POWEROFF_TARGET,               "poweroff",               "replace-irreversibly" },
@@ -265,7 +302,7 @@ int start_unit(int argc, char *argv[], void *userdata) {
                                 job_type = "start";
                                 mode = "isolate";
                                 suffix = ".target";
-                        } else {
+                        } else if (!arg_marked) {
                                 /* A command in style of "systemctl start <unit1> <unit2> …", "sysemctl stop <unit1> <unit2> …" and so on */
                                 method = verb_to_method(argv[0]);
                                 job_type = verb_to_job_type(argv[0]);
@@ -289,7 +326,7 @@ int start_unit(int argc, char *argv[], void *userdata) {
                 names = strv_new(one_name);
                 if (!names)
                         return log_oom();
-        } else {
+        } else if (!arg_marked) {
                 bool expanded;
 
                 r = expand_unit_names(bus, strv_skip(argv, 1), suffix, &names, &expanded);
@@ -322,19 +359,23 @@ int start_unit(int argc, char *argv[], void *userdata) {
                         return log_error_errno(r, "Failed to allocate unit watch context: %m");
         }
 
-        STRV_FOREACH(name, names) {
-                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        if (arg_marked)
+                ret = enqueue_marked_jobs(bus, w);
 
-                r = start_unit_one(bus, method, job_type, *name, mode, &error, w, wu);
-                if (ret == EXIT_SUCCESS && r < 0)
-                        ret = translate_bus_error_to_exit_status(r, &error);
+        else
+                STRV_FOREACH(name, names) {
+                        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
-                if (r >= 0 && streq(method, "StopUnit")) {
-                        r = strv_push(&stopped_units, *name);
-                        if (r < 0)
-                                return log_oom();
+                        r = start_unit_one(bus, method, job_type, *name, mode, &error, w, wu);
+                        if (ret == EXIT_SUCCESS && r < 0)
+                                ret = translate_bus_error_to_exit_status(r, &error);
+
+                        if (r >= 0 && streq(method, "StopUnit")) {
+                                r = strv_push(&stopped_units, *name);
+                                if (r < 0)
+                                        return log_oom();
+                        }
                 }
-        }
 
         if (!arg_no_block) {
                 const char* extra_args[4];
index 16d0555c7ca89a76369ee164a7571e85633c7416..315202a64b0f2713c0f5b8fe4eeba38c24793e1a 100644 (file)
@@ -108,6 +108,7 @@ char **arg_clean_what = NULL;
 TimestampStyle arg_timestamp_style = TIMESTAMP_PRETTY;
 bool arg_read_only = false;
 bool arg_mkdir = false;
+bool arg_marked = false;
 
 STATIC_DESTRUCTOR_REGISTER(arg_wall, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
@@ -295,6 +296,7 @@ static int systemctl_help(void) {
                "                         'us+utc': 'Day YYYY-MM-DD HH:MM:SS.UUUUUU UTC\n"
                "     --read-only         Create read-only bind mount\n"
                "     --mkdir             Create directory before mounting, if missing\n"
+               "     --marked            Restart/reload previously marked units\n"
                "\nSee the %2$s for details.\n",
                program_invocation_short_name,
                link,
@@ -413,6 +415,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_TIMESTAMP_STYLE,
                 ARG_READ_ONLY,
                 ARG_MKDIR,
+                ARG_MARKED,
         };
 
         static const struct option options[] = {
@@ -471,6 +474,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 { "timestamp",           required_argument, NULL, ARG_TIMESTAMP_STYLE     },
                 { "read-only",           no_argument,       NULL, ARG_READ_ONLY           },
                 { "mkdir",               no_argument,       NULL, ARG_MKDIR               },
+                { "marked",              no_argument,       NULL, ARG_MARKED              },
                 {}
         };
 
@@ -900,6 +904,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         arg_mkdir = true;
                         break;
 
+                case ARG_MARKED:
+                        arg_marked = true;
+                        break;
+
                 case '.':
                         /* Output an error mimicking getopt, and print a hint afterwards */
                         log_error("%s: invalid option -- '.'", program_invocation_name);
@@ -923,6 +931,27 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "--wait may not be combined with --no-block.");
 
+        bool do_reload_or_restart = streq_ptr(argv[optind], "reload-or-restart");
+        if (arg_marked) {
+                if (!do_reload_or_restart)
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "--marked may only be used with 'reload-or-restart'.");
+                if (optind + 1 < argc)
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "No additional arguments allowed with 'reload-or-restart --marked'.");
+                if (arg_wait)
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "--marked --wait is not supported.");
+                if (arg_show_transaction)
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "--marked --show-transaction is not supported.");
+
+        } else if (do_reload_or_restart) {
+                if (optind + 1 >= argc)
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "List of units to restart/reload is required.");
+        }
+
         return 1;
 }
 
@@ -1004,7 +1033,7 @@ static int systemctl_main(int argc, char *argv[]) {
                 { "reload",                2,        VERB_ANY, VERB_ONLINE_ONLY, start_unit              },
                 { "restart",               2,        VERB_ANY, VERB_ONLINE_ONLY, start_unit              },
                 { "try-restart",           2,        VERB_ANY, VERB_ONLINE_ONLY, start_unit              },
-                { "reload-or-restart",     2,        VERB_ANY, VERB_ONLINE_ONLY, start_unit              },
+                { "reload-or-restart",     VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, start_unit              },
                 { "reload-or-try-restart", 2,        VERB_ANY, VERB_ONLINE_ONLY, start_unit              }, /* For compatibility with old systemctl <= 228 */
                 { "try-reload-or-restart", 2,        VERB_ANY, VERB_ONLINE_ONLY, start_unit              },
                 { "force-reload",          2,        VERB_ANY, VERB_ONLINE_ONLY, start_unit              }, /* For compatibility with SysV */
index 0ebe4580c6027b7c11122f48bcab6c4ebfa2fc0f..3c5a4023a9f827367402e63e8eacddac0b2c9b31 100644 (file)
@@ -93,5 +93,6 @@ extern char **arg_clean_what;
 extern TimestampStyle arg_timestamp_style;
 extern bool arg_read_only;
 extern bool arg_mkdir;
+extern bool arg_marked;
 
 int systemctl_dispatch_parse_argv(int argc, char *argv[]);