mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 02:03:37 +08:00
portable: support vpick
Resolve at attach/detach/inspect time, so that the image is pinned and requires re-attaching on update, given files are extracted from it so just passing img.v/ to RootImage= is not enough to get a portable image updated
This commit is contained in:
parent
421a4ba7e4
commit
8257508c58
@ -259,6 +259,9 @@ node /org/freedesktop/portable1 {
|
||||
on the system. Note that this method returns only after all the listed operations are completed,
|
||||
and due to the I/O involved it might take some time.</para>
|
||||
|
||||
<xi:include href="vpick.xml" xpointer="image"/>
|
||||
<xi:include href="vpick.xml" xpointer="directory"/>
|
||||
|
||||
<para><function>AttachImageWithExtensions()</function> attaches a portable image to the system.
|
||||
This method is a superset of <function>AttachImage()</function> with the addition of
|
||||
a list of extensions as input parameter, which will be overlaid on top of the main
|
||||
|
@ -141,6 +141,8 @@
|
||||
immediately started (blocking operation unless <option>--no-block</option> is passed) and/or enabled after
|
||||
attaching the image.</para>
|
||||
|
||||
<xi:include href="vpick.xml" xpointer="image"/>
|
||||
<xi:include href="vpick.xml" xpointer="directory"/>
|
||||
<xi:include href="version-info.xml" xpointer="v239"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -421,6 +423,8 @@
|
||||
<para>Note that the same extensions have to be specified, in the same order, when attaching
|
||||
and detaching.</para>
|
||||
|
||||
<xi:include href="vpick.xml" xpointer="image"/>
|
||||
<xi:include href="vpick.xml" xpointer="directory"/>
|
||||
<xi:include href="version-info.xml" xpointer="v249"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "strv.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "user-util.h"
|
||||
#include "vpick.h"
|
||||
|
||||
/* Markers used in the first line of our 20-portable.conf unit file drop-in to determine, that a) the unit file was
|
||||
* dropped there by the portable service logic and b) for which image it was dropped there. */
|
||||
@ -564,6 +565,7 @@ static int extract_image_and_extensions(
|
||||
_cleanup_free_ char *id = NULL, *version_id = NULL, *sysext_level = NULL, *confext_level = NULL;
|
||||
_cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL;
|
||||
_cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL, *extension_releases = NULL;
|
||||
_cleanup_(pick_result_done) PickResult result = PICK_RESULT_NULL;
|
||||
_cleanup_hashmap_free_ Hashmap *unit_files = NULL;
|
||||
_cleanup_strv_free_ char **valid_prefixes = NULL;
|
||||
_cleanup_(image_unrefp) Image *image = NULL;
|
||||
@ -572,7 +574,27 @@ static int extract_image_and_extensions(
|
||||
|
||||
assert(name_or_path);
|
||||
|
||||
r = image_find_harder(IMAGE_PORTABLE, name_or_path, NULL, &image);
|
||||
/* If we get a path, then check if it can be resolved with vpick. We need this as we might just
|
||||
* get a simple image name, which would make vpick error out. */
|
||||
if (path_is_absolute(name_or_path)) {
|
||||
r = path_pick(/* toplevel_path= */ NULL,
|
||||
/* toplevel_fd= */ AT_FDCWD,
|
||||
name_or_path,
|
||||
&pick_filter_image_any,
|
||||
PICK_ARCHITECTURE|PICK_TRIES|PICK_RESOLVE,
|
||||
&result);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!result.path)
|
||||
return log_debug_errno(
|
||||
SYNTHETIC_ERRNO(ENOENT),
|
||||
"No matching entry in .v/ directory %s found.",
|
||||
name_or_path);
|
||||
|
||||
name_or_path = result.path;
|
||||
}
|
||||
|
||||
r = image_find_harder(IMAGE_PORTABLE, name_or_path, /* root= */ NULL, &image);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -588,9 +610,29 @@ static int extract_image_and_extensions(
|
||||
}
|
||||
|
||||
STRV_FOREACH(p, extension_image_paths) {
|
||||
_cleanup_(pick_result_done) PickResult ext_result = PICK_RESULT_NULL;
|
||||
_cleanup_(image_unrefp) Image *new = NULL;
|
||||
const char *path = *p;
|
||||
|
||||
r = image_find_harder(IMAGE_PORTABLE, *p, NULL, &new);
|
||||
if (path_is_absolute(*p)) {
|
||||
r = path_pick(/* toplevel_path= */ NULL,
|
||||
/* toplevel_fd= */ AT_FDCWD,
|
||||
*p,
|
||||
&pick_filter_image_any,
|
||||
PICK_ARCHITECTURE|PICK_TRIES|PICK_RESOLVE,
|
||||
&ext_result);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!ext_result.path)
|
||||
return log_debug_errno(
|
||||
SYNTHETIC_ERRNO(ENOENT),
|
||||
"No matching entry in .v/ directory %s found.",
|
||||
*p);
|
||||
|
||||
path = ext_result.path;
|
||||
}
|
||||
|
||||
r = image_find_harder(IMAGE_PORTABLE, path, NULL, &new);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1691,6 +1733,7 @@ static bool marker_matches_images(const char *marker, const char *name_or_path,
|
||||
while (!isempty(marker))
|
||||
STRV_FOREACH(image_name_or_path, root_and_extensions) {
|
||||
_cleanup_free_ char *image = NULL, *base_image = NULL, *base_image_name_or_path = NULL;
|
||||
_cleanup_(pick_result_done) PickResult result = PICK_RESULT_NULL;
|
||||
|
||||
r = extract_first_word(&marker, &image, ":", EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
|
||||
if (r < 0)
|
||||
@ -1702,9 +1745,23 @@ static bool marker_matches_images(const char *marker, const char *name_or_path,
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to extract image name from %s, ignoring: %m", image);
|
||||
|
||||
r = path_extract_image_name(*image_name_or_path, &base_image_name_or_path);
|
||||
r = path_pick(/* toplevel_path= */ NULL,
|
||||
/* toplevel_fd= */ AT_FDCWD,
|
||||
*image_name_or_path,
|
||||
&pick_filter_image_any,
|
||||
PICK_ARCHITECTURE|PICK_TRIES|PICK_RESOLVE,
|
||||
&result);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to extract image name from %s, ignoring: %m", *image_name_or_path);
|
||||
return r;
|
||||
if (!result.path)
|
||||
return log_debug_errno(
|
||||
SYNTHETIC_ERRNO(ENOENT),
|
||||
"No matching entry in .v/ directory %s found.",
|
||||
*image_name_or_path);
|
||||
|
||||
r = path_extract_image_name(result.path, &base_image_name_or_path);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to extract image name from %s, ignoring: %m", result.path);
|
||||
|
||||
if (!streq(base_image, base_image_name_or_path)) {
|
||||
if (match_all)
|
||||
|
@ -183,6 +183,26 @@ status="$(portablectl is-attached --extension app1 minimal_0)"
|
||||
|
||||
portablectl detach --now --runtime --extension /usr/share/app1.raw /usr/share/minimal_0.raw app1
|
||||
|
||||
# Ensure vpick works, including reattaching to a new image
|
||||
mkdir -p /tmp/app1.v/
|
||||
cp /usr/share/app1.raw /tmp/app1.v/app1_1.0.raw
|
||||
cp /tmp/app1_2.raw /tmp/app1.v/app1_2.0.raw
|
||||
portablectl "${ARGS[@]}" attach --now --runtime --extension /tmp/app1.v/ /usr/share/minimal_1.raw app1
|
||||
|
||||
systemctl is-active app1.service
|
||||
status="$(portablectl is-attached --extension app1_2.0.raw minimal_1)"
|
||||
[[ "${status}" == "running-runtime" ]]
|
||||
|
||||
rm -f /tmp/app1.v/app1_2.0.raw
|
||||
portablectl "${ARGS[@]}" reattach --now --runtime --extension /tmp/app1.v/ /usr/share/minimal_1.raw app1
|
||||
|
||||
systemctl is-active app1.service
|
||||
status="$(portablectl is-attached --extension app1_1.0.raw minimal_1)"
|
||||
[[ "${status}" == "running-runtime" ]]
|
||||
|
||||
portablectl detach --now --runtime --extension /tmp/app1.v/ /usr/share/minimal_0.raw app1
|
||||
rm -f /tmp/app1.v/app1_1.0.raw
|
||||
|
||||
# Ensure that the combination of read-only images, state directory and dynamic user works, and that
|
||||
# state is retained. Check after detaching, as on slow systems (eg: sanitizers) it might take a while
|
||||
# after the service is attached before the file appears.
|
||||
|
Loading…
Reference in New Issue
Block a user