machinectl.c revision fee6d013d859bc66f5c993530898fece53fab06d
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2013 Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic bool arg_all = false;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringstatic bool arg_full = false;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringstatic bool arg_no_pager = false;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringstatic bool arg_legend = true;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic bool arg_read_only = false;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringstatic bool arg_mkdir = false;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringstatic bool arg_quiet = false;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringstatic bool arg_ask_password = true;
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poetteringstatic OutputMode arg_output = OUTPUT_SHORT;
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poetteringstatic bool arg_force = false;
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poetteringstatic ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringstatic const char* arg_dkr_index_url = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic void pager_open_if_enabled(void) {
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersenstatic void polkit_agent_open_if_enabled(void) {
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen /* Open the polkit agent as a child process if necessary */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersentypedef struct MachineInfo {
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersenstatic int compare_machine_info(const void *a, const void *b) {
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen const MachineInfo *x = a, *y = b;
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersenstatic int list_machines(int argc, char *argv[], void *userdata) {
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen size_t max_name = strlen("MACHINE"), max_class = strlen("CLASS"), max_service = strlen("SERVICE");
84129d46cd6e95e142973da93aede4c7433c9600Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
84129d46cd6e95e142973da93aede4c7433c9600Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
84129d46cd6e95e142973da93aede4c7433c9600Lennart Poettering _cleanup_free_ MachineInfo *machines = NULL;
84129d46cd6e95e142973da93aede4c7433c9600Lennart Poettering const char *name, *class, *service, *object;
84129d46cd6e95e142973da93aede4c7433c9600Lennart Poettering size_t n_machines = 0, n_allocated = 0, j;
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen "org.freedesktop.machine1",
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen "org.freedesktop.machine1.Manager",
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering "ListMachines",
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen log_error("Could not get machines: %s", bus_error_message(&error, -r));
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering r = sd_bus_message_enter_container(reply, 'a', "(ssso)");
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt if (!GREEDY_REALLOC(machines, n_allocated, n_machines + 1))
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering r = sd_bus_message_exit_container(reply);
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering qsort_safe(machines, n_machines, sizeof(MachineInfo), compare_machine_info);
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering for (j = 0; j < n_machines; j++)
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering printf("\n%zu machines listed.\n", n_machines);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poetteringtypedef struct ImageInfo {
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poetteringstatic int compare_image_info(const void *a, const void *b) {
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering const ImageInfo *x = a, *y = b;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poetteringstatic int list_images(int argc, char *argv[], void *userdata) {
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering size_t max_name = strlen("NAME"), max_type = strlen("TYPE"), max_size = strlen("USAGE"), max_crtime = strlen("CREATED"), max_mtime = strlen("MODIFIED");
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering "org.freedesktop.machine1",
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering "org.freedesktop.machine1.Manager",
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering log_error("Could not get images: %s", bus_error_message(&error, -r));
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssbttto)");
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering while ((r = sd_bus_message_read(reply, "(ssbttto)", &name, &type, &read_only, &crtime, &mtime, &size, &object)) > 0) {
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering char buf[MAX(FORMAT_TIMESTAMP_MAX, FORMAT_BYTES_MAX)];
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering if (!GREEDY_REALLOC(images, n_allocated, n_images + 1))
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering l = strlen(strna(format_timestamp(buf, sizeof(buf), crtime)));
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering l = strlen(strna(format_timestamp(buf, sizeof(buf), mtime)));
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering l = strlen(strna(format_bytes(buf, sizeof(buf), size)));
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() : "",
if (arg_legend)
const char *cgroup;
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, get_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;
if (info) {
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;
if (info) {
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 (info) {
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;
if (!abs_host_path)
return log_oom();
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) {
static int process_forward(sd_event *event, PTYForward **forward, int master, bool ignore_vhangup, const char *name) {
char last_char = 0;
bool machine_died;
int ret = 0, r;
if (machine_died)
return ret;
return -EINVAL;
return -EOPNOTSUPP;
"path='/org/freedesktop/machine1',",
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
&reply,
return bus_log_parse_error(r);
return -EOPNOTSUPP;
"path='/org/freedesktop/machine1',",
bus,
"/org/freedesktop/machine1",
return bus_log_create_error(r);
return bus_log_create_error(r);
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/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;
case ARG_UID:
case ARG_SETENV:
return -EINVAL;
return log_oom();
return -EINVAL;
log_open();
goto finish;
goto finish;
pager_close();