machinectl.c revision 57ab2eabb8f92fad5239c7d4492e9c6e23ee0678
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers This file is part of systemd.
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers Copyright 2013 Lennart Poettering
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers systemd is free software; you can redistribute it and/or modify it
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers under the terms of the GNU Lesser General Public License as published by
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers the Free Software Foundation; either version 2.1 of the License, or
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers (at your option) any later version.
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers systemd is distributed in the hope that it will be useful, but
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers WITHOUT ANY WARRANTY; without even the implied warranty of
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers Lesser General Public License for more details.
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers You should have received a copy of the GNU Lesser General Public License
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers along with systemd; If not, see <http://www.gnu.org/licenses/>.
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sieversstatic bool arg_all = false;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sieversstatic bool arg_full = false;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sieversstatic bool arg_no_pager = false;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sieversstatic bool arg_legend = true;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sieversstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sieversstatic bool arg_read_only = false;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sieversstatic bool arg_mkdir = false;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sieversstatic bool arg_quiet = false;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sieversstatic bool arg_ask_password = true;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sieversstatic bool arg_force = false;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sieversstatic ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sieversstatic void pager_open_if_enabled(void) {
39883f622f392d8579f4428fc5a789a102efbb10Lennart Poetteringstatic void polkit_agent_open_if_enabled(void) {
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers /* Open the polkit agent as a child process if necessary */
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sieverstypedef struct MachineInfo {
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers const char *name;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers const char *class;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sieversstatic int compare_machine_info(const void *a, const void *b) {
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers const MachineInfo *x = a, *y = b;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sieversstatic int list_machines(int argc, char *argv[], void *userdata) {
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers size_t max_name = strlen("MACHINE"), max_class = strlen("CLASS"), max_service = strlen("SERVICE");
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers "org.freedesktop.machine1",
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers "org.freedesktop.machine1.Manager",
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers "ListMachines",
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers if (r < 0) {
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers log_error("Could not get machines: %s", bus_error_message(&error, -r));
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers r = sd_bus_message_enter_container(reply, 'a', "(ssso)");
6c7980093c4e39d07bf06484f96f489e236c7c29Kay Sievers while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
c51d84dc09476d9c06b8aac726220bf3c7d62e8dKay Sievers if (!GREEDY_REALLOC(machines, n_allocated, n_machines + 1))
if (l > max_name)
max_name = l;
if (l > max_class)
max_class = l;
if (l > max_service)
max_service = l;
n_machines ++;
return bus_log_parse_error(r);
return bus_log_parse_error(r);
if (arg_legend)
for (j = 0; j < n_machines; j++)
if (arg_legend)
typedef struct ImageInfo {
const char *name;
const char *type;
bool read_only;
} ImageInfo;
static int compare_image_info(const void *a, const void *b) {
const ImageInfo *x = a, *y = b;
size_t max_name = strlen("NAME"), max_type = strlen("TYPE"), max_size = strlen("USAGE"), max_crtime = strlen("CREATED"), max_mtime = strlen("MODIFIED");
int read_only, r;
r = sd_bus_call_method(
bus,
"/org/freedesktop/machine1",
&error,
&reply,
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(reply, "(ssbttto)", &name, &type, &read_only, &crtime, &mtime, &size, &object)) > 0) {
size_t l;
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() : "",
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;
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();