From d6ce17c7f02ed3facdb45f65f546e587c2f00950 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 24 Feb 2015 23:50:37 +0100 Subject: machined,machinectl: add calls for changing container/VM quotas --- src/machine/image-dbus.c | 39 +++++++++++++++++++++ src/machine/image-dbus.h | 1 + src/machine/machinectl.c | 54 ++++++++++++++++++++++++++++- src/machine/machined-dbus.c | 57 +++++++++++++++++++++++++++++++ src/machine/org.freedesktop.machine1.conf | 12 +++++++ 5 files changed, 162 insertions(+), 1 deletion(-) (limited to 'src/machine') diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c index 9061017eef..12c879aff0 100644 --- a/src/machine/image-dbus.c +++ b/src/machine/image-dbus.c @@ -182,6 +182,44 @@ int bus_image_method_mark_read_only( return sd_bus_reply_method_return(message, NULL); } +int bus_image_method_set_limit( + sd_bus *bus, + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Image *image = userdata; + Manager *m = image->userdata; + uint64_t limit; + int r; + + assert(bus); + assert(message); + + r = sd_bus_message_read(message, "t", &limit); + if (r < 0) + return r; + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.machine1.manage-images", + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = image_set_limit(image, limit); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + const sd_bus_vtable image_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Image, name), 0), @@ -198,6 +236,7 @@ const sd_bus_vtable image_vtable[] = { SD_BUS_METHOD("Rename", "s", NULL, bus_image_method_rename, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Clone", "sb", NULL, bus_image_method_clone, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("MarkReadOnly", "b", NULL, bus_image_method_mark_read_only, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLimit", "t", NULL, bus_image_method_set_limit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END }; diff --git a/src/machine/image-dbus.h b/src/machine/image-dbus.h index 1b4364cbea..b9def6bc1b 100644 --- a/src/machine/image-dbus.h +++ b/src/machine/image-dbus.h @@ -34,3 +34,4 @@ int bus_image_method_remove(sd_bus *bus, sd_bus_message *message, void *userdata int bus_image_method_rename(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_image_method_clone(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_image_method_mark_read_only(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_image_method_set_limit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index ddd2a4aadb..d25b5266b8 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -1961,6 +1961,56 @@ static int cancel_transfer(int argc, char *argv[], void *userdata) { return 0; } +static int set_limit(int argc, char *argv[], void *userdata) { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + uint64_t limit; + int r; + + if (streq(argv[argc-1], "-")) + limit = (uint64_t) -1; + else { + off_t off; + + r = parse_size(argv[argc-1], 1024, &off); + if (r < 0) + return log_error("Failed to parse size: %s", argv[argc-1]); + + limit = (uint64_t) off; + } + + if (argc > 2) + /* With two arguments changes the quota limit of the + * specified image */ + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "SetImageLimit", + &error, + NULL, + "st", argv[1], limit); + else + /* With one argument changes the pool quota limit */ + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "SetPoolLimit", + &error, + NULL, + "t", limit); + + if (r < 0) { + log_error("Could not set limit: %s", bus_error_message(&error, -r)); + return r; + } + + return 0; +} + static int help(int argc, char *argv[], void *userdata) { printf("%s [OPTIONS...] {COMMAND} ...\n\n" @@ -2012,7 +2062,8 @@ static int help(int argc, char *argv[], void *userdata) { " clone NAME NAME Clone an image\n" " rename NAME NAME Rename an image\n" " read-only NAME [BOOL] Mark or unmark image read-only\n" - " remove NAME... Remove an image\n\n" + " remove NAME... Remove an image\n" + " set-limit [NAME] BYTES Set image size limit (quota)\n\n" "Image Transfer Commands:\n" " pull-tar URL [NAME] Download a TAR container image\n" " pull-raw URL [NAME] Download a RAW container or VM image\n" @@ -2221,6 +2272,7 @@ static int machinectl_main(int argc, char *argv[], sd_bus *bus) { { "pull-dkr", 2, 3, 0, pull_dkr }, { "list-transfers", VERB_ANY, 1, 0, list_transfers }, { "cancel-transfer", 2, VERB_ANY, 0, cancel_transfer }, + { "set-limit", 2, 3, 0, set_limit }, {} }; diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index c4f60b5b02..fdb9d5fac8 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -776,6 +776,61 @@ static int method_mark_image_read_only(sd_bus *bus, sd_bus_message *message, voi return bus_image_method_mark_read_only(bus, message, i, error); } +static int method_set_pool_limit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + uint64_t limit; + int r; + + assert(bus); + r = sd_bus_message_read(message, "t", &limit); + if (r < 0) + return r; + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.machine1.manage-machines", + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = btrfs_quota_limit("/var/lib/machines", limit); + if (r == -ENOTTY) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs."); + else if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to adjust quota limit: %m"); + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_set_image_limit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(image_unrefp) Image *i = NULL; + const char *name; + int r; + + assert(bus); + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + if (!image_name_is_valid(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name); + + r = image_find(name, &i); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name); + + i->userdata = userdata; + return bus_image_method_set_limit(bus, message, i, error); +} + const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0), @@ -803,6 +858,8 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_METHOD("RenameImage", "ss", NULL, method_rename_image, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CloneImage", "ssb", NULL, method_clone_image, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("MachineNew", "so", 0), SD_BUS_SIGNAL("MachineRemoved", "so", 0), SD_BUS_VTABLE_END diff --git a/src/machine/org.freedesktop.machine1.conf b/src/machine/org.freedesktop.machine1.conf index 0e99933488..93aaf6a377 100644 --- a/src/machine/org.freedesktop.machine1.conf +++ b/src/machine/org.freedesktop.machine1.conf @@ -104,6 +104,14 @@ send_interface="org.freedesktop.machine1.Manager" send_member="MarkImageReadOnly"/> + + + + @@ -148,6 +156,10 @@ send_interface="org.freedesktop.machine1.Image" send_member="Clone"/> + + -- cgit v1.2.3-54-g00ecf