machinectl.c revision da054c3782f25b3b18243f6c76dcfcf90ba70274
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2013 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_all = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_full = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_no_pager = false;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersenstatic bool arg_legend = true;
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poetteringstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringstatic bool arg_read_only = false;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringstatic bool arg_mkdir = false;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poetteringstatic bool arg_quiet = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void pager_open_if_enabled(void) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Cache result before we open the pager */
56159e0d918e9a9be07988133bb2847779325de0Lennart Poetteringstatic int list_machines(int argc, char *argv[], void *userdata) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned k = 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "org.freedesktop.machine1",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "org.freedesktop.machine1.Manager",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "ListMachines",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error("Could not get machines: %s", bus_error_message(&error, -r));
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen printf("%-32s %-9s %-16s\n", "MACHINE", "CONTAINER", "SERVICE");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssso)");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("%-32s %-9s %-16s\n", name, class, service);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen printf("\n%u machines listed.\n", k);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringtypedef struct ImageInfo {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic int compare_image_info(const void *a, const void *b) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering const ImageInfo *x = a, *y = b;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poetteringstatic int list_images(int argc, char *argv[], void *userdata) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering size_t max_name = strlen("NAME"), max_type = strlen("TYPE"), max_size = strlen("SIZE"), max_crtime = strlen("CREATED"), max_mtime = strlen("MODIFIED");
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering "org.freedesktop.machine1",
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering "org.freedesktop.machine1.Manager",
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering log_error("Could not get images: %s", bus_error_message(&error, -r));
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssbttto)");
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering while ((r = sd_bus_message_read(reply, "(ssbttto)", &name, &type, &read_only, &crtime, &mtime, &size, &object)) > 0) {
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering char buf[MAX(FORMAT_TIMESTAMP_MAX, FORMAT_BYTES_MAX)];
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (!GREEDY_REALLOC(images, n_allocated, n_images + 1))
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering l = strlen(strna(format_timestamp(buf, sizeof(buf), crtime)));
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering l = strlen(strna(format_timestamp(buf, sizeof(buf), mtime)));
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering l = strlen(strna(format_bytes(buf, sizeof(buf), size)));
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = sd_bus_message_exit_container(reply);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering qsort_safe(images, n_images, sizeof(ImageInfo), compare_image_info);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering printf("%-*s %-*s %-3s %-*s %-*s %-*s\n",
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering for (j = 0; j < n_images; j++) {
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering char crtime_buf[FORMAT_TIMESTAMP_MAX], mtime_buf[FORMAT_TIMESTAMP_MAX], size_buf[FORMAT_BYTES_MAX];
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering printf("%-*s %-*s %s%-3s%s %-*s %-*s %-*s\n",
8937e7b68940d0fa0d0aab90eb7425fa7dccebc9Lennart Poettering images[j].read_only ? ansi_highlight_red() : "", yes_no(images[j].read_only), images[j].read_only ? ansi_highlight_off() : "",
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering (int) max_size, strna(format_bytes(size_buf, sizeof(size_buf), images[j].size)),
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering (int) max_crtime, strna(format_timestamp(crtime_buf, sizeof(crtime_buf), images[j].crtime)),
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering (int) max_mtime, strna(format_timestamp(mtime_buf, sizeof(mtime_buf), images[j].mtime)));
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering printf("\n%zu images listed.\n", n_images);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poetteringstatic int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering if (arg_transport == BUS_TRANSPORT_REMOTE)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering endswith(unit, ".scope") ? "org.freedesktop.systemd1.Scope" : "org.freedesktop.systemd1.Service",
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering "ControlGroup",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r));
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering r = sd_bus_message_read(reply, "s", &cgroup);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, output_flags);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poetteringstatic int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering "org.freedesktop.machine1",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering "org.freedesktop.machine1.Manager",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering "GetMachineAddresses",
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering r = sd_bus_message_enter_container(reply, 'a', "(iay)");
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering const void *a;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering char buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering r = sd_bus_message_read(reply, "i", &family);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = sd_bus_message_read_array(reply, 'y', &a, &sz);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering fputs(inet_ntop(family, a, buffer, sizeof(buffer)), stdout);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = sd_bus_message_exit_container(reply);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = sd_bus_message_exit_container(reply);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poetteringstatic int print_os_release(sd_bus *bus, const char *name, const char *prefix) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "org.freedesktop.machine1",
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "org.freedesktop.machine1.Manager",
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "GetMachineOSRelease",
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = sd_bus_message_enter_container(reply, 'a', "{ss}");
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = sd_bus_message_exit_container(reply);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!sd_id128_equal(i->id, SD_ID128_NULL))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("(" SD_ID128_FORMAT_STR ")\n", SD_ID128_FORMAT_VAL(i->id));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s1 = format_timestamp_relative(since1, sizeof(since1), i->timestamp);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s2 = format_timestamp(since2, sizeof(since2), i->timestamp);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Leader: %u", (unsigned) i->leader);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else if (i->class)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Root: %s\n", i->root_directory);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering for (c = 0; c < i->n_netif; c++) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering "\t Address: ",
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering print_os_release(bus, i->name, "\t OS: ");
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering show_unit_cgroup(bus, i->unit, i->leader);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poetteringstatic int map_netif(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering const void *v;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering assert_cc(sizeof(int32_t) == sizeof(int));
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = sd_bus_message_read_array(m, SD_BUS_TYPE_INT32, &v, &l);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringstatic int show_machine_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers static const struct bus_properties_map map[] = {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering { "Name", "s", NULL, offsetof(MachineStatusInfo, name) },
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering { "Class", "s", NULL, offsetof(MachineStatusInfo, class) },
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering { "Service", "s", NULL, offsetof(MachineStatusInfo, service) },
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering { "Unit", "s", NULL, offsetof(MachineStatusInfo, unit) },
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering { "RootDirectory", "s", NULL, offsetof(MachineStatusInfo, root_directory) },
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering { "Leader", "u", NULL, offsetof(MachineStatusInfo, leader) },
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering { "Timestamp", "t", NULL, offsetof(MachineStatusInfo, timestamp) },
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering { "Id", "ay", bus_map_id128, offsetof(MachineStatusInfo, id) },
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering { "NetworkInterfaces", "ai", map_netif, 0 },
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers "org.freedesktop.machine1",
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt return log_error_errno(r, "Could not get properties: %m");
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringstatic int show_machine_properties(sd_bus *bus, const char *path, bool *new_line) {
27e72d6b22890ba4a8cbc05c49667cd1cccf1461Simon Peeters r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Could not get properties: %m");
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringstatic int show_machine(int argc, char *argv[], void *userdata) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* If no argument is specified, inspect the manager
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = show_machine_properties(bus, "/org/freedesktop/machine1", &new_line);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "org.freedesktop.machine1",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "org.freedesktop.machine1.Manager",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "GetMachine",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = show_machine_properties(bus, path, &new_line);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = show_machine_info(argv[0], bus, path, &new_line);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringstatic void print_image_status_info(sd_bus *bus, ImageStatusInfo *i) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering char ts_relative[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering char ts_absolute[FORMAT_TIMESTAMP_MAX], *s2;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering char bs_exclusive[FORMAT_BYTES_MAX], *s4;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering i->read_only ? ansi_highlight_red() : "",
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering i->read_only ? ansi_highlight_off() : "");
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering s1 = format_timestamp_relative(ts_relative, sizeof(ts_relative), i->crtime);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering s2 = format_timestamp(ts_absolute, sizeof(ts_absolute), i->crtime);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering s1 = format_timestamp_relative(ts_relative, sizeof(ts_relative), i->mtime);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering s2 = format_timestamp(ts_absolute, sizeof(ts_absolute), i->mtime);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering s3 = format_bytes(bs, sizeof(bs), i->size);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering s4 = i->size_exclusive != i->size ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->size_exclusive) : NULL;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering printf("\t Size: %s (exclusive: %s)\n", s3, s4);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering s3 = format_bytes(bs, sizeof(bs), i->limit);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering s4 = i->limit_exclusive != i->limit ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->limit_exclusive) : NULL;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering printf("\t Limit: %s (exclusive: %s)\n", s3, s4);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringstatic int show_image_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering static const struct bus_properties_map map[] = {
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering { "Name", "s", NULL, offsetof(ImageStatusInfo, name) },
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering { "Path", "s", NULL, offsetof(ImageStatusInfo, path) },
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering { "Type", "s", NULL, offsetof(ImageStatusInfo, type) },
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering { "ReadOnly", "b", NULL, offsetof(ImageStatusInfo, read_only) },
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering { "CreationTimestamp", "t", NULL, offsetof(ImageStatusInfo, crtime) },
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering { "ModificationTimestamp", "t", NULL, offsetof(ImageStatusInfo, mtime) },
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering { "Size", "t", NULL, offsetof(ImageStatusInfo, size) },
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering { "Limit", "t", NULL, offsetof(ImageStatusInfo, limit) },
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering { "SizeExclusive", "t", NULL, offsetof(ImageStatusInfo, size_exclusive) },
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering { "LimitExclusive", "t", NULL, offsetof(ImageStatusInfo, limit_exclusive) },
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering "org.freedesktop.machine1",
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return log_error_errno(r, "Could not get properties: %m");
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringstatic int show_image_properties(sd_bus *bus, const char *path, bool *new_line) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering log_error_errno(r, "Could not get properties: %m");
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringstatic int show_image(int argc, char *argv[], void *userdata) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* If no argument is specified, inspect the manager
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = show_image_properties(bus, "/org/freedesktop/machine1", &new_line);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering "org.freedesktop.machine1",
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering "org.freedesktop.machine1.Manager",
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering log_error("Could not get path to image: %s", bus_error_message(&error, -r));
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = sd_bus_message_read(reply, "o", &path);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = show_image_properties(bus, path, &new_line);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = show_image_info(argv[0], bus, path, &new_line);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poetteringstatic int kill_machine(int argc, char *argv[], void *userdata) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering "org.freedesktop.machine1",
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering "org.freedesktop.machine1.Manager",
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering "KillMachine",
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering "ssi", argv[i], arg_kill_who, arg_signal);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error("Could not kill machine: %s", bus_error_message(&error, -r));
56159e0d918e9a9be07988133bb2847779325de0Lennart Poetteringstatic int reboot_machine(int argc, char *argv[], void *userdata) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering arg_signal = SIGINT; /* sysvinit + systemd */
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering return kill_machine(argc, argv, userdata);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poetteringstatic int poweroff_machine(int argc, char *argv[], void *userdata) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering arg_signal = SIGRTMIN+4; /* only systemd */
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering return kill_machine(argc, argv, userdata);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poetteringstatic int terminate_machine(int argc, char *argv[], void *userdata) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering "org.freedesktop.machine1",
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering "org.freedesktop.machine1.Manager",
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering "TerminateMachine",
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering log_error("Could not terminate machine: %s", bus_error_message(&error, -r));
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringstatic int machine_get_leader(sd_bus *bus, const char *name, pid_t *ret) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *reply2 = NULL;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering "org.freedesktop.machine1",
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering "org.freedesktop.machine1.Manager",
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = sd_bus_message_read(reply, "o", &object);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering "org.freedesktop.machine1",
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering "org.freedesktop.machine1.Machine",
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering return log_error_errno(r, "Failed to retrieve PID of leader: %m");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = sd_bus_message_read(reply2, "u", &leader);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poetteringstatic int copy_files(int argc, char *argv[], void *userdata) {
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering char *dest, *host_path, *container_path, *host_dirname, *host_basename, *container_dirname, *container_basename, *t;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering host_path = strdupa(copy_from ? dest : argv[2]);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering container_path = strdupa(copy_from ? argv[2] : dest);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering log_error("Container path not absolute.");
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering container_dirname = dirname(container_path);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering r = machine_get_leader(bus, argv[1], &leader);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering hostfd = open(host_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering return log_error_errno(errno, "Failed to open source directory: %m");
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering return log_error_errno(errno, "Failed to fork(): %m");
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering const char *q;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering q = procfs_file_alloca(leader, "ns/mnt");
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering log_error_errno(errno, "Failed to open mount namespace of leader: %m");
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering log_error_errno(errno, "Failed to join namespace of leader: %m");
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering containerfd = open(container_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering log_error_errno(errno, "Failed top open destination directory: %m");
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, true);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, true);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering log_error_errno(errno, "Failed to copy tree: %m");
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering return log_error_errno(r, "Failed to wait for client: %m");
56159e0d918e9a9be07988133bb2847779325de0Lennart Poetteringstatic int bind_mount(int argc, char *argv[], void *userdata) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering bool mount_slave_created = false, mount_slave_mounted = false,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering mount_tmp_created = false, mount_tmp_mounted = false,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering mount_outside_created = false, mount_outside_mounted = false;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* One day, when bind mounting /proc/self/fd/n works across
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering * namespace boundaries we should rework this logic to make
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering * use of it... */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering log_error("Destination path not absolute.");
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering p = strappenda("/run/systemd/nspawn/propagate/", argv[1], "/");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering log_error("Container does not allow propagation of mount points.");
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering r = machine_get_leader(bus, argv[1], &leader);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* Our goal is to install a new bind mount into the container,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering possibly read-only. This is irritatingly complex
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering unfortunately, currently.
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering First, we start by creating a private playground in /tmp,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering that we can mount MS_SLAVE. (Which is necessary, since
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering MS_MOUNT cannot be applied to mounts with MS_SHARED parent
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering return log_error_errno(errno, "Failed to create playground: %m");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (mount(mount_slave, mount_slave, NULL, MS_BIND, NULL) < 0) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = log_error_errno(errno, "Failed to make bind mount: %m");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (mount(NULL, mount_slave, NULL, MS_SLAVE, NULL) < 0) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = log_error_errno(errno, "Failed to remount slave: %m");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* Second, we mount the source directory to a directory inside
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering of our MS_SLAVE playground. */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering mount_tmp = strappenda(mount_slave, "/mount");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = log_error_errno(errno, "Failed to create temporary mount: %m");
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (mount(argv[2], mount_tmp, NULL, MS_BIND, NULL) < 0) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = log_error_errno(errno, "Failed to overmount: %m");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* Third, we remount the new bind mount read-only if requested. */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (mount(NULL, mount_tmp, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = log_error_errno(errno, "Failed to mark read-only: %m");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* Fourth, we move the new bind mount into the propagation
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering * directory. This way it will appear there read-only
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering * right-away. */
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering mount_outside = strappenda("/run/systemd/nspawn/propagate/", argv[1], "/XXXXXX");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = log_error_errno(errno, "Cannot create propagation directory: %m");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (mount(mount_tmp, mount_outside, NULL, MS_MOVE, NULL) < 0) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = log_error_errno(errno, "Failed to move: %m");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = log_error_errno(errno, "Failed to fork(): %m");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering const char *q;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering q = procfs_file_alloca(leader, "ns/mnt");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering log_error_errno(errno, "Failed to open mount namespace of leader: %m");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering log_error_errno(errno, "Failed to join namespace of leader: %m");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* Fifth, move the mount to the right place inside */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering mount_inside = strappenda("/run/systemd/nspawn/incoming/", basename(mount_outside));
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (mount(mount_inside, dest, NULL, MS_MOVE, NULL) < 0) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering log_error_errno(errno, "Failed to mount: %m");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering log_error_errno(r, "Failed to wait for client: %m");
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poetteringstatic int on_machine_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering PTYForward ** forward = (PTYForward**) userdata;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering /* If the forwarder is already initialized, tell it to
da054c3782f25b3b18243f6c76dcfcf90ba70274Lennart Poettering * exit on the next vhangup(), so that we still flush
da054c3782f25b3b18243f6c76dcfcf90ba70274Lennart Poettering * out what might be queued and exit then. */
da054c3782f25b3b18243f6c76dcfcf90ba70274Lennart Poettering r = pty_forward_set_ignore_vhangup(*forward, false);
da054c3782f25b3b18243f6c76dcfcf90ba70274Lennart Poettering log_error_errno(r, "Failed to set ignore_vhangup flag: %m");
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering /* On error, or when the forwarder is not initialized yet, quit immediately */
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering sd_event_exit(sd_bus_get_event(bus), EXIT_FAILURE);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poetteringstatic int login_machine(int argc, char *argv[], void *userdata) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering _cleanup_event_unref_ sd_event *event = NULL;
bf441e3d9371a7e5aa1def66cfc40f0118884644Lennart Poettering if (arg_transport != BUS_TRANSPORT_LOCAL &&
de33fc625725d199629ed074d6278504deb23debLennart Poettering arg_transport != BUS_TRANSPORT_MACHINE) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering log_error("Login only supported on local machines.");
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt return log_error_errno(r, "Failed to get event loop: %m");
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt return log_error_errno(r, "Failed to attach bus to event loop: %m");
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering "sender='org.freedesktop.machine1',"
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering "interface='org.freedesktop.machine1.Manager',"
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering "member='MachineRemoved',"
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering r = sd_bus_add_match(bus, &slot, match, on_machine_removed, &forward);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering return log_error_errno(r, "Failed to add machine removal match: %m");
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering "org.freedesktop.machine1",
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering "org.freedesktop.machine1.Manager",
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering "OpenMachineLogin");
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering r = sd_bus_message_set_allow_interactive_authorization(m, true);
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering r = sd_bus_message_append(m, "s", argv[1]);
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering r = sd_bus_call(bus, m, 0, &error, &reply);
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering log_error("Failed to get machine PTY: %s", bus_error_message(&error, -r));
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering r = sd_bus_message_read(reply, "hs", &master, &pty);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering sigset_add_many(&mask, SIGWINCH, SIGTERM, SIGINT, -1);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering log_info("Connected to machine %s. Press ^] three times within 1s to exit session.", argv[1]);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
9b15b7846d4de01bb5d9700a24077787e984e8abLennart Poettering r = pty_forward_new(event, master, true, &forward);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt return log_error_errno(r, "Failed to create PTY forwarder: %m");
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt return log_error_errno(r, "Failed to run event loop: %m");
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering pty_forward_get_last_char(forward, &last_char);
da054c3782f25b3b18243f6c76dcfcf90ba70274Lennart Poettering machine_died = pty_forward_get_ignore_vhangup(forward) == 0;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering log_info("Machine %s terminated.", argv[1]);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering log_info("Connection to machine %s terminated.", argv[1]);
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poetteringstatic int remove_image(int argc, char *argv[], void *userdata) {
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering "org.freedesktop.machine1",
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering "org.freedesktop.machine1.Manager",
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering "RemoveImage",
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering log_error("Could not remove image: %s", bus_error_message(&error, -r));
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poetteringstatic int rename_image(int argc, char *argv[], void *userdata) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering "org.freedesktop.machine1",
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering "org.freedesktop.machine1.Manager",
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering "RenameImage",
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering log_error("Could not rename image: %s", bus_error_message(&error, -r));
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poetteringstatic int clone_image(int argc, char *argv[], void *userdata) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering "org.freedesktop.machine1",
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering "org.freedesktop.machine1.Manager",
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering log_error("Could not clone image: %s", bus_error_message(&error, -r));
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poetteringstatic int read_only_image(int argc, char *argv[], void *userdata) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering int b = true, r;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering log_error("Failed to parse boolean argument: %s", argv[2]);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering "org.freedesktop.machine1",
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering "org.freedesktop.machine1.Manager",
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering "MarkImageReadOnly",
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering log_error("Could not mark image read-only: %s", bus_error_message(&error, -r));
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poetteringstatic int start_machine(int argc, char *argv[], void *userdata) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering _cleanup_free_ char *e = NULL, *unit = NULL;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering log_error("Invalid machine name %s.", argv[i]);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering unit = unit_name_build("systemd-nspawn", e, ".service");
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering "org.freedesktop.systemd1.Manager",
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering r = sd_bus_message_set_allow_interactive_authorization(m, true);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering r = sd_bus_message_append(m, "ss", unit, "fail");
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering r = sd_bus_call(bus, m, 0, &error, &reply);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering log_error("Failed to start unit: %s", bus_error_message(&error, -r));
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering r = sd_bus_message_read(reply, "o", &object);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poetteringstatic int enable_machine(int argc, char *argv[], void *userdata) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering method = streq(argv[0], "enable") ? "EnableUnitFiles" : "DisableUnitFiles";
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering "org.freedesktop.systemd1.Manager",
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = sd_bus_message_set_allow_interactive_authorization(m, true);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = sd_bus_message_open_container(m, 'a', "s");
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering _cleanup_free_ char *e = NULL, *unit = NULL;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering log_error("Invalid machine name %s.", argv[i]);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering unit = unit_name_build("systemd-nspawn", e, ".service");
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = sd_bus_message_append(m, "bb", false, false);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = sd_bus_message_append(m, "b", false);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = sd_bus_call(bus, m, 0, &error, &reply);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering log_error("Failed to enable or disable unit: %s", bus_error_message(&error, -r));
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = sd_bus_message_read(reply, "b", carries_install_info);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering "org.freedesktop.systemd1.Manager",
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = sd_bus_message_set_allow_interactive_authorization(m, true);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = sd_bus_call(bus, m, 0, &error, NULL);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering log_error("Failed to reload daemon: %s", bus_error_message(&error, -r));
56159e0d918e9a9be07988133bb2847779325de0Lennart Poetteringstatic int help(int argc, char *argv[], void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("%s [OPTIONS...] {COMMAND} ...\n\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering "Send control commands to or query the virtual machine and container\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering "registration manager.\n\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " -h --help Show this help\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " --version Show package version\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " --no-pager Do not pipe output into a pager\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " --no-legend Do not show the headers and footers\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " -H --host=[USER@]HOST Operate on remote host\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " -M --machine=CONTAINER Operate on local container\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " -p --property=NAME Show only properties by this name\n"
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering " -q --quiet Suppress output\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " -a --all Show all properties, including empty ones\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " -l --full Do not ellipsize output\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " --kill-who=WHO Who to send signal to\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " -s --signal=SIGNAL Which signal to send\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " --read-only Create read-only bind mount\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " --mkdir Create directory before bind mounting, if missing\n\n"
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering "Machine Commands:\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " list List running VMs and containers\n"
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering " status NAME... Show VM/container details\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " show NAME... Show properties of one or more VMs/containers\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " login NAME Get a login prompt on a container\n"
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering " start NAME... Start container as a service\n"
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering " enable NAME... Enable automatic container start at boot\n"
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering " disable NAME... Disable automatic container start at boot\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " poweroff NAME... Power off one or more containers\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " reboot NAME... Reboot one or more containers\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " terminate NAME... Terminate one or more VMs/containers\n"
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering " kill NAME... Send signal to processes of a VM/container\n"
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering " copy-to NAME PATH [PATH] Copy files from the host to a container\n"
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering " copy-from NAME PATH [PATH] Copy files from a container to the host\n"
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering " bind NAME PATH [PATH] Bind mount a path from the host into a container\n\n"
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering "Image Commands:\n"
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering " list-images Show available images\n"
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering " image-status NAME... Show image details\n"
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering " show-image NAME... Show properties of image\n"
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering " clone NAME NAME Clone an image\n"
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering " rename NAME NAME Rename an image\n"
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering " read-only NAME [BOOL] Mark or unmark image read-only\n"
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering " remove NAME... Remove an image\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int parse_argv(int argc, char *argv[]) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "version", no_argument, NULL, ARG_VERSION },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "property", required_argument, NULL, 'p' },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "no-pager", no_argument, NULL, ARG_NO_PAGER },
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "kill-who", required_argument, NULL, ARG_KILL_WHO },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "signal", required_argument, NULL, 's' },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "host", required_argument, NULL, 'H' },
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering { "machine", required_argument, NULL, 'M' },
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering { "read-only", no_argument, NULL, ARG_READ_ONLY },
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering { "mkdir", no_argument, NULL, ARG_MKDIR },
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering while ((c = getopt_long(argc, argv, "hp:als:H:M:q", options, NULL)) >= 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* If the user asked for a particular
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * property, show it to him, even if it is
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_signal = signal_from_string_try_harder(optarg);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to parse signal string %s.", optarg);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poetteringstatic int machinectl_main(int argc, char *argv[], sd_bus *bus) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering { "list", VERB_ANY, 1, VERB_DEFAULT, list_machines },
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering { "list-images", VERB_ANY, 1, 0, list_images },
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering { "status", 2, VERB_ANY, 0, show_machine },
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering { "image-status",2, VERB_ANY, 0, show_image },
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering { "show", VERB_ANY, VERB_ANY, 0, show_machine },
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering { "show-image", VERB_ANY, VERB_ANY, 0, show_image },
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering { "terminate", 2, VERB_ANY, 0, terminate_machine },
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering { "reboot", 2, VERB_ANY, 0, reboot_machine },
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering { "poweroff", 2, VERB_ANY, 0, poweroff_machine },
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering { "kill", 2, VERB_ANY, 0, kill_machine },
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering { "remove", 2, VERB_ANY, 0, remove_image },
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering { "read-only", 2, 3, 0, read_only_image },
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering { "start", 2, VERB_ANY, 0, start_machine },
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering { "enable", 2, VERB_ANY, 0, enable_machine },
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering { "disable", 2, VERB_ANY, 0, enable_machine },
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering return dispatch_verb(argc, argv, verbs, bus);
249968612f16a71df909d6e73785c18a9ff36a65Lennart Poettering _cleanup_bus_close_unref_ sd_bus *bus = NULL;
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering r = bus_open_transport(arg_transport, arg_host, false, &bus);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error_errno(r, "Failed to create bus connection: %m");