machinectl: add new "machinectl reboot" call
authorLennart Poettering <lennart@poettering.net>
Wed, 12 Feb 2014 01:07:57 +0000 (02:07 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 12 Feb 2014 01:11:00 +0000 (02:11 +0100)
man/machinectl.xml
src/machine/machinectl.c

index 6e991ee..cabdbac 100644 (file)
                         </varlistentry>
 
                         <varlistentry>
-                                <term><command>login</command> <replaceable>ID</replaceable>...</term>
+                                <term><command>reboot</command> <replaceable>ID</replaceable>...</term>
+
+                                <listitem><para>Reboot one or more
+                                containers. This will trigger a reboot
+                                by sending SIGINT to the container's
+                                init process, which is roughly
+                                equivalent to pressing Ctrl+Alt+Del on
+                                a non-containerized
+                                system.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><command>login</command> <replaceable>ID</replaceable></term>
 
                                 <listitem><para>Open a terminal login
                                 session to a container. This will
index 703fb3a..3f4f8ac 100644 (file)
@@ -395,6 +395,69 @@ static int terminate_machine(sd_bus *bus, char **args, unsigned n) {
         return 0;
 }
 
+static int reboot_machine(sd_bus *bus, char **args, unsigned n) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        unsigned i;
+        int r;
+
+        assert(args);
+
+        if (arg_transport != BUS_TRANSPORT_LOCAL) {
+                log_error("Reboot only supported on local machines.");
+                return -ENOTSUP;
+        }
+
+        for (i = 1; i < n; i++) {
+                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *reply2 = NULL;
+                const char *path;
+                uint32_t leader;
+
+                r = sd_bus_call_method(
+                                bus,
+                                "org.freedesktop.machine1",
+                                "/org/freedesktop/machine1",
+                                "org.freedesktop.machine1.Manager",
+                                "GetMachine",
+                                &error,
+                                &reply,
+                                "s", args[i]);
+
+                if (r < 0) {
+                        log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
+                        return r;
+                }
+
+                r = sd_bus_message_read(reply, "o", &path);
+                if (r < 0)
+                        return bus_log_parse_error(r);
+
+                r = sd_bus_get_property(
+                                bus,
+                                "org.freedesktop.machine1",
+                                path,
+                                "org.freedesktop.machine1.Machine",
+                                "Leader",
+                                &error,
+                                &reply2,
+                                "u");
+                if (r < 0) {
+                        log_error("Failed to retrieve PID of leader: %s", strerror(-r));
+                        return r;
+                }
+
+                r = sd_bus_message_read(reply2, "u", &leader);
+                if (r < 0)
+                        return bus_log_parse_error(r);
+
+                if (kill(leader, SIGINT) < 0) {
+                        log_error("Failed to kill init process " PID_FMT ": %m", (pid_t) leader);
+                        return -errno;
+                }
+        }
+
+        return 0;
+}
+
 static int openpt_in_namespace(pid_t pid, int flags) {
         _cleanup_close_pipe_ int pair[2] = { -1, -1 };
         _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
@@ -497,7 +560,7 @@ static int login_machine(sd_bus *bus, char **args, unsigned n) {
         assert(args);
 
         if (arg_transport != BUS_TRANSPORT_LOCAL) {
-                log_error("Login only support on local machines.");
+                log_error("Login only supported on local machines.");
                 return -ENOTSUP;
         }
 
@@ -624,6 +687,7 @@ static int help(void) {
                "  show NAME...           Show properties of one or more VMs/containers\n"
                "  terminate NAME...      Terminate one or more VMs/containers\n"
                "  kill NAME...           Send signal to processes of a VM/container\n"
+               "  reboot NAME...         Reboot one or more containers\n"
                "  login NAME             Get a login prompt on a container\n",
                program_invocation_short_name);
 
@@ -747,6 +811,7 @@ static int machinectl_main(sd_bus *bus, int argc, char *argv[]) {
                 { "status",                MORE,   2, show              },
                 { "show",                  MORE,   1, show              },
                 { "terminate",             MORE,   2, terminate_machine },
+                { "reboot",                MORE,   2, reboot_machine    },
                 { "kill",                  MORE,   2, kill_machine      },
                 { "login",                 MORE,   2, login_machine     },
         };