mirror of
https://github.com/systemd/systemd
synced 2024-07-21 18:24:38 +00:00
Merge pull request #31801 from flatcar-hub/krnowak/sysext-config
systemd-sysext: Add support for env vars, ephemeral layers and some fixes
This commit is contained in:
commit
b1d18b96c4
|
@ -378,6 +378,13 @@ All tools:
|
|||
`$SYSTEMD_CONFEXT_HIERARCHIES` works for confext images and supports the
|
||||
systemd-confext multi-call functionality of sysext.
|
||||
|
||||
* `$SYSTEMD_SYSEXT_MUTABLE_MODE` — this variable may be used to override the
|
||||
default mutability mode for hierarchies managed by `systemd-sysext`. It takes
|
||||
the same values the `--mutable=` command line switch does. Note that the
|
||||
command line still overrides the effect of the environment
|
||||
variable. Similarly, `$SYSTEMD_CONFEXT_MUTABLE_MODE` works for confext images
|
||||
and supports the systemd-confext multi-call functionality of sysext.
|
||||
|
||||
`systemd-tmpfiles`:
|
||||
|
||||
* `$SYSTEMD_TMPFILES_FORCE_SUBVOL` — if unset, `v`/`q`/`Q` lines will create
|
||||
|
|
|
@ -1077,7 +1077,7 @@ manpages = [
|
|||
['systemd-sysext',
|
||||
'8',
|
||||
['systemd-confext', 'systemd-confext.service', 'systemd-sysext.service'],
|
||||
''],
|
||||
'ENABLE_SYSEXT'],
|
||||
['systemd-system-update-generator', '8', [], ''],
|
||||
['systemd-system.conf',
|
||||
'5',
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
||||
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
|
||||
|
||||
<refentry id="systemd-sysext"
|
||||
<refentry id="systemd-sysext" conditional='ENABLE_SYSEXT'
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
|
||||
<refentryinfo>
|
||||
|
@ -221,21 +221,30 @@
|
|||
|
||||
<para>The following modes are supported:
|
||||
<orderedlist>
|
||||
<listitem><para><option>disabled</option>: Force immutable mode even if write routing
|
||||
directories exist below <filename>/var/lib/extensions.mutable/</filename>.
|
||||
This is the default.</para></listitem>
|
||||
<listitem><para><option>auto</option>: Automatic mode. Mutability is disabled by default
|
||||
and only enabled if a corresponding write routing directory exists below
|
||||
<filename>/var/lib/extensions.mutable/</filename>.</para></listitem>
|
||||
<listitem><para><option>disabled</option>: Force immutable mode even if write routing directories exist
|
||||
below <filename>/var/lib/extensions.mutable/</filename>. This is the default.</para></listitem>
|
||||
<listitem><para><option>auto</option>: Automatic mode. Mutability is disabled by default and only
|
||||
enabled if a corresponding write routing directory exists below
|
||||
<filename>/var/lib/extensions.mutable/</filename>.</para></listitem>
|
||||
<listitem><para><option>enabled</option>: Force mutable mode and automatically create write routing
|
||||
directories below <filename>/var/lib/extensions.mutable/</filename> when required.</para></listitem>
|
||||
directories below <filename>/var/lib/extensions.mutable/</filename> when required.</para></listitem>
|
||||
<listitem><para><option>import</option>: Force immutable mode like <option>disabled</option> above, but
|
||||
merge the contents of directories below <filename>/var/lib/extensions.mutable/</filename> into the host
|
||||
file system.</para></listitem>
|
||||
merge the contents of directories below <filename>/var/lib/extensions.mutable/</filename> into the host
|
||||
file system.</para></listitem>
|
||||
<listitem><para><option>ephemeral</option>: Force mutable mode like <option>enabled</option> above, but
|
||||
instead of using write routing directory below <filename>/var/lib/extensions.mutable/</filename>,
|
||||
<command>systemd-sysext</command> will use empty ephemeral directories. This means that the
|
||||
modifications made in the merged hierarchies will be gone when the hierarchies are
|
||||
unmerged.</para></listitem>
|
||||
<listitem><para><option>ephemeral-import</option>: Force mutable mode like <option>ephemeral</option>
|
||||
above, but instead of ignoring the contents of write routing directories under
|
||||
<filename>/var/lib/extensions.mutable/</filename>, merge them into the host file system, like
|
||||
<option>import</option> does.</para></listitem>
|
||||
</orderedlist>
|
||||
See "Options" below on specifying modes using the <option>--mutable=</option> command line option.</para>
|
||||
|
||||
<para>Mutable mode routes writes to subdirectories in <filename>/var/lib/extensions.mutable/</filename>.
|
||||
<para>With exception of the ephemeral mode, the mutable mode routes writes to subdirectories in
|
||||
<filename>/var/lib/extensions.mutable/</filename>.
|
||||
<simplelist type="horiz">
|
||||
<member>Writes to <filename>/usr/</filename> are directed to <filename>/var/lib/extensions.mutable/usr/</filename></member>,
|
||||
<member>writes to <filename>/opt/</filename> are directed to <filename>/var/lib/extensions.mutable/opt/</filename>, and</member>
|
||||
|
@ -253,10 +262,11 @@
|
|||
</simplelist>
|
||||
to route writes back to the original base directory hierarchy.</para>
|
||||
|
||||
<para> Alternatively, a temporary file system may be mounted to
|
||||
<para>Alternatively, a temporary file system may be mounted to
|
||||
<filename>/var/lib/extensions.mutable/</filename>, or symlinks in
|
||||
<filename>/var/lib/extensions.mutable/</filename> may point to sub-directories on a temporary
|
||||
file system (e.g. below <filename>/tmp/</filename>) to only allow ephemeral changes.</para>
|
||||
<filename>/var/lib/extensions.mutable/</filename> may point to sub-directories on a temporary file system
|
||||
(e.g. below <filename>/tmp/</filename>) to only allow ephemeral changes. Note that this is not the same
|
||||
as ephemeral mode, because the temporary file system will still exist after unmerging.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/>
|
||||
</refsect1>
|
||||
|
@ -403,6 +413,22 @@
|
|||
<filename>/var/lib/extensions.mutable/</filename> also merged into the host file system.</para>
|
||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>ephemeral</option></term>
|
||||
<listitem><para>force mutable mode, but with contents of write routing directories in
|
||||
<filename>/var/lib/extensions.mutable/</filename> being ignored, and modifications of the host
|
||||
file system being discarded after unmerge.</para>
|
||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>ephemeral-import</option></term>
|
||||
<listitem><para>force mutable mode, with contents of write routing directories in
|
||||
<filename>/var/lib/extensions.mutable/</filename> being merged into the host file system, but
|
||||
with the modifications made to the host file system being discarded after unmerge.</para>
|
||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||
|
|
|
@ -56,6 +56,8 @@ typedef enum MutableMode {
|
|||
MUTABLE_NO,
|
||||
MUTABLE_AUTO,
|
||||
MUTABLE_IMPORT,
|
||||
MUTABLE_EPHEMERAL,
|
||||
MUTABLE_EPHEMERAL_IMPORT,
|
||||
_MUTABLE_MAX,
|
||||
_MUTABLE_INVALID = -EINVAL,
|
||||
} MutableMode;
|
||||
|
@ -75,6 +77,8 @@ static MutableMode arg_mutable = MUTABLE_NO;
|
|||
/* Is set to IMAGE_CONFEXT when systemd is called with the confext functionality instead of the default */
|
||||
static ImageClass arg_image_class = IMAGE_SYSEXT;
|
||||
|
||||
static const char *mutable_extensions_base_dir = "/var/lib/extensions.mutable";
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_hierarchies, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
|
||||
|
@ -90,6 +94,7 @@ static const struct {
|
|||
const char *level_env;
|
||||
const char *scope_env;
|
||||
const char *name_env;
|
||||
const char *mode_env;
|
||||
const ImagePolicy *default_image_policy;
|
||||
unsigned long default_mount_flags;
|
||||
} image_class_info[_IMAGE_CLASS_MAX] = {
|
||||
|
@ -102,6 +107,7 @@ static const struct {
|
|||
.level_env = "SYSEXT_LEVEL",
|
||||
.scope_env = "SYSEXT_SCOPE",
|
||||
.name_env = "SYSTEMD_SYSEXT_HIERARCHIES",
|
||||
.mode_env = "SYSTEMD_SYSEXT_MUTABLE_MODE",
|
||||
.default_image_policy = &image_policy_sysext,
|
||||
.default_mount_flags = MS_RDONLY|MS_NODEV,
|
||||
},
|
||||
|
@ -114,11 +120,36 @@ static const struct {
|
|||
.level_env = "CONFEXT_LEVEL",
|
||||
.scope_env = "CONFEXT_SCOPE",
|
||||
.name_env = "SYSTEMD_CONFEXT_HIERARCHIES",
|
||||
.mode_env = "SYSTEMD_CONFEXT_MUTABLE_MODE",
|
||||
.default_image_policy = &image_policy_confext,
|
||||
.default_mount_flags = MS_RDONLY|MS_NODEV|MS_NOSUID|MS_NOEXEC,
|
||||
}
|
||||
};
|
||||
|
||||
static int parse_mutable_mode(const char *p) {
|
||||
int r;
|
||||
|
||||
assert(p);
|
||||
|
||||
if (streq(p, "auto"))
|
||||
return MUTABLE_AUTO;
|
||||
|
||||
if (streq(p, "import"))
|
||||
return MUTABLE_IMPORT;
|
||||
|
||||
if (streq(p, "ephemeral"))
|
||||
return MUTABLE_EPHEMERAL;
|
||||
|
||||
if (streq(p, "ephemeral-import"))
|
||||
return MUTABLE_EPHEMERAL_IMPORT;
|
||||
|
||||
r = parse_boolean(p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return r ? MUTABLE_YES : MUTABLE_NO;
|
||||
}
|
||||
|
||||
static int is_our_mount_point(
|
||||
ImageClass image_class,
|
||||
const char *p) {
|
||||
|
@ -636,17 +667,6 @@ static char *hierarchy_as_single_path_component(const char *hierarchy) {
|
|||
return TAKE_PTR(dir_name);
|
||||
}
|
||||
|
||||
static char *determine_mutable_directory_path_for_hierarchy(const char *hierarchy) {
|
||||
_cleanup_free_ char *dir_name = NULL;
|
||||
|
||||
assert(hierarchy);
|
||||
dir_name = hierarchy_as_single_path_component(hierarchy);
|
||||
if (!dir_name)
|
||||
return NULL;
|
||||
|
||||
return path_join("/var/lib/extensions.mutable", dir_name);
|
||||
}
|
||||
|
||||
static int paths_on_same_fs(const char *path1, const char *path2) {
|
||||
struct stat st1, st2;
|
||||
|
||||
|
@ -748,8 +768,13 @@ static int resolve_hierarchy(const char *hierarchy, char **ret_resolved_hierarch
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int resolve_mutable_directory(const char *hierarchy, char **ret_resolved_mutable_directory) {
|
||||
_cleanup_free_ char *path = NULL, *resolved_path = NULL;
|
||||
static int resolve_mutable_directory(
|
||||
const char *hierarchy,
|
||||
const char *workspace,
|
||||
char **ret_resolved_mutable_directory) {
|
||||
|
||||
_cleanup_free_ char *path = NULL, *resolved_path = NULL, *dir_name = NULL;
|
||||
const char *root = arg_root, *base = mutable_extensions_base_dir;
|
||||
int r;
|
||||
|
||||
assert(hierarchy);
|
||||
|
@ -761,14 +786,25 @@ static int resolve_mutable_directory(const char *hierarchy, char **ret_resolved_
|
|||
return 0;
|
||||
}
|
||||
|
||||
path = determine_mutable_directory_path_for_hierarchy(hierarchy);
|
||||
if (IN_SET(arg_mutable, MUTABLE_EPHEMERAL, MUTABLE_EPHEMERAL_IMPORT)) {
|
||||
/* We create mutable directory inside the temporary tmpfs workspace, which is a fixed
|
||||
* location that ignores arg_root. */
|
||||
root = NULL;
|
||||
base = workspace;
|
||||
}
|
||||
|
||||
dir_name = hierarchy_as_single_path_component(hierarchy);
|
||||
if (!dir_name)
|
||||
return log_oom();
|
||||
|
||||
path = path_join(base, dir_name);
|
||||
if (!path)
|
||||
return log_oom();
|
||||
|
||||
if (arg_mutable == MUTABLE_YES) {
|
||||
if (IN_SET(arg_mutable, MUTABLE_YES, MUTABLE_EPHEMERAL, MUTABLE_EPHEMERAL_IMPORT)) {
|
||||
_cleanup_free_ char *path_in_root = NULL;
|
||||
|
||||
path_in_root = path_join(arg_root, path);
|
||||
path_in_root = path_join(root, path);
|
||||
if (!path_in_root)
|
||||
return log_oom();
|
||||
|
||||
|
@ -777,7 +813,7 @@ static int resolve_mutable_directory(const char *hierarchy, char **ret_resolved_
|
|||
return log_error_errno(r, "Failed to create a directory '%s': %m", path_in_root);
|
||||
}
|
||||
|
||||
r = chase(path, arg_root, CHASE_PREFIX_ROOT, &resolved_path, NULL);
|
||||
r = chase(path, root, CHASE_PREFIX_ROOT, &resolved_path, NULL);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return log_error_errno(r, "Failed to resolve mutable directory '%s': %m", path);
|
||||
|
||||
|
@ -785,7 +821,7 @@ static int resolve_mutable_directory(const char *hierarchy, char **ret_resolved_
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int overlayfs_paths_new(const char *hierarchy, OverlayFSPaths **ret_op) {
|
||||
static int overlayfs_paths_new(const char *hierarchy, const char *workspace_path, OverlayFSPaths **ret_op) {
|
||||
_cleanup_free_ char *hierarchy_copy = NULL, *resolved_hierarchy = NULL, *resolved_mutable_directory = NULL;
|
||||
int r;
|
||||
|
||||
|
@ -799,7 +835,7 @@ static int overlayfs_paths_new(const char *hierarchy, OverlayFSPaths **ret_op) {
|
|||
r = resolve_hierarchy(hierarchy, &resolved_hierarchy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = resolve_mutable_directory(hierarchy, &resolved_mutable_directory);
|
||||
r = resolve_mutable_directory(hierarchy, workspace_path, &resolved_mutable_directory);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -818,6 +854,79 @@ static int overlayfs_paths_new(const char *hierarchy, OverlayFSPaths **ret_op) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int resolved_paths_equal(const char *resolved_a, const char *resolved_b) {
|
||||
/* Returns true if paths are of the same entry, false if not, <0 on error. */
|
||||
|
||||
if (path_equal(resolved_a, resolved_b))
|
||||
return 1;
|
||||
|
||||
if (!resolved_a || !resolved_b)
|
||||
return 0;
|
||||
|
||||
return inode_same(resolved_a, resolved_b, 0);
|
||||
}
|
||||
|
||||
static int maybe_import_mutable_directory(OverlayFSPaths *op) {
|
||||
int r;
|
||||
|
||||
assert(op);
|
||||
|
||||
/* If importing mutable layer and it actually exists and is not a hierarchy itself, add it just below
|
||||
* the meta path */
|
||||
|
||||
if (arg_mutable != MUTABLE_IMPORT || !op->resolved_mutable_directory)
|
||||
return 0;
|
||||
|
||||
r = resolved_paths_equal(op->resolved_hierarchy, op->resolved_mutable_directory);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to check equality of hierarchy %s and its mutable directory %s: %m", op->resolved_hierarchy, op->resolved_mutable_directory);
|
||||
if (r > 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ELOOP), "Not importing mutable directory for hierarchy %s as a lower dir, because it points to the hierarchy itself", op->hierarchy);
|
||||
|
||||
r = strv_extend(&op->lower_dirs, op->resolved_mutable_directory);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int maybe_import_ignored_mutable_directory(OverlayFSPaths *op) {
|
||||
_cleanup_free_ char *dir_name = NULL, *path = NULL, *resolved_path = NULL;
|
||||
int r;
|
||||
|
||||
assert(op);
|
||||
|
||||
/* If importing the ignored mutable layer and it actually exists and is not a hierarchy itself, add
|
||||
* it just below the meta path */
|
||||
if (arg_mutable != MUTABLE_EPHEMERAL_IMPORT)
|
||||
return 0;
|
||||
|
||||
dir_name = hierarchy_as_single_path_component(op->hierarchy);
|
||||
if (!dir_name)
|
||||
return log_oom();
|
||||
|
||||
path = path_join(mutable_extensions_base_dir, dir_name);
|
||||
if (!path)
|
||||
return log_oom();
|
||||
|
||||
r = chase(path, arg_root, CHASE_PREFIX_ROOT, &resolved_path, NULL);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return log_error_errno(r, "Failed to resolve mutable directory '%s': %m", path);
|
||||
|
||||
r = resolved_paths_equal(op->resolved_hierarchy, resolved_path);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to check equality of hierarchy %s and its mutable directory %s: %m", op->resolved_hierarchy, op->resolved_mutable_directory);
|
||||
|
||||
if (r > 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ELOOP), "Not importing mutable directory for hierarchy %s as a lower dir, because it points to the hierarchy itself", op->hierarchy);
|
||||
|
||||
r = strv_consume(&op->lower_dirs, TAKE_PTR(resolved_path));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int determine_top_lower_dirs(OverlayFSPaths *op, const char *meta_path) {
|
||||
int r;
|
||||
|
||||
|
@ -829,12 +938,13 @@ static int determine_top_lower_dirs(OverlayFSPaths *op, const char *meta_path) {
|
|||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
/* If importing mutable layer and it actually exists, add it just below the meta path */
|
||||
if (arg_mutable == MUTABLE_IMPORT && op->resolved_mutable_directory) {
|
||||
r = strv_extend(&op->lower_dirs, op->resolved_mutable_directory);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
r = maybe_import_mutable_directory(op);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = maybe_import_ignored_mutable_directory(op);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -898,7 +1008,12 @@ static int hierarchy_as_lower_dir(OverlayFSPaths *op) {
|
|||
}
|
||||
|
||||
if (arg_mutable == MUTABLE_IMPORT) {
|
||||
log_debug("Mutability for host hierarchy '%s' is disabled, so it will be a lowerdir", op->resolved_hierarchy);
|
||||
log_debug("Mutability for host hierarchy '%s' is disabled, so host hierarchy will be a lowerdir", op->resolved_hierarchy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (arg_mutable == MUTABLE_EPHEMERAL_IMPORT) {
|
||||
log_debug("Mutability for host hierarchy '%s' is ephemeral, so host hierarchy will be a lowerdir", op->resolved_hierarchy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -907,13 +1022,9 @@ static int hierarchy_as_lower_dir(OverlayFSPaths *op) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (path_equal(op->resolved_hierarchy, op->resolved_mutable_directory)) {
|
||||
log_debug("Host hierarchy '%s' will serve as upperdir.", op->resolved_hierarchy);
|
||||
return 1;
|
||||
}
|
||||
r = inode_same(op->resolved_hierarchy, op->resolved_mutable_directory, 0);
|
||||
r = resolved_paths_equal(op->resolved_hierarchy, op->resolved_mutable_directory);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to check inode equality of hierarchy %s and its mutable directory %s: %m", op->resolved_hierarchy, op->resolved_mutable_directory);
|
||||
return log_error_errno(r, "Failed to check equality of hierarchy %s and its mutable directory %s: %m", op->resolved_hierarchy, op->resolved_mutable_directory);
|
||||
if (r > 0) {
|
||||
log_debug("Host hierarchy '%s' will serve as upperdir.", op->resolved_hierarchy);
|
||||
return 1;
|
||||
|
@ -933,7 +1044,7 @@ static int determine_bottom_lower_dirs(OverlayFSPaths *op) {
|
|||
if (!r) {
|
||||
r = strv_extend(&op->lower_dirs, op->resolved_hierarchy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1116,6 +1227,10 @@ static int write_work_dir_file(ImageClass image_class, const char *meta_path, co
|
|||
if (!work_dir)
|
||||
return 0;
|
||||
|
||||
/* Do not store work dir path for ephemeral mode, it will be gone once this process is done. */
|
||||
if (IN_SET(arg_mutable, MUTABLE_EPHEMERAL, MUTABLE_EPHEMERAL_IMPORT))
|
||||
return 0;
|
||||
|
||||
work_dir_in_root = path_startswith(work_dir, empty_to_root(arg_root));
|
||||
if (!work_dir_in_root)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Workdir '%s' must not be outside root '%s'", work_dir, empty_to_root(arg_root));
|
||||
|
@ -1209,7 +1324,8 @@ static int merge_hierarchy(
|
|||
char **extensions,
|
||||
char **paths,
|
||||
const char *meta_path,
|
||||
const char *overlay_path) {
|
||||
const char *overlay_path,
|
||||
const char *workspace_path) {
|
||||
|
||||
_cleanup_(overlayfs_paths_freep) OverlayFSPaths *op = NULL;
|
||||
size_t extensions_used = 0;
|
||||
|
@ -1220,8 +1336,9 @@ static int merge_hierarchy(
|
|||
assert(paths);
|
||||
assert(meta_path);
|
||||
assert(overlay_path);
|
||||
assert(workspace_path);
|
||||
|
||||
r = overlayfs_paths_new(hierarchy, &op);
|
||||
r = overlayfs_paths_new(hierarchy, workspace_path, &op);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -1530,7 +1647,7 @@ static int merge_subprocess(
|
|||
|
||||
/* Create overlayfs mounts for all hierarchies */
|
||||
STRV_FOREACH(h, hierarchies) {
|
||||
_cleanup_free_ char *meta_path = NULL, *overlay_path = NULL;
|
||||
_cleanup_free_ char *meta_path = NULL, *overlay_path = NULL, *merge_hierarchy_workspace = NULL;
|
||||
|
||||
meta_path = path_join(workspace, "meta", *h); /* The place where to store metadata about this instance */
|
||||
if (!meta_path)
|
||||
|
@ -1540,6 +1657,11 @@ static int merge_subprocess(
|
|||
if (!overlay_path)
|
||||
return log_oom();
|
||||
|
||||
/* Temporary directory for merge_hierarchy needs, like ephemeral directories. */
|
||||
merge_hierarchy_workspace = path_join(workspace, "mh_workspace", *h);
|
||||
if (!merge_hierarchy_workspace)
|
||||
return log_oom();
|
||||
|
||||
r = merge_hierarchy(
|
||||
image_class,
|
||||
*h,
|
||||
|
@ -1547,7 +1669,8 @@ static int merge_subprocess(
|
|||
extensions,
|
||||
paths,
|
||||
meta_path,
|
||||
overlay_path);
|
||||
overlay_path,
|
||||
merge_hierarchy_workspace);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
@ -1615,9 +1738,10 @@ static int merge(ImageClass image_class,
|
|||
r = wait_for_terminate_and_check("(sd-merge)", pid, WAIT_LOG_ABNORMAL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (r == 123) /* exit code 123 means: didn't do anything */
|
||||
return 0;
|
||||
if (r > 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Failed to merge hierarchies");
|
||||
|
||||
r = need_reload(image_class, hierarchies, no_reload);
|
||||
if (r < 0)
|
||||
|
@ -1996,6 +2120,8 @@ static int verb_help(int argc, char **argv, void *userdata) {
|
|||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
"\n%3$sOptions:%4$s\n"
|
||||
" --mutable=yes|no|auto|import|ephemeral|ephemeral-import\n"
|
||||
" Specify a mutability mode of the merged hierarchy\n"
|
||||
" --no-pager Do not pipe output into a pager\n"
|
||||
" --no-legend Do not show the headers and footers\n"
|
||||
" --root=PATH Operate relative to root path\n"
|
||||
|
@ -2109,16 +2235,10 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
break;
|
||||
|
||||
case ARG_MUTABLE:
|
||||
if (streq(optarg, "auto"))
|
||||
arg_mutable = MUTABLE_AUTO;
|
||||
else if (streq(optarg, "import"))
|
||||
arg_mutable = MUTABLE_IMPORT;
|
||||
else {
|
||||
r = parse_boolean(optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse argument to --mutable=: %s", optarg);
|
||||
arg_mutable = r ? MUTABLE_YES : MUTABLE_NO;
|
||||
}
|
||||
r = parse_mutable_mode(optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse argument to --mutable=: %s", optarg);
|
||||
arg_mutable = r;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
|
@ -2153,12 +2273,23 @@ static int sysext_main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
const char* env_var;
|
||||
int r;
|
||||
|
||||
log_setup();
|
||||
|
||||
arg_image_class = invoked_as(argv, "systemd-confext") ? IMAGE_CONFEXT : IMAGE_SYSEXT;
|
||||
|
||||
env_var = getenv(image_class_info[arg_image_class].mode_env);
|
||||
if (env_var) {
|
||||
r = parse_mutable_mode(env_var);
|
||||
if (r < 0)
|
||||
log_warning("Failed to parse %s environment variable value '%s'. Ignoring.",
|
||||
image_class_info[arg_image_class].mode_env, env_var);
|
||||
else
|
||||
arg_mutable = r;
|
||||
}
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
|
|
@ -808,9 +808,23 @@ prep_root() {
|
|||
local r=${1}; shift
|
||||
local h=${1}; shift
|
||||
|
||||
if [[ -d ${r} ]]; then
|
||||
die "${r@Q} is being reused as a root, possibly a result of copy-pasting some test case and forgetting to rename the root directory name"
|
||||
fi
|
||||
|
||||
mkdir -p "${r}${h}" "${r}/usr/lib" "${r}/var/lib/extensions" "${r}/var/lib/extensions.mutable"
|
||||
}
|
||||
|
||||
prep_env() {
|
||||
local mode=${1}; shift
|
||||
|
||||
export SYSTEMD_SYSEXT_MUTABLE_MODE=${mode}
|
||||
}
|
||||
|
||||
drop_env() {
|
||||
unset -v SYSTEMD_SYSEXT_MUTABLE_MODE
|
||||
}
|
||||
|
||||
gen_os_release() {
|
||||
local r=${1}; shift
|
||||
|
||||
|
@ -946,6 +960,7 @@ check_usual_suspects_after_unmerge() {
|
|||
check_usual_suspects "${r}" "${h}" "after unmerge" "${@}"
|
||||
}
|
||||
|
||||
drop_env
|
||||
|
||||
#
|
||||
# no extension data in /var/lib/extensions.mutable/…, read-only hierarchy,
|
||||
|
@ -978,6 +993,7 @@ check_usual_suspects_after_unmerge "${fake_root}" "${hierarchy}" h
|
|||
|
||||
touch "${fake_root}${hierarchy}/should-still-fail-on-read-only-fs" && die "${fake_root}${hierarchy} is not read-only after unmerge"
|
||||
|
||||
|
||||
#
|
||||
# no extension data in /var/lib/extensions.mutable/…, mutable hierarchy,
|
||||
# mutability disabled by default
|
||||
|
@ -1307,7 +1323,7 @@ ln -sfTr "${real_ext_dir}" "${ext_data_path}"
|
|||
prep_ro_hierarchy "${fake_root}" "${hierarchy}"
|
||||
|
||||
# run systemd-sysext
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" --mutable=auto merge || die "expected merge to fail"
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" --mutable=auto merge && die "expected merge to fail"
|
||||
|
||||
|
||||
#
|
||||
|
@ -1476,6 +1492,427 @@ SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" u
|
|||
check_usual_suspects_after_unmerge "${fake_root}" "${hierarchy}" h
|
||||
|
||||
|
||||
#
|
||||
# /var/lib/extensions.mutable/… does not exist, but mutability is enabled
|
||||
# through an env var
|
||||
#
|
||||
# mutable merged
|
||||
#
|
||||
|
||||
|
||||
fake_root=${fake_roots_dir}/enabled-env-var
|
||||
hierarchy=/usr
|
||||
|
||||
prep_env "yes"
|
||||
prep_root "${fake_root}" "${hierarchy}"
|
||||
gen_os_release "${fake_root}"
|
||||
gen_test_ext_image "${fake_root}" "${hierarchy}"
|
||||
|
||||
ext_data_path=$(hierarchy_ext_mut_path "${fake_root}" "${hierarchy}")
|
||||
|
||||
prep_ro_hierarchy "${fake_root}" "${hierarchy}"
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-fail-on-read-only-fs" && die "${fake_root}${hierarchy} is not read-only"
|
||||
|
||||
test ! -d "${ext_data_path}" || die "extensions.mutable should not exist"
|
||||
|
||||
# run systemd-sysext
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" merge
|
||||
|
||||
test -d "${ext_data_path}" || die "extensions.mutable should exist now"
|
||||
touch "${fake_root}${hierarchy}/now-is-mutable" || die "${fake_root}${hierarchy} is not mutable"
|
||||
check_usual_suspects_after_merge "${fake_root}" "${hierarchy}" e h
|
||||
test -f "${ext_data_path}/now-is-mutable" || die "now-is-mutable is not stored in expected location"
|
||||
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" unmerge
|
||||
|
||||
check_usual_suspects_after_unmerge "${fake_root}" "${hierarchy}" h
|
||||
test -f "${ext_data_path}/now-is-mutable" || die "now-is-mutable disappeared from writable storage after unmerge"
|
||||
test ! -f "${fake_root}${hierarchy}/now-is-mutable" || die "now-is-mutable did not disappear from hierarchy after unmerge"
|
||||
drop_env
|
||||
|
||||
|
||||
#
|
||||
# /var/lib/extensions.mutable/… does not exist, auto-mutability through an env
|
||||
# var
|
||||
#
|
||||
# read-only merged
|
||||
#
|
||||
|
||||
|
||||
fake_root=${fake_roots_dir}/read-only-auto-env-var
|
||||
hierarchy=/usr
|
||||
|
||||
prep_env "auto"
|
||||
prep_root "${fake_root}" "${hierarchy}"
|
||||
gen_os_release "${fake_root}"
|
||||
gen_test_ext_image "${fake_root}" "${hierarchy}"
|
||||
|
||||
prep_ro_hierarchy "${fake_root}" "${hierarchy}"
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-fail-on-read-only-fs" && die "${fake_root}${hierarchy} is not read-only"
|
||||
|
||||
# run systemd-sysext
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" --mutable=auto merge
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-still-fail-on-read-only-fs" && die "${fake_root}${hierarchy} is not read-only"
|
||||
check_usual_suspects_after_merge "${fake_root}" "${hierarchy}" e h
|
||||
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" unmerge
|
||||
|
||||
check_usual_suspects_after_unmerge "${fake_root}" "${hierarchy}" h
|
||||
drop_env
|
||||
|
||||
|
||||
#
|
||||
# extension data in /var/lib/extensions.mutable/…, read-only hierarchy,
|
||||
# auto-mutability through an env var
|
||||
#
|
||||
# mutable merged
|
||||
#
|
||||
|
||||
|
||||
fake_root=${fake_roots_dir}/auto-mutable-env-var
|
||||
hierarchy=/usr
|
||||
|
||||
prep_env "auto"
|
||||
prep_root "${fake_root}" "${hierarchy}"
|
||||
gen_os_release "${fake_root}"
|
||||
gen_test_ext_image "${fake_root}" "${hierarchy}"
|
||||
|
||||
ext_data_path=$(hierarchy_ext_mut_path "${fake_root}" "${hierarchy}")
|
||||
prep_ext_mut "${ext_data_path}"
|
||||
|
||||
prep_ro_hierarchy "${fake_root}" "${hierarchy}"
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-fail-on-read-only-fs" && die "${fake_root}${hierarchy} is not read-only"
|
||||
|
||||
# run systemd-sysext
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" merge
|
||||
|
||||
touch "${fake_root}${hierarchy}/now-is-mutable" || die "${fake_root}${hierarchy} is not mutable"
|
||||
check_usual_suspects_after_merge "${fake_root}" "${hierarchy}" e h u
|
||||
test -f "${ext_data_path}/now-is-mutable" || die "now-is-mutable is not stored in expected location"
|
||||
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" unmerge
|
||||
|
||||
check_usual_suspects_after_unmerge "${fake_root}" "${hierarchy}" h
|
||||
test -f "${ext_data_path}/now-is-mutable" || die "now-is-mutable disappeared from writable storage after unmerge"
|
||||
test ! -f "${fake_root}${hierarchy}/now-is-mutable" || die "now-is-mutable did not disappear from hierarchy after unmerge"
|
||||
drop_env
|
||||
|
||||
|
||||
#
|
||||
# extension data in /var/lib/extensions.mutable/…, read-only hierarchy,
|
||||
# mutability disabled through an env var
|
||||
#
|
||||
# read-only merged
|
||||
#
|
||||
|
||||
|
||||
fake_root=${fake_roots_dir}/env-var-disabled
|
||||
hierarchy=/usr
|
||||
|
||||
prep_env "no"
|
||||
prep_root "${fake_root}" "${hierarchy}"
|
||||
gen_os_release "${fake_root}"
|
||||
gen_test_ext_image "${fake_root}" "${hierarchy}"
|
||||
|
||||
ext_data_path=$(hierarchy_ext_mut_path "${fake_root}" "${hierarchy}")
|
||||
prep_ext_mut "${ext_data_path}"
|
||||
|
||||
prep_ro_hierarchy "${fake_root}" "${hierarchy}"
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-fail-on-read-only-fs" && die "${fake_root}${hierarchy} is not read-only"
|
||||
|
||||
# run systemd-sysext
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" merge
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-be-read-only" && die "${fake_root}${hierarchy} is not read-only"
|
||||
check_usual_suspects_after_merge "${fake_root}" "${hierarchy}" e h
|
||||
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" unmerge
|
||||
|
||||
check_usual_suspects_after_unmerge "${fake_root}" "${hierarchy}" h
|
||||
drop_env
|
||||
|
||||
|
||||
#
|
||||
# /var/lib/extensions.mutable/… exists, but it's imported instead through an
|
||||
# env var
|
||||
#
|
||||
# read-only merged
|
||||
#
|
||||
|
||||
|
||||
fake_root=${fake_roots_dir}/imported-env-var
|
||||
hierarchy=/usr
|
||||
|
||||
prep_env "import"
|
||||
prep_root "${fake_root}" "${hierarchy}"
|
||||
gen_os_release "${fake_root}"
|
||||
gen_test_ext_image "${fake_root}" "${hierarchy}"
|
||||
|
||||
ext_data_path=$(hierarchy_ext_mut_path "${fake_root}" "${hierarchy}")
|
||||
prep_ext_mut "${ext_data_path}"
|
||||
|
||||
prep_ro_hierarchy "${fake_root}" "${hierarchy}"
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-fail-on-read-only-fs" && die "${fake_root}${hierarchy} is not read-only"
|
||||
|
||||
# run systemd-sysext
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" merge
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-still-fail-on-read-only-fs" && die "${fake_root}${hierarchy} is not read-only"
|
||||
|
||||
check_usual_suspects_after_merge "${fake_root}" "${hierarchy}" e h u
|
||||
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" unmerge
|
||||
|
||||
check_usual_suspects_after_unmerge "${fake_root}" "${hierarchy}" h
|
||||
drop_env
|
||||
|
||||
|
||||
#
|
||||
# extension data in /var/lib/extensions.mutable/…, read-only hierarchy,
|
||||
# mutability enabled through an env var, but overridden with a command-line
|
||||
# option
|
||||
#
|
||||
# read-only merged
|
||||
#
|
||||
|
||||
|
||||
fake_root=${fake_roots_dir}/env-var-overridden
|
||||
hierarchy=/usr
|
||||
|
||||
prep_env "yes"
|
||||
prep_root "${fake_root}" "${hierarchy}"
|
||||
gen_os_release "${fake_root}"
|
||||
gen_test_ext_image "${fake_root}" "${hierarchy}"
|
||||
|
||||
ext_data_path=$(hierarchy_ext_mut_path "${fake_root}" "${hierarchy}")
|
||||
prep_ext_mut "${ext_data_path}"
|
||||
|
||||
prep_ro_hierarchy "${fake_root}" "${hierarchy}"
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-fail-on-read-only-fs" && die "${fake_root}${hierarchy} is not read-only"
|
||||
|
||||
# run systemd-sysext
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" --mutable=no merge
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-be-read-only" && die "${fake_root}${hierarchy} is not read-only"
|
||||
check_usual_suspects_after_merge "${fake_root}" "${hierarchy}" e h
|
||||
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" unmerge
|
||||
|
||||
check_usual_suspects_after_unmerge "${fake_root}" "${hierarchy}" h
|
||||
drop_env
|
||||
|
||||
|
||||
#
|
||||
# extension data in /var/lib/extensions.mutable/…, read-only hierarchy,
|
||||
# ephemeral mutability, so extension data contents are ignored
|
||||
#
|
||||
# mutable merged
|
||||
#
|
||||
|
||||
|
||||
fake_root=${fake_roots_dir}/ephemeral
|
||||
hierarchy=/usr
|
||||
|
||||
prep_root "${fake_root}" "${hierarchy}"
|
||||
gen_os_release "${fake_root}"
|
||||
gen_test_ext_image "${fake_root}" "${hierarchy}"
|
||||
|
||||
ext_data_path=$(hierarchy_ext_mut_path "${fake_root}" "${hierarchy}")
|
||||
prep_ext_mut "${ext_data_path}"
|
||||
|
||||
prep_ro_hierarchy "${fake_root}" "${hierarchy}"
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-fail-on-read-only-fs" && die "${fake_root}${hierarchy} is not read-only"
|
||||
|
||||
# run systemd-sysext
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" --mutable=ephemeral merge
|
||||
|
||||
touch "${fake_root}${hierarchy}/now-is-mutable" || die "${fake_root}${hierarchy} is not mutable"
|
||||
check_usual_suspects_after_merge "${fake_root}" "${hierarchy}" e h
|
||||
test ! -f "${ext_data_path}/now-is-mutable" || die "now-is-mutable should not be stored in extension data"
|
||||
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" unmerge
|
||||
|
||||
check_usual_suspects_after_unmerge "${fake_root}" "${hierarchy}" h
|
||||
test ! -f "${ext_data_path}/now-is-mutable" || die "now-is-mutable should not appear in writable storage after unmerge"
|
||||
test ! -f "${fake_root}${hierarchy}/now-is-mutable" || die "now-is-mutable did not disappear from hierarchy after unmerge"
|
||||
|
||||
|
||||
#
|
||||
# extension data in /var/lib/extensions.mutable/…, read-only hierarchy,
|
||||
# ephemeral mutability through an env var, so extension data contents are
|
||||
# ignored
|
||||
#
|
||||
# mutable merged
|
||||
#
|
||||
|
||||
|
||||
fake_root=${fake_roots_dir}/ephemeral-env-var
|
||||
hierarchy=/usr
|
||||
|
||||
prep_env "ephemeral"
|
||||
prep_root "${fake_root}" "${hierarchy}"
|
||||
gen_os_release "${fake_root}"
|
||||
gen_test_ext_image "${fake_root}" "${hierarchy}"
|
||||
|
||||
ext_data_path=$(hierarchy_ext_mut_path "${fake_root}" "${hierarchy}")
|
||||
prep_ext_mut "${ext_data_path}"
|
||||
|
||||
prep_ro_hierarchy "${fake_root}" "${hierarchy}"
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-fail-on-read-only-fs" && die "${fake_root}${hierarchy} is not read-only"
|
||||
|
||||
# run systemd-sysext
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" merge
|
||||
|
||||
touch "${fake_root}${hierarchy}/now-is-mutable" || die "${fake_root}${hierarchy} is not mutable"
|
||||
check_usual_suspects_after_merge "${fake_root}" "${hierarchy}" e h
|
||||
test ! -f "${ext_data_path}/now-is-mutable" || die "now-is-mutable should not be stored in extension data"
|
||||
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" unmerge
|
||||
|
||||
check_usual_suspects_after_unmerge "${fake_root}" "${hierarchy}" h
|
||||
test ! -f "${ext_data_path}/now-is-mutable" || die "now-is-mutable should not appear in writable storage after unmerge"
|
||||
test ! -f "${fake_root}${hierarchy}/now-is-mutable" || die "now-is-mutable did not disappear from hierarchy after unmerge"
|
||||
drop_env
|
||||
|
||||
|
||||
#
|
||||
# extension data in /var/lib/extensions.mutable/…, read-only hierarchy,
|
||||
# ephemeral import mutability, so extension data contents are imported too
|
||||
#
|
||||
# mutable merged
|
||||
#
|
||||
|
||||
|
||||
fake_root=${fake_roots_dir}/ephemeral-import
|
||||
hierarchy=/usr
|
||||
|
||||
prep_root "${fake_root}" "${hierarchy}"
|
||||
gen_os_release "${fake_root}"
|
||||
gen_test_ext_image "${fake_root}" "${hierarchy}"
|
||||
|
||||
ext_data_path=$(hierarchy_ext_mut_path "${fake_root}" "${hierarchy}")
|
||||
prep_ext_mut "${ext_data_path}"
|
||||
|
||||
prep_ro_hierarchy "${fake_root}" "${hierarchy}"
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-fail-on-read-only-fs" && die "${fake_root}${hierarchy} is not read-only"
|
||||
|
||||
# run systemd-sysext
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" --mutable=ephemeral-import merge
|
||||
|
||||
touch "${fake_root}${hierarchy}/now-is-mutable" || die "${fake_root}${hierarchy} is not mutable"
|
||||
check_usual_suspects_after_merge "${fake_root}" "${hierarchy}" e h u
|
||||
test ! -f "${ext_data_path}/now-is-mutable" || die "now-is-mutable should not be stored in extension data"
|
||||
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" unmerge
|
||||
|
||||
check_usual_suspects_after_unmerge "${fake_root}" "${hierarchy}" h
|
||||
test ! -f "${ext_data_path}/now-is-mutable" || die "now-is-mutable should not appear in writable storage after unmerge"
|
||||
test ! -f "${fake_root}${hierarchy}/now-is-mutable" || die "now-is-mutable did not disappear from hierarchy after unmerge"
|
||||
|
||||
|
||||
#
|
||||
# extension data in /var/lib/extensions.mutable/…, read-only hierarchy,
|
||||
# ephemeral mutability through an env var, so extension data contents are
|
||||
# imported too
|
||||
#
|
||||
# mutable merged
|
||||
#
|
||||
|
||||
|
||||
fake_root=${fake_roots_dir}/ephemeral-import-env-var
|
||||
hierarchy=/usr
|
||||
|
||||
prep_env "ephemeral-import"
|
||||
prep_root "${fake_root}" "${hierarchy}"
|
||||
gen_os_release "${fake_root}"
|
||||
gen_test_ext_image "${fake_root}" "${hierarchy}"
|
||||
|
||||
ext_data_path=$(hierarchy_ext_mut_path "${fake_root}" "${hierarchy}")
|
||||
prep_ext_mut "${ext_data_path}"
|
||||
|
||||
prep_ro_hierarchy "${fake_root}" "${hierarchy}"
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-fail-on-read-only-fs" && die "${fake_root}${hierarchy} is not read-only"
|
||||
|
||||
# run systemd-sysext
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" merge
|
||||
|
||||
touch "${fake_root}${hierarchy}/now-is-mutable" || die "${fake_root}${hierarchy} is not mutable"
|
||||
check_usual_suspects_after_merge "${fake_root}" "${hierarchy}" e h u
|
||||
test ! -f "${ext_data_path}/now-is-mutable" || die "now-is-mutable should not be stored in extension data"
|
||||
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" unmerge
|
||||
|
||||
check_usual_suspects_after_unmerge "${fake_root}" "${hierarchy}" h
|
||||
test ! -f "${ext_data_path}/now-is-mutable" || die "now-is-mutable should not appear in writable storage after unmerge"
|
||||
test ! -f "${fake_root}${hierarchy}/now-is-mutable" || die "now-is-mutable did not disappear from hierarchy after unmerge"
|
||||
drop_env
|
||||
|
||||
|
||||
#
|
||||
# extension data pointing to mutable hierarchy, ephemeral import mutability
|
||||
#
|
||||
# expecting a failure here
|
||||
#
|
||||
|
||||
|
||||
fake_root=${fake_roots_dir}/ephemeral-import-self
|
||||
hierarchy=/usr
|
||||
|
||||
prep_root "${fake_root}" "${hierarchy}"
|
||||
gen_os_release "${fake_root}"
|
||||
gen_test_ext_image "${fake_root}" "${hierarchy}"
|
||||
|
||||
ext_data_path=$(hierarchy_ext_mut_path "${fake_root}" "${hierarchy}")
|
||||
real_ext_dir="${fake_root}${hierarchy}"
|
||||
prep_ext_mut "${real_ext_dir}"
|
||||
ln -sfTr "${real_ext_dir}" "${ext_data_path}"
|
||||
|
||||
prep_hierarchy "${fake_root}" "${hierarchy}"
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-succeed-on-read-only-fs" || die "${fake_root}${hierarchy} is not mutable"
|
||||
|
||||
# run systemd-sysext
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" --mutable=ephemeral-import merge && die 'expected merge to fail'
|
||||
|
||||
|
||||
#
|
||||
# extension data pointing to mutable hierarchy, import mutability
|
||||
#
|
||||
# expecting a failure here
|
||||
#
|
||||
|
||||
|
||||
fake_root=${fake_roots_dir}/import-self
|
||||
hierarchy=/usr
|
||||
|
||||
prep_root "${fake_root}" "${hierarchy}"
|
||||
gen_os_release "${fake_root}"
|
||||
gen_test_ext_image "${fake_root}" "${hierarchy}"
|
||||
|
||||
ext_data_path=$(hierarchy_ext_mut_path "${fake_root}" "${hierarchy}")
|
||||
real_ext_dir="${fake_root}${hierarchy}"
|
||||
prep_ext_mut "${real_ext_dir}"
|
||||
ln -sfTr "${real_ext_dir}" "${ext_data_path}"
|
||||
|
||||
prep_hierarchy "${fake_root}" "${hierarchy}"
|
||||
|
||||
touch "${fake_root}${hierarchy}/should-succeed-on-read-only-fs" || die "${fake_root}${hierarchy} is not mutable"
|
||||
|
||||
# run systemd-sysext
|
||||
SYSTEMD_SYSEXT_HIERARCHIES="${hierarchy}" systemd-sysext --root="${fake_root}" --mutable=import merge && die 'expected merge to fail'
|
||||
|
||||
|
||||
#
|
||||
# done
|
||||
#
|
||||
|
|
Loading…
Reference in a new issue