From d8f52ed25a9edce75fda5251c977b7898e33887e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Dec 2014 14:05:17 +0100 Subject: [PATCH] machinectl: add "enable" and "disable" verbs for enabling/disabling systemd-nspawn for containers This is basically just a shortcut for "systemctl enable systemd-nspawn@.service", but does escaping. --- src/libsystemd/sd-bus/bus-util.c | 26 +++++++ src/libsystemd/sd-bus/bus-util.h | 2 + src/machine/machinectl.c | 118 ++++++++++++++++++++++++++++++- src/systemctl/systemctl.c | 34 ++------- 4 files changed, 148 insertions(+), 32 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c index c264f2d3f..29520f95d 100644 --- a/src/libsystemd/sd-bus/bus-util.c +++ b/src/libsystemd/sd-bus/bus-util.c @@ -1776,3 +1776,29 @@ int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) { return set_put_strdup(d->jobs, path); } + +int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) { + const char *type, *path, *source; + int r; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) { + if (!quiet) { + if (streq(type, "symlink")) + log_info("Created symlink from %s to %s.", path, source); + else + log_info("Removed symlink %s.", path); + } + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + return 0; +} diff --git a/src/libsystemd/sd-bus/bus-util.h b/src/libsystemd/sd-bus/bus-util.h index 31e7fadbb..e8a97cef9 100644 --- a/src/libsystemd/sd-bus/bus-util.h +++ b/src/libsystemd/sd-bus/bus-util.h @@ -210,3 +210,5 @@ int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path); int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet); DEFINE_TRIVIAL_CLEANUP_FUNC(BusWaitForJobs*, bus_wait_for_jobs_free); + +int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet); diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index b0c153349..0abc251cf 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -63,6 +63,7 @@ static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static char *arg_host = NULL; static bool arg_read_only = false; static bool arg_mkdir = false; +static bool arg_quiet = false; static void pager_open_if_enabled(void) { @@ -1480,13 +1481,116 @@ static int start_machine(int argc, char *argv[], void *userdata) { return log_oom(); } - r = bus_wait_for_jobs(w, false); + r = bus_wait_for_jobs(w, arg_quiet); if (r < 0) return r; return 0; } +static int enable_machine(int argc, char *argv[], void *userdata) { + _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL; + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + int carries_install_info = 0; + const char *method = NULL; + sd_bus *bus = userdata; + int r, i; + + assert(bus); + + method = streq(argv[0], "enable") ? "EnableUnitFiles" : "DisableUnitFiles"; + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + method); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_set_allow_interactive_authorization(m, true); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "s"); + if (r < 0) + return bus_log_create_error(r); + + for (i = 1; i < argc; i++) { + _cleanup_free_ char *e = NULL, *unit = NULL; + + if (!machine_name_is_valid(argv[i])) { + log_error("Invalid machine name %s.", argv[i]); + return -EINVAL; + } + + e = unit_name_escape(argv[i]); + if (!e) + return log_oom(); + + unit = unit_name_build("systemd-nspawn", e, ".service"); + if (!unit) + return log_oom(); + + r = sd_bus_message_append(m, "s", unit); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + if (streq(argv[0], "enable")) + r = sd_bus_message_append(m, "bb", false, false); + else + r = sd_bus_message_append(m, "b", false); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) { + log_error("Failed to enable or disable unit: %s", bus_error_message(&error, -r)); + return r; + } + + if (streq(argv[0], "enable")) { + r = sd_bus_message_read(reply, "b", carries_install_info); + if (r < 0) + return bus_log_parse_error(r); + } + + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); + if (r < 0) + return r; + + m = sd_bus_message_unref(m); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "Reload"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_set_allow_interactive_authorization(m, true); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, NULL); + if (r < 0) { + log_error("Failed to reload daemon: %s", bus_error_message(&error, -r)); + return r; + } + + return 0; +} + static int help(int argc, char *argv[], void *userdata) { printf("%s [OPTIONS...] {COMMAND} ...\n\n" @@ -1499,6 +1603,7 @@ static int help(int argc, char *argv[], void *userdata) { " -H --host=[USER@]HOST Operate on remote host\n" " -M --machine=CONTAINER Operate on local container\n" " -p --property=NAME Show only properties by this name\n" + " -q --quiet Suppress output\n" " -a --all Show all properties, including empty ones\n" " -l --full Do not ellipsize output\n" " --kill-who=WHO Who to send signal to\n" @@ -1511,6 +1616,8 @@ static int help(int argc, char *argv[], void *userdata) { " show NAME... Show properties of one or more VMs/containers\n" " login NAME Get a login prompt on a container\n" " start NAME... Start container as a service\n" + " enable NAME... Enable automatic container start at boot\n" + " disable NAME... Disable automatic container start at boot\n" " poweroff NAME... Power off one or more containers\n" " reboot NAME... Reboot one or more containers\n" " terminate NAME... Terminate one or more VMs/containers\n" @@ -1556,6 +1663,7 @@ static int parse_argv(int argc, char *argv[]) { { "machine", required_argument, NULL, 'M' }, { "read-only", no_argument, NULL, ARG_READ_ONLY }, { "mkdir", no_argument, NULL, ARG_MKDIR }, + { "quiet", no_argument, NULL, 'q' }, {} }; @@ -1564,7 +1672,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hp:als:H:M:", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "hp:als:H:M:q", options, NULL)) >= 0) switch (c) { @@ -1633,6 +1741,10 @@ static int parse_argv(int argc, char *argv[]) { arg_mkdir = true; break; + case 'q': + arg_quiet = true; + break; + case '?': return -EINVAL; @@ -1666,6 +1778,8 @@ static int machinectl_main(int argc, char *argv[], sd_bus *bus) { { "clone", 3, 3, 0, clone_image }, { "read-only", 2, 3, 0, read_only_image }, { "start", 2, VERB_ANY, 0, start_machine }, + { "enable", 2, VERB_ANY, 0, enable_machine }, + { "disable", 2, VERB_ANY, 0, enable_machine }, {} }; diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 060bfe28e..a6c7e91f5 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -1951,32 +1951,6 @@ static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_cha } } -static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) { - const char *type, *path, *source; - int r; - - r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)"); - if (r < 0) - return bus_log_parse_error(r); - - while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) { - if (!arg_quiet) { - if (streq(type, "symlink")) - log_info("Created symlink from %s to %s.", path, source); - else - log_info("Removed symlink %s.", path); - } - } - if (r < 0) - return bus_log_parse_error(r); - - r = sd_bus_message_exit_container(m); - if (r < 0) - return bus_log_parse_error(r); - - return 0; -} - static int set_default(sd_bus *bus, char **args) { _cleanup_free_ char *unit = NULL; UnitFileChange *changes = NULL; @@ -2024,7 +1998,7 @@ static int set_default(sd_bus *bus, char **args) { return r; } - r = deserialize_and_dump_unit_file_changes(reply); + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); if (r < 0) return r; @@ -5389,7 +5363,7 @@ static int enable_unit(sd_bus *bus, char **args) { return bus_log_parse_error(r); } - r = deserialize_and_dump_unit_file_changes(reply); + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); if (r < 0) return r; @@ -5488,7 +5462,7 @@ static int add_dependency(sd_bus *bus, char **args) { return r; } - r = deserialize_and_dump_unit_file_changes(reply); + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); if (r < 0) return r; @@ -5552,7 +5526,7 @@ static int preset_all(sd_bus *bus, char **args) { return r; } - r = deserialize_and_dump_unit_file_changes(reply); + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); if (r < 0) return r; -- 2.30.2