diff options
author | Luca Boccassi <bluca@debian.org> | 2022-01-22 01:53:54 +0000 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2022-01-24 00:21:15 +0900 |
commit | 2ef20244625c9cebff7117ad1d15d0a3fad4c0fd (patch) | |
tree | bf1b02ca14fbcbe8f5f9aef18b6aa1628e5427c1 | |
parent | de4fe289cfab789d249752aa7df851c792658f21 (diff) | |
download | systemd-2ef20244625c9cebff7117ad1d15d0a3fad4c0fd.tar.gz |
portable: add support for ExtensionDirectories in --extension
Same as for the root os image, support passing a directory, using
the new ExtensionDirectories setting.
-rw-r--r-- | docs/PORTABLE_SERVICES.md | 5 | ||||
-rw-r--r-- | man/portablectl.xml | 5 | ||||
-rw-r--r-- | src/portable/portable.c | 33 | ||||
-rwxr-xr-x | test/units/testsuite-29.sh | 12 |
4 files changed, 40 insertions, 15 deletions
diff --git a/docs/PORTABLE_SERVICES.md b/docs/PORTABLE_SERVICES.md index dd9164126f..6fb61d5e87 100644 --- a/docs/PORTABLE_SERVICES.md +++ b/docs/PORTABLE_SERVICES.md @@ -284,9 +284,12 @@ following must be also be observed: 4. The upper extension(s) image(s) must at least contain one matching unit file each, with the right name prefix and suffix (see above). +5. As with the base/OS image, the upper extension(s) image(s) must be a plain + sub-directory, a btrfs subvolume or a raw disk image. + ``` # portablectl attach --extension foobar_0.7.23.raw debian-runtime_11.1.raw foobar -# portablectl attach --extension barbaz_7.0.23.raw debian-runtime_11.1.raw barbaz +# portablectl attach --extension barbaz_7.0.23/ debian-runtime_11.1.raw barbaz ``` ## Execution Environment diff --git a/man/portablectl.xml b/man/portablectl.xml index f58275b158..719ea81aee 100644 --- a/man/portablectl.xml +++ b/man/portablectl.xml @@ -365,8 +365,9 @@ The image(s) must contain an <filename>extension-release</filename> file with metadata that matches what is defined in the <filename>os-release</filename> of <replaceable>IMAGE</replaceable>. See: <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>. - For more information on portable services with extensions, see the <literal>Extension Images</literal> - paragraph on <ulink url="https://systemd.io/PORTABLE_SERVICES">Portable Services</ulink>. + Images can be block images, btrfs subvolumes or directories. For more information on portable + services with extensions, see the <literal>Extension Images</literal> paragraph on + <ulink url="https://systemd.io/PORTABLE_SERVICES">Portable Services</ulink>. </para> <para>Note that the same extensions have to be specified, in the same order, when attaching diff --git a/src/portable/portable.c b/src/portable/portable.c index be311f94c4..b79992b245 100644 --- a/src/portable/portable.c +++ b/src/portable/portable.c @@ -253,6 +253,7 @@ static int extract_now( FOREACH_DIRENT(de, d, return log_debug_errno(errno, "Failed to read directory: %m")) { _cleanup_(portable_metadata_unrefp) PortableMetadata *m = NULL; + _cleanup_(mac_selinux_freep) char *con = NULL; _cleanup_close_ int fd = -1; if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) @@ -274,16 +275,16 @@ static int extract_now( continue; } - if (socket_fd >= 0) { - _cleanup_(mac_selinux_freep) char *con = NULL; #if HAVE_SELINUX - /* The units will be copied on the host's filesystem, so if they had a SELinux label - * we have to preserve it. Copy it out so that it can be applied later. */ + /* The units will be copied on the host's filesystem, so if they had a SELinux label + * we have to preserve it. Copy it out so that it can be applied later. */ - r = fgetfilecon_raw(fd, &con); - if (r < 0 && errno != ENODATA) - log_debug_errno(errno, "Failed to get SELinux file context from '%s', ignoring: %m", de->d_name); + r = fgetfilecon_raw(fd, &con); + if (r < 0 && errno != ENODATA) + log_debug_errno(errno, "Failed to get SELinux file context from '%s', ignoring: %m", de->d_name); #endif + + if (socket_fd >= 0) { struct iovec iov[] = { IOVEC_MAKE_STRING(de->d_name), IOVEC_MAKE((char *)"\0", sizeof(char)), @@ -295,7 +296,7 @@ static int extract_now( return log_debug_errno(r, "Failed to send unit metadata to parent: %m"); } - m = portable_metadata_new(de->d_name, NULL, NULL, fd); + m = portable_metadata_new(de->d_name, where, con, fd); if (!m) return -ENOMEM; fd = -1; @@ -336,10 +337,16 @@ static int portable_extract_by_path( r = loop_device_make_by_path(path, O_RDONLY, LO_FLAGS_PARTSCAN, &d); if (r == -EISDIR) { + _cleanup_free_ char *image_name = NULL; + /* We can't turn this into a loop-back block device, and this returns EISDIR? Then this is a directory * tree and not a raw device. It's easy then. */ - r = extract_now(path, matches, NULL, path_is_extension, -1, &os_release, &unit_files); + r = path_extract_filename(path, &image_name); + if (r < 0) + return log_error_errno(r, "Failed to extract image name from path '%s': %m", path); + + r = extract_now(path, matches, image_name, path_is_extension, -1, &os_release, &unit_files); if (r < 0) return r; @@ -872,6 +879,10 @@ static const char *root_setting_from_image(ImageType type) { return IN_SET(type, IMAGE_DIRECTORY, IMAGE_SUBVOLUME) ? "RootDirectory=" : "RootImage="; } +static const char *extension_setting_from_image(ImageType type) { + return IN_SET(type, IMAGE_DIRECTORY, IMAGE_SUBVOLUME) ? "ExtensionDirectories=" : "ExtensionImages="; +} + static int make_marker_text(const char *image_path, OrderedHashmap *extension_images, char **ret_text) { _cleanup_free_ char *text = NULL, *escaped_image_path = NULL; Image *ext; @@ -918,7 +929,6 @@ static int install_chroot_dropin( size_t *n_changes) { _cleanup_free_ char *text = NULL, *dropin = NULL; - Image *ext; int r; assert(image_path); @@ -936,6 +946,7 @@ static int install_chroot_dropin( if (endswith(m->name, ".service")) { const char *os_release_source, *root_type; _cleanup_free_ char *base_name = NULL; + Image *ext; root_type = root_setting_from_image(type); @@ -962,7 +973,7 @@ static int install_chroot_dropin( if (m->image_path && !path_equal(m->image_path, image_path)) ORDERED_HASHMAP_FOREACH(ext, extension_images) - if (!strextend(&text, "ExtensionImages=", ext->path, "\n")) + if (!strextend(&text, extension_setting_from_image(ext->type), ext->path, "\n")) return -ENOMEM; } diff --git a/test/units/testsuite-29.sh b/test/units/testsuite-29.sh index 0e0c8cf41d..5008a1b44c 100755 --- a/test/units/testsuite-29.sh +++ b/test/units/testsuite-29.sh @@ -103,7 +103,8 @@ portablectl detach --now --runtime --extension /usr/share/app1.raw /usr/share/mi # portablectl also works with directory paths rather than images -mkdir /tmp/rootdir /tmp/app1 /tmp/overlay /tmp/os-release-fix /tmp/os-release-fix/etc +mkdir /tmp/rootdir /tmp/app0 /tmp/app1 /tmp/overlay /tmp/os-release-fix /tmp/os-release-fix/etc +mount /usr/share/app0.raw /tmp/app0 mount /usr/share/app1.raw /tmp/app1 mount /usr/share/minimal_0.raw /tmp/rootdir @@ -124,7 +125,16 @@ systemctl is-active app1.service portablectl detach --now --runtime overlay app1 umount /tmp/overlay + +portablectl "${ARGS[@]}" attach --copy=symlink --now --runtime --extension /tmp/app0 --extension /tmp/app1 /tmp/rootdir app0 app1 + +systemctl is-active app0.service +systemctl is-active app1.service + +portablectl detach --now --runtime --extension /tmp/app0 --extension /tmp/app1 /tmp/rootdir app0 app1 + umount /tmp/rootdir +umount /tmp/app0 umount /tmp/app1 echo OK >/testok |