machinectl.c revision b6b1849830f5e4a6065c3b0c993668e500c954d3
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier This file is part of systemd.
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier Copyright 2013 Lennart Poettering
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier systemd is free software; you can redistribute it and/or modify it
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier under the terms of the GNU Lesser General Public License as published by
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier the Free Software Foundation; either version 2.1 of the License, or
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier (at your option) any later version.
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier systemd is distributed in the hope that it will be useful, but
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier WITHOUT ANY WARRANTY; without even the implied warranty of
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier Lesser General Public License for more details.
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier You should have received a copy of the GNU Lesser General Public License
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier along with systemd; If not, see <http://www.gnu.org/licenses/>.
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalierstatic bool arg_all = false;
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalierstatic bool arg_full = false;
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poetteringstatic bool arg_no_pager = false;
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poetteringstatic bool arg_legend = true;
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poetteringstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poetteringstatic bool arg_read_only = false;
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poetteringstatic bool arg_mkdir = false;
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poetteringstatic void pager_open_if_enabled(void) {
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering /* Cache result before we open the pager */
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poetteringstatic int list_machines(int argc, char *argv[], void *userdata) {
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering const char *name, *class, *service, *object;
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier unsigned k = 0;
c6878637502b1717a110a9a7e8bba32a8583fcdfLennart Poettering "org.freedesktop.machine1",
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier "org.freedesktop.machine1.Manager",
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering "ListMachines",
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier log_error("Could not get machines: %s", bus_error_message(&error, -r));
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier printf("%-32s %-9s %-16s\n", "MACHINE", "CONTAINER", "SERVICE");
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssso)");
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier printf("%-32s %-9s %-16s\n", name, class, service);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevaliertypedef struct ImageInfo {
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmekstatic int compare_image_info(const void *a, const void *b) {
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek const ImageInfo *x = a, *y = b;
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek return strcmp(x->name, y->name);
4f36d4004c407c16508001a20450c5f14f7d4d31Dimitri John Ledkovstatic int list_images(int argc, char *argv[], void *userdata) {
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek size_t max_name = strlen("NAME"), max_type = strlen("TYPE"), max_size = strlen("SIZE"), max_crtime = strlen("CREATED"), max_mtime = strlen("MODIFIED");
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek _cleanup_free_ ImageInfo *images = NULL;
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek size_t n_images = 0, n_allocated = 0, j;
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek const char *name, *type, *object;
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek "org.freedesktop.machine1",
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek "org.freedesktop.machine1.Manager",
ad5ecc113821fbfa33f6fd43cdaee9c538cdff78Zbigniew Jędrzejewski-Szmek log_error("Could not get images: %s", bus_error_message(&error, -r));
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssbttto)");
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier while ((r = sd_bus_message_read(reply, "(ssbttto)", &name, &type, &read_only, &crtime, &mtime, &size, &object)) > 0) {
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier char buf[MAX(FORMAT_TIMESTAMP_MAX, FORMAT_BYTES_MAX)];
return log_oom();
if (l > max_name)
max_name = l;
if (l > max_type)
max_type = l;
if (crtime != 0) {
if (l > max_crtime)
max_crtime = l;
if (mtime != 0) {
if (l > max_mtime)
max_mtime = l;
if (l > max_size)
max_size = l;
n_images++;
return bus_log_parse_error(r);
return bus_log_parse_error(r);
if (arg_legend)
for (j = 0; j < n_images; j++) {
images[j].read_only ? ansi_highlight_red() : "", yes_no(images[j].read_only), images[j].read_only ? ansi_highlight_off() : "",
return bus_log_parse_error(r);
if (arg_legend)
const char *cgroup;
int r, output_flags;
if (!path)
return log_oom();
r = sd_bus_get_property(
bus,
"org.freedesktop.systemd1",
path,
&error,
&reply,
return bus_log_parse_error(r);
c = columns();
show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, output_flags);
static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2) {
"/org/freedesktop/machine1",
NULL,
&reply,
return bus_log_parse_error(r);
int family;
return bus_log_parse_error(r);
return bus_log_parse_error(r);
return bus_log_parse_error(r);
return bus_log_parse_error(r);
return bus_log_parse_error(r);
"/org/freedesktop/machine1",
NULL,
&reply,
return bus_log_parse_error(r);
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) {
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->path)
if (i->path)
else if (s2)
else if (s2)
s4 = i->size_exclusive != i->size ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->size_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;
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)
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,
const char *object;
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
&reply,
return bus_log_parse_error(r);
r = sd_bus_get_property(
bus,
&error,
&reply2,
return bus_log_parse_error(r);
char *dest, *host_path, *container_path, *host_dirname, *host_basename, *container_dirname, *container_basename, *t;
bool copy_from;
return -EINVAL;
if (child < 0)
if (child == 0) {
int containerfd;
int mntfd;
if (mntfd < 0) {
if (containerfd < 0) {
if (copy_from)
return -EIO;
return -EIO;
const char *dest;
return -EINVAL;
return -ENOTSUP;
mount_slave_created = true;
goto finish;
mount_slave_mounted = true;
goto finish;
goto finish;
mount_tmp_created = true;
goto finish;
mount_tmp_mounted = true;
if (arg_read_only)
goto finish;
goto finish;
mount_outside_created = true;
goto finish;
mount_outside_mounted = true;
mount_tmp_mounted = false;
mount_tmp_created = false;
mount_slave_mounted = false;
mount_slave_created = false;
if (child < 0) {
goto finish;
if (child == 0) {
const char *mount_inside;
int mntfd;
if (mntfd < 0) {
if (arg_mkdir)
goto finish;
r = -EIO;
goto finish;
r = -EIO;
goto finish;
if (mount_tmp_mounted)
if (mount_tmp_created)
if (mount_slave_mounted)
if (mount_slave_created)
const char *pty;
char last_char = 0;
return -ENOTSUP;
"/org/freedesktop/machine1",
return bus_log_create_error(r);
r = sd_bus_message_set_allow_interactive_authorization(m, true);
return bus_log_create_error(r);
return bus_log_create_error(r);
return bus_log_parse_error(r);
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,
" 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;
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_READ_ONLY:
arg_read_only = true;
case ARG_MKDIR:
arg_mkdir = true;
return -EINVAL;
log_open();
goto finish;
goto finish;
pager_close();