mirror of
https://github.com/systemd/systemd.git
synced 2024-11-27 04:03:36 +08:00
portable: add support for ExtensionDirectories in --extension
Same as for the root os image, support passing a directory, using the new ExtensionDirectories setting.
This commit is contained in:
parent
de4fe289cf
commit
2ef2024462
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user