From: Lennart Poettering Date: Tue, 24 Feb 2015 17:23:40 +0000 (+0100) Subject: machined/machinectl: when "machinectl image-status" is used without arguments show... X-Git-Tag: v219.0~586 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=160e3793adf2da2bd9ae3fe6b8881bb937e6e71b machined/machinectl: when "machinectl image-status" is used without arguments show statistics about pool --- diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 61183a6bf..ddd2a4aad 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -803,7 +803,7 @@ static void print_image_status_info(sd_bus *bus, ImageStatusInfo *i) { printf("\t Limit: %s\n", s3); } -static int show_image_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) { +static int show_image_info(sd_bus *bus, const char *path, bool *new_line) { static const struct bus_properties_map map[] = { { "Name", "s", NULL, offsetof(ImageStatusInfo, name) }, @@ -822,7 +822,6 @@ static int show_image_info(const char *verb, sd_bus *bus, const char *path, bool ImageStatusInfo info = {}; int r; - assert(verb); assert(bus); assert(path); assert(new_line); @@ -848,6 +847,59 @@ static int show_image_info(const char *verb, sd_bus *bus, const char *path, bool return r; } +typedef struct PoolStatusInfo { + char *path; + uint64_t usage; + uint64_t limit; +} PoolStatusInfo; + +static void print_pool_status_info(sd_bus *bus, PoolStatusInfo *i) { + char bs[FORMAT_BYTES_MAX], *s; + + if (i->path) + printf("\t Path: %s\n", i->path); + + s = format_bytes(bs, sizeof(bs), i->usage); + if (s) + printf("\t Usage: %s\n", s); + + s = format_bytes(bs, sizeof(bs), i->limit); + if (s) + printf("\t Limit: %s\n", s); +} + +static int show_pool_info(sd_bus *bus) { + + static const struct bus_properties_map map[] = { + { "PoolPath", "s", NULL, offsetof(PoolStatusInfo, path) }, + { "PoolUsage", "t", NULL, offsetof(PoolStatusInfo, usage) }, + { "PoolLimit", "t", NULL, offsetof(PoolStatusInfo, limit) }, + {} + }; + + PoolStatusInfo info = { + .usage = (uint64_t) -1, + .limit = (uint64_t) -1, + }; + int r; + + assert(bus); + + r = bus_map_all_properties(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + map, + &info); + if (r < 0) + return log_error_errno(r, "Could not get properties: %m"); + + print_pool_status_info(bus, &info); + + free(info.path); + return 0; +} + + static int show_image_properties(sd_bus *bus, const char *path, bool *new_line) { int r; @@ -881,11 +933,15 @@ static int show_image(int argc, char *argv[], void *userdata) { pager_open_if_enabled(); - if (properties && argc <= 1) { + if (argc <= 1) { /* If no argument is specified, inspect the manager * itself */ - r = show_image_properties(bus, "/org/freedesktop/machine1", &new_line); + + if (properties) + r = show_image_properties(bus, "/org/freedesktop/machine1", &new_line); + else + r = show_pool_info(bus); if (r < 0) return r; } @@ -914,7 +970,7 @@ static int show_image(int argc, char *argv[], void *userdata) { if (properties) r = show_image_properties(bus, path, &new_line); else - r = show_image_info(argv[0], bus, path, &new_line); + r = show_image_info(bus, path, &new_line); } return r; @@ -2142,7 +2198,7 @@ static int machinectl_main(int argc, char *argv[], sd_bus *bus) { { "list", VERB_ANY, 1, VERB_DEFAULT, list_machines }, { "list-images", VERB_ANY, 1, 0, list_images }, { "status", 2, VERB_ANY, 0, show_machine }, - { "image-status", 2, VERB_ANY, 0, show_image }, + { "image-status", VERB_ANY, VERB_ANY, 0, show_image }, { "show", VERB_ANY, VERB_ANY, 0, show_machine }, { "show-image", VERB_ANY, VERB_ANY, 0, show_image }, { "terminate", 2, VERB_ANY, 0, terminate_machine }, diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index 0e5a494f8..c4f60b5b0 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -29,11 +29,99 @@ #include "bus-util.h" #include "bus-common-errors.h" #include "cgroup-util.h" +#include "btrfs-util.h" #include "machine-image.h" #include "image-dbus.h" #include "machined.h" #include "machine-dbus.h" +static int property_get_pool_path( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + assert(bus); + assert(reply); + + return sd_bus_message_append(reply, "s", "/var/lib/machines"); +} + +static int property_get_pool_usage( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_close_ int fd = -1; + uint64_t usage = (uint64_t) -1; + struct stat st; + + assert(bus); + assert(reply); + + /* We try to read the quota info from /var/lib/machines, as + * well as the usage of the loopback file + * /var/lib/machines.raw, and pick the larger value. */ + + fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY); + if (fd >= 0) { + BtrfsQuotaInfo q; + + if (btrfs_subvol_get_quota_fd(fd, &q) >= 0) + usage = q.referred; + } + + if (stat("/var/lib/machines.raw", &st) >= 0) { + if (usage == (uint64_t) -1 || st.st_blocks * 512ULL > usage) + usage = st.st_blocks * 512ULL; + } + + return sd_bus_message_append(reply, "t", usage); +} + +static int property_get_pool_limit( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_close_ int fd = -1; + uint64_t size = (uint64_t) -1; + struct stat st; + + assert(bus); + assert(reply); + + /* We try to read the quota limit from /var/lib/machines, as + * well as the size of the loopback file + * /var/lib/machines.raw, and pick the smaller value. */ + + fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY); + if (fd >= 0) { + BtrfsQuotaInfo q; + + if (btrfs_subvol_get_quota_fd(fd, &q) >= 0) + size = q.referred_max; + } + + if (stat("/var/lib/machines.raw", &st) >= 0) { + if (size == (uint64_t) -1 || (uint64_t) st.st_size < size) + size = st.st_size; + } + + return sd_bus_message_append(reply, "t", size); +} + static int method_get_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Manager *m = userdata; @@ -690,6 +778,9 @@ static int method_mark_image_read_only(sd_bus *bus, sd_bus_message *message, voi const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0), + SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage, 0, 0), + SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit, 0, 0), SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),