[systemd-commits] 3 commits - man/machinectl.xml man/systemd-nspawn.xml src/core src/machine src/nspawn src/shared

Lennart Poettering lennart at kemper.freedesktop.org
Wed Feb 25 13:07:05 PST 2015


 man/machinectl.xml                        |   25 ++++++++++---
 man/systemd-nspawn.xml                    |   13 ++++++
 src/core/unit.c                           |    2 -
 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 ++++++
 src/nspawn/nspawn.c                       |   20 +++++++++-
 src/shared/btrfs-util.c                   |   26 +++++++++++++
 src/shared/btrfs-util.h                   |    3 +
 src/shared/machine-image.c                |   13 ++++++
 src/shared/machine-image.h                |    2 +
 13 files changed, 258 insertions(+), 9 deletions(-)

New commits:
commit 5bd4b173605142c7be493aa4d958ebaef21f421d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Feb 25 22:05:14 2015 +0100

    unit: use weaker dependencies between mount and device units in --user mode
    
    When running in user mode unmounting of mount units when a device
    vanishes is unlikely to work, and even if it would work is already done
    by PID 1 anyway. HEnce, when creating implicit dependencies between
    mount units and their backing devices, created a Wants= type dependency
    in --user mode, but leave a BindsTo= dependency in --system mode.

diff --git a/src/core/unit.c b/src/core/unit.c
index ad5348b..875befa 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2839,7 +2839,7 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) {
         if (r < 0)
                 return r;
 
-        r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_BINDS_TO, device, true);
+        r = unit_add_two_dependencies(u, UNIT_AFTER, u->manager->running_as == SYSTEMD_SYSTEM ? UNIT_BINDS_TO : UNIT_WANTS, device, true);
         if (r < 0)
                 return r;
 

commit c6c8f6e218995852350e5e35c080dec788c42c3f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Feb 25 22:04:48 2015 +0100

    nspawn: make kill signal to use for PID 1 configurable

diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index e84d2b7..b991b5d 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -471,6 +471,19 @@
       </varlistentry>
 
       <varlistentry>
+        <term><option>--kill-signal=</option></term>
+
+        <listitem><para>Specify the process signal to send to the
+        container's PID 1 when nspawn itself receives SIGTERM, in
+        order to trigger an orderly shutdown of the
+        container. Defaults to SIGRTMIN+3 if <option>--boot</option>
+        is used (on systemd-compatible init systems SIGRTMIN+3
+        triggers an orderly shutdown). Takes a signal name like
+        <literal>SIGHUP</literal>, <literal>SIGTERM</literal> or
+        similar as argument.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
         <term><option>--link-journal=</option></term>
 
         <listitem><para>Control whether the container's journal shall
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 08bfdcf..8ce5fbe 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -181,6 +181,7 @@ static ExposePort *arg_expose_ports = NULL;
 static char **arg_property = NULL;
 static uid_t arg_uid_shift = UID_INVALID, arg_uid_range = 0x10000U;
 static bool arg_userns = false;
+static int arg_kill_signal = 0;
 
 static void help(void) {
         printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n"
@@ -229,6 +230,7 @@ static void help(void) {
                "     --capability=CAP       In addition to the default, retain specified\n"
                "                            capability\n"
                "     --drop-capability=CAP  Drop the specified capability from the default set\n"
+               "     --kill-signal=SIGNAL   Select signal to use for shutting down PID 1\n"
                "     --link-journal=MODE    Link up guest journal, one of no, auto, guest, host,\n"
                "                            try-guest, try-host\n"
                "  -j                        Equivalent to --link-journal=try-guest\n"
@@ -293,6 +295,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_TEMPLATE,
                 ARG_PROPERTY,
                 ARG_PRIVATE_USERS,
+                ARG_KILL_SIGNAL,
         };
 
         static const struct option options[] = {
@@ -332,6 +335,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "port",                  required_argument, NULL, 'p'                   },
                 { "property",              required_argument, NULL, ARG_PROPERTY          },
                 { "private-users",         optional_argument, NULL, ARG_PRIVATE_USERS     },
+                { "kill-signal",           required_argument, NULL, ARG_KILL_SIGNAL       },
                 {}
         };
 
@@ -767,6 +771,15 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_userns = true;
                         break;
 
+                case ARG_KILL_SIGNAL:
+                        arg_kill_signal = signal_from_string_try_harder(optarg);
+                        if (arg_kill_signal < 0) {
+                                log_error("Cannot parse signal: %s", optarg);
+                                return -EINVAL;
+                        }
+
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -829,6 +842,9 @@ static int parse_argv(int argc, char *argv[]) {
 
         arg_retain = (arg_retain | plus | (arg_private_network ? 1ULL << CAP_NET_ADMIN : 0)) & ~minus;
 
+        if (arg_boot && arg_kill_signal <= 0)
+                arg_kill_signal = SIGRTMIN+3;
+
         return 1;
 }
 
@@ -3559,7 +3575,7 @@ static int on_orderly_shutdown(sd_event_source *s, const struct signalfd_siginfo
 
         pid = PTR_TO_UINT32(userdata);
         if (pid > 0) {
-                if (kill(pid, SIGRTMIN+3) >= 0) {
+                if (kill(pid, arg_kill_signal) >= 0) {
                         log_info("Trying to halt container. Send SIGTERM again to trigger immediate termination.");
                         sd_event_source_set_userdata(s, NULL);
                         return 0;
@@ -4356,7 +4372,7 @@ int main(int argc, char *argv[]) {
                                         goto finish;
                                 }
 
-                                if (arg_boot) {
+                                if (arg_kill_signal > 0) {
                                         /* Try to kill the init system on SIGINT or SIGTERM */
                                         sd_event_add_signal(event, NULL, SIGINT, on_orderly_shutdown, UINT32_TO_PTR(pid));
                                         sd_event_add_signal(event, NULL, SIGTERM, on_orderly_shutdown, UINT32_TO_PTR(pid));

commit d6ce17c7f02ed3facdb45f65f546e587c2f00950
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Feb 24 23:50:37 2015 +0100

    machined,machinectl: add calls for changing container/VM quotas

diff --git a/man/machinectl.xml b/man/machinectl.xml
index 640cb8b..b50f03f 100644
--- a/man/machinectl.xml
+++ b/man/machinectl.xml
@@ -469,7 +469,7 @@
       <varlistentry>
         <term><command>clone</command> <replaceable>NAME</replaceable> <replaceable>NAME</replaceable></term>
 
-        <listitem><para>Clones a container or disk image. The
+        <listitem><para>Clones a container or VM image. The
         arguments specify the name of the image to clone and the name
         of the newly cloned image. Note that plain directory container
         images are cloned into subvolume images with this command.
@@ -481,7 +481,7 @@
       <varlistentry>
         <term><command>rename</command> <replaceable>NAME</replaceable> <replaceable>NAME</replaceable></term>
 
-        <listitem><para>Renames a container or disk image. The
+        <listitem><para>Renames a container or VM image. The
         arguments specify the name of the image to rename and the new
         name of the image.</para></listitem>
       </varlistentry>
@@ -489,22 +489,37 @@
       <varlistentry>
         <term><command>read-only</command> <replaceable>NAME</replaceable> [<replaceable>BOOL</replaceable>]</term>
 
-        <listitem><para>Marks or (unmarks) a container or disk image
+        <listitem><para>Marks or (unmarks) a container or VM image
         read-only. Takes a VM or container image name, followed by a
         boolean as arguments. If the boolean is omitted, positive is
         implied, i.e. the image is marked read-only.</para></listitem>
       </varlistentry>
 
-
       <varlistentry>
         <term><command>remove</command> <replaceable>NAME</replaceable>...</term>
 
-        <listitem><para>Removes one or more container or disk images.
+        <listitem><para>Removes one or more container or VM images.
         The special image <literal>.host</literal>, which refers to
         the host's own directory tree may not be
         removed.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><command>set-limit</command> [<replaceable>NAME</replaceable>] <replaceable>BYTES</replaceable></term>
+
+        <listitem><para>Sets the maximum size in bytes a specific
+        container or VM image, or all images may grow up to
+        (quota). Takes either one or two parameters. The first,
+        optional parameter refers to a container or VM image name. If
+        specified the size limit of the specified images is
+        changed. If omitted the overall size limit of the sum of all
+        images stored locally is changed. The final argument specifies
+        the size limit in bytes, possibly suffixed by the usual K, M,
+        G, T units. If the size limit shall be disabled, specify
+        <literal>-</literal> as size. This operation is currently only
+        supported on btrfs subvolume images.</para></listitem>
+      </varlistentry>
+
     </variablelist></refsect2>
 
     <refsect2><title>Image Transfer Commands</title><variablelist>
diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c
index 9061017..12c879a 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 1b4364c..b9def6b 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 ddd2a4a..d25b526 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 c4f60b5..fdb9d5f 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 0e99933..93aaf6a 100644
--- a/src/machine/org.freedesktop.machine1.conf
+++ b/src/machine/org.freedesktop.machine1.conf
@@ -105,6 +105,14 @@
                        send_member="MarkImageReadOnly"/>
 
                 <allow send_destination="org.freedesktop.machine1"
+                       send_interface="org.freedesktop.machine1.Manager"
+                       send_member="SetPoolLimit"/>
+
+                <allow send_destination="org.freedesktop.machine1"
+                       send_interface="org.freedesktop.machine1.Manager"
+                       send_member="SetImageLimit"/>
+
+                <allow send_destination="org.freedesktop.machine1"
                        send_interface="org.freedesktop.machine1.Machine"
                        send_member="GetAddresses"/>
 
@@ -150,6 +158,10 @@
 
                 <allow send_destination="org.freedesktop.machine1"
                        send_interface="org.freedesktop.machine1.Image"
+                       send_member="SetLimit"/>
+
+                <allow send_destination="org.freedesktop.machine1"
+                       send_interface="org.freedesktop.machine1.Image"
                        send_member="MarkReadOnly"/>
 
                 <allow receive_sender="org.freedesktop.machine1"/>
diff --git a/src/shared/btrfs-util.c b/src/shared/btrfs-util.c
index 980963b..6761501 100644
--- a/src/shared/btrfs-util.c
+++ b/src/shared/btrfs-util.c
@@ -669,3 +669,29 @@ int btrfs_quota_enable(const char *path, bool b) {
 
         return btrfs_quota_enable_fd(fd, b);
 }
+
+int btrfs_quota_limit_fd(int fd, uint64_t referred_max) {
+        struct btrfs_ioctl_qgroup_limit_args args = {
+                .lim.max_rfer =
+                        referred_max == (uint64_t) -1 ? 0 :
+                        referred_max == 0 ? 1 : referred_max,
+                .lim.flags = BTRFS_QGROUP_LIMIT_MAX_RFER,
+        };
+
+        assert(fd >= 0);
+
+        if (ioctl(fd, BTRFS_IOC_QGROUP_LIMIT, &args) < 0)
+                return -errno;
+
+        return 0;
+}
+
+int btrfs_quota_limit(const char *path, uint64_t referred_max) {
+        _cleanup_close_ int fd = -1;
+
+        fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
+        if (fd < 0)
+                return -errno;
+
+        return btrfs_quota_limit_fd(fd, referred_max);
+}
diff --git a/src/shared/btrfs-util.h b/src/shared/btrfs-util.h
index 93c3f13..9a1eb3f 100644
--- a/src/shared/btrfs-util.h
+++ b/src/shared/btrfs-util.h
@@ -67,3 +67,6 @@ int btrfs_defrag(const char *p);
 
 int btrfs_quota_enable_fd(int fd, bool b);
 int btrfs_quota_enable(const char *path, bool b);
+
+int btrfs_quota_limit_fd(int fd, uint64_t referred_max);
+int btrfs_quota_limit(const char *path, uint64_t referred_max);
diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c
index c734f14..c6d2850 100644
--- a/src/shared/machine-image.c
+++ b/src/shared/machine-image.c
@@ -613,6 +613,19 @@ int image_path_lock(const char *path, int operation, LockFile *global, LockFile
         return 0;
 }
 
+int image_set_limit(Image *i, uint64_t referred_max) {
+        assert(i);
+
+        if (path_equal(i->path, "/") ||
+            path_startswith(i->path, "/usr"))
+                return -EROFS;
+
+        if (i->type != IMAGE_SUBVOLUME)
+                return -ENOTSUP;
+
+        return btrfs_quota_limit(i->path, referred_max);
+}
+
 int image_name_lock(const char *name, int operation, LockFile *ret) {
         const char *p;
 
diff --git a/src/shared/machine-image.h b/src/shared/machine-image.h
index 314fd6d..df23949 100644
--- a/src/shared/machine-image.h
+++ b/src/shared/machine-image.h
@@ -70,3 +70,5 @@ bool image_name_is_valid(const char *s) _pure_;
 
 int image_path_lock(const char *path, int operation, LockFile *global, LockFile *local);
 int image_name_lock(const char *name, int operation, LockFile *ret);
+
+int image_set_limit(Image *i, uint64_t referred_max);



More information about the systemd-commits mailing list