machinectl.c revision 90615ad79188c360c0571b0a0d2ed81d88ece1ab
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering This file is part of systemd.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering Copyright 2013 Lennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering systemd is free software; you can redistribute it and/or modify it
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering under the terms of the GNU Lesser General Public License as published by
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering (at your option) any later version.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering systemd is distributed in the hope that it will be useful, but
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering Lesser General Public License for more details.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering You should have received a copy of the GNU Lesser General Public License
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic bool arg_all = false;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic bool arg_full = false;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic bool arg_no_pager = false;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic bool arg_legend = true;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic bool arg_read_only = false;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic bool arg_mkdir = false;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic bool arg_quiet = false;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic bool arg_ask_password = true;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic OutputMode arg_output = OUTPUT_SHORT;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic bool arg_force = false;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic const char* arg_dkr_index_url = NULL;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poetteringstatic void pager_open_if_enabled(void) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic void polkit_agent_open_if_enabled(void) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering /* Open the polkit agent as a child process if necessary */
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (arg_transport != BUS_TRANSPORT_LOCAL)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic OutputFlags get_output_flags(void) {
baed47c3c20512507e497058d388782400a072f6Lennart Poettering (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int compare_machine_info(const void *a, const void *b) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering const MachineInfo *x = a, *y = b;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int list_machines(int argc, char *argv[], void *userdata) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering size_t max_name = strlen("MACHINE"), max_class = strlen("CLASS"), max_service = strlen("SERVICE");
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
baed47c3c20512507e497058d388782400a072f6Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering _cleanup_free_ MachineInfo *machines = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering const char *name, *class, *service, *object;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering size_t n_machines = 0, n_allocated = 0, j;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering "org.freedesktop.machine1",
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering "org.freedesktop.machine1.Manager",
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering "ListMachines",
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering log_error("Could not get machines: %s", bus_error_message(&error, -r));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = sd_bus_message_enter_container(reply, 'a', "(ssso)");
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!GREEDY_REALLOC(machines, n_allocated, n_machines + 1))
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering r = sd_bus_message_exit_container(reply);
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering qsort_safe(machines, n_machines, sizeof(MachineInfo), compare_machine_info);
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering for (j = 0; j < n_machines; j++)
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering printf("\n%zu machines listed.\n", n_machines);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringtypedef struct ImageInfo {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int compare_image_info(const void *a, const void *b) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering const ImageInfo *x = a, *y = b;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int list_images(int argc, char *argv[], void *userdata) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering size_t max_name = strlen("NAME"), max_type = strlen("TYPE"), max_size = strlen("USAGE"), max_crtime = strlen("CREATED"), max_mtime = strlen("MODIFIED");
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
baed47c3c20512507e497058d388782400a072f6Lennart Poettering "org.freedesktop.machine1",
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering "org.freedesktop.machine1.Manager",
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering log_error("Could not get images: %s", bus_error_message(&error, -r));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssbttto)");
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering while ((r = sd_bus_message_read(reply, "(ssbttto)", &name, &type, &read_only, &crtime, &mtime, &size, &object)) > 0) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering char buf[MAX(FORMAT_TIMESTAMP_MAX, FORMAT_BYTES_MAX)];
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!GREEDY_REALLOC(images, n_allocated, n_images + 1))
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l = strlen(strna(format_timestamp(buf, sizeof(buf), crtime)));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l = strlen(strna(format_timestamp(buf, sizeof(buf), mtime)));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l = strlen(strna(format_bytes(buf, sizeof(buf), size)));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = sd_bus_message_exit_container(reply);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering qsort_safe(images, n_images, sizeof(ImageInfo), compare_image_info);
baed47c3c20512507e497058d388782400a072f6Lennart Poettering printf("%-*s %-*s %-3s %-*s %-*s %-*s\n",
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering for (j = 0; j < n_images; j++) {
baed47c3c20512507e497058d388782400a072f6Lennart Poettering char crtime_buf[FORMAT_TIMESTAMP_MAX], mtime_buf[FORMAT_TIMESTAMP_MAX], size_buf[FORMAT_BYTES_MAX];
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering printf("%-*s %-*s %s%-3s%s %-*s %-*s %-*s\n",
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering images[j].read_only ? ansi_highlight_red() : "", yes_no(images[j].read_only), images[j].read_only ? ansi_highlight_off() : "",
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering (int) max_size, strna(format_bytes(size_buf, sizeof(size_buf), images[j].size)),
baed47c3c20512507e497058d388782400a072f6Lennart Poettering (int) max_crtime, strna(format_timestamp(crtime_buf, sizeof(crtime_buf), images[j].crtime)),
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering (int) max_mtime, strna(format_timestamp(mtime_buf, sizeof(mtime_buf), images[j].mtime)));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering printf("\n%zu images listed.\n", n_images);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
baed47c3c20512507e497058d388782400a072f6Lennart Poettering if (arg_transport == BUS_TRANSPORT_REMOTE)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering endswith(unit, ".scope") ? "org.freedesktop.systemd1.Scope" : "org.freedesktop.systemd1.Service",
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering "ControlGroup",
baed47c3c20512507e497058d388782400a072f6Lennart Poettering log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = sd_bus_message_read(reply, "s", &cgroup);
baed47c3c20512507e497058d388782400a072f6Lennart Poettering if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags());
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
baed47c3c20512507e497058d388782400a072f6Lennart Poettering "org.freedesktop.machine1",
b7c9ae91d111b3e89d1ffc00e08f9ed97a8ff5dbLennart Poettering "org.freedesktop.machine1.Manager",
baed47c3c20512507e497058d388782400a072f6Lennart Poettering "GetMachineAddresses",
baed47c3c20512507e497058d388782400a072f6Lennart Poettering r = sd_bus_message_enter_container(reply, 'a', "(iay)");
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering const void *a;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering char buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = sd_bus_message_read(reply, "i", &family);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = sd_bus_message_read_array(reply, 'y', &a, &sz);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering fputs(inet_ntop(family, a, buffer, sizeof(buffer)), stdout);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = sd_bus_message_exit_container(reply);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = sd_bus_message_exit_container(reply);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int print_os_release(sd_bus *bus, const char *name, const char *prefix) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering "org.freedesktop.machine1",
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering "org.freedesktop.machine1.Manager",
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering "GetMachineOSRelease",
4da416aa20b956571d74720bc91222881443e24bLennart Poettering r = sd_bus_message_enter_container(reply, 'a', "{ss}");
pretty = v;
return bus_log_parse_error(r);
return bus_log_parse_error(r);
if (pretty)
typedef struct MachineStatusInfo {
char *name;
char *class;
char *service;
char *unit;
char *root_directory;
int *netif;
unsigned n_netif;
assert(i);
if (s1)
else if (s2)
if (i->leader > 0) {
if (i->service) {
if (i->class)
} else if (i->class)
if (i->root_directory)
if (i->n_netif > 0) {
for (c = 0; c < i->n_netif; c++) {
if (ifi < 0)
ifi = 0;
if (i->unit) {
i->unit,
NULL);
static int map_netif(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
size_t l;
return -EBADMSG;
if (!i->netif)
return -ENOMEM;
path,
map,
&info);
if (*new_line)
*new_line = true;
if (*new_line)
*new_line = true;
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
&reply,
return bus_log_parse_error(r);
if (properties)
typedef struct ImageStatusInfo {
char *name;
char *path;
char *type;
int read_only;
assert(i);
if (i->name) {
if (i->type)
if (i->path)
else if (s2)
else if (s2)
s4 = i->usage_exclusive != i->usage ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->usage_exclusive) : NULL;
else if (s3)
s4 = i->limit_exclusive != i->limit ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->limit_exclusive) : NULL;
else if (s3)
path,
map,
&info);
if (*new_line)
*new_line = true;
typedef struct PoolStatusInfo {
char *path;
if (i->path)
"/org/freedesktop/machine1",
map,
&info);
if (*new_line)
*new_line = true;
if (properties)
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
&reply,
return bus_log_parse_error(r);
if (properties)
if (!arg_kill_who)
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
NULL,
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
NULL,
bool copy_from;
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
NULL,
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
NULL,
assert(m);
if (*forward) {
char last_char = 0;
bool machine_died;
return -EOPNOTSUPP;
"path='/org/freedesktop/machine1',",
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
&reply,
return bus_log_parse_error(r);
if (machine_died)
return ret;
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
NULL,
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
NULL,
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
NULL,
return -EINVAL;
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
NULL,
return -EINVAL;
return log_oom();
return log_oom();
const char *object;
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&error,
&reply,
return bus_log_parse_error(r);
return log_oom();
int carries_install_info = 0;
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
method);
return bus_log_create_error(r);
return bus_log_create_error(r);
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
return bus_log_create_error(r);
return bus_log_create_error(r);
return bus_log_parse_error(r);
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&error,
NULL,
NULL);
unsigned priority;
assert(m);
assert(m);
static int transfer_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
assert(s);
if (!arg_quiet)
log_info("Continuing download in the background. Use \"machinectl cancel-transfer %" PRIu32 "\" to abort transfer.", PTR_TO_UINT32(userdata));
assert(m);
r = sd_bus_add_match(
bus,
"path='/org/freedesktop/import1'",
r = sd_bus_add_match(
bus,
return bus_log_parse_error(r);
if (!arg_quiet)
else if (path)
if (!local) {
return -EINVAL;
return log_oom();
return -EINVAL;
if (path) {
if (fd < 0)
bus,
"/org/freedesktop/import1",
return bus_log_create_error(r);
return bus_log_create_error(r);
else if (path)
if (!local) {
return -EINVAL;
return log_oom();
return -EINVAL;
if (path) {
if (fd < 0)
bus,
"/org/freedesktop/import1",
return bus_log_create_error(r);
return bus_log_create_error(r);
static void determine_compression_from_filename(const char *p) {
if (arg_format)
return -EINVAL;
if (path) {
if (fd < 0)
bus,
"/org/freedesktop/import1",
return bus_log_create_error(r);
return bus_log_create_error(r);
return -EINVAL;
if (path) {
if (fd < 0)
bus,
"/org/freedesktop/import1",
return bus_log_create_error(r);
return bus_log_create_error(r);
return -EINVAL;
local = l;
if (local) {
return log_oom();
return -EINVAL;
bus,
"/org/freedesktop/import1",
return bus_log_create_error(r);
return bus_log_create_error(r);
return -EINVAL;
local = l;
if (local) {
return log_oom();
return -EINVAL;
bus,
"/org/freedesktop/import1",
return bus_log_create_error(r);
return bus_log_create_error(r);
return -EINVAL;
if (tag) {
tag++;
return -EINVAL;
return -EINVAL;
if (local)
local++;
if (local) {
return -EINVAL;
bus,
"/org/freedesktop/import1",
return bus_log_create_error(r);
tag,
return bus_log_create_error(r);
typedef struct TransferInfo {
const char *type;
const char *remote;
const char *local;
double progress;
} TransferInfo;
static int compare_transfer_info(const void *a, const void *b) {
const TransferInfo *x = a, *y = b;
double progress;
r = sd_bus_call_method(
bus,
"/org/freedesktop/import1",
&error,
&reply,
NULL);
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(reply, "(usssdo)", &id, &type, &remote, &local, &progress, &object)) > 0) {
size_t l;
return log_oom();
if (l > max_type)
max_type = l;
if (l > max_remote)
max_remote = l;
if (l > max_local)
max_local = l;
n_transfers ++;
return bus_log_parse_error(r);
return bus_log_parse_error(r);
if (arg_legend)
for (j = 0; j < n_transfers; j++)
if (arg_legend)
r = sd_bus_call_method(
bus,
"/org/freedesktop/import1",
&error,
NULL,
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
NULL,
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
NULL,
" show NAME... Show properties of one or more VMs/containers\n"
" terminate NAME... Terminate one or more VMs/containers\n"
case ARG_VERSION:
return log_oom();
arg_all = true;
arg_all = true;
arg_full = true;
return -EINVAL;
if (arg_output < 0) {
return -EINVAL;
case ARG_NO_PAGER:
arg_no_pager = true;
case ARG_NO_LEGEND:
arg_legend = false;
case ARG_KILL_WHO:
if (arg_signal < 0) {
return -EINVAL;
case ARG_NO_ASK_PASSWORD:
arg_ask_password = false;
case ARG_READ_ONLY:
arg_read_only = true;
case ARG_MKDIR:
arg_mkdir = true;
arg_quiet = true;
case ARG_VERIFY:
if (arg_verify < 0) {
return -EINVAL;
case ARG_FORCE:
arg_force = true;
case ARG_DKR_INDEX_URL:
return -EINVAL;
case ARG_FORMAT:
return -EINVAL;
return -EINVAL;
log_open();
goto finish;
goto finish;
pager_close();