From: Lennart Poettering Date: Mon, 10 Feb 2025 10:57:19 +0000 (+0100) Subject: import-generator: optionally import images into /run/ hierarchy rather than /var/ X-Git-Tag: v258-rc1~1280^2~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8b918a3a38c3ed5cf3acbc8c41e4cd0ed97f5b38;p=thirdparty%2Fsystemd.git import-generator: optionally import images into /run/ hierarchy rather than /var/ This is useful in particular in the initrd, as this ensures any downloaded images are not deleted during the initrd→host transition (where /var/ does not survive, but /run/ does). Might be useful in other cases too, for example for transiently deployed confexts and such. --- diff --git a/man/systemd-import-generator.xml b/man/systemd-import-generator.xml index d60c9c96fed..cea015e6f8a 100644 --- a/man/systemd-import-generator.xml +++ b/man/systemd-import-generator.xml @@ -144,6 +144,17 @@ + + + runtime= + + Takes a boolean argument. If set to true, the image is downloaded below the + /run/ hierarchy, if set to false below the /var/lib/ + hierarchy. If not specified defaults to true in the initial RAM disk (initrd) and to false on the + host system. + + + diff --git a/src/import/import-generator.c b/src/import/import-generator.c index 5d2f37107e8..d63ed23a7b9 100644 --- a/src/import/import-generator.c +++ b/src/import/import-generator.c @@ -11,6 +11,7 @@ #include "import-util.h" #include "initrd-util.h" #include "json-util.h" +#include "parse-util.h" #include "proc-cmdline.h" #include "special.h" #include "specifier.h" @@ -22,6 +23,7 @@ typedef struct Transfer { ImportType type; char *local; char *remote; + const char *image_root; bool blockdev; sd_json_variant *json; } Transfer; @@ -78,7 +80,7 @@ static int parse_pull_expression(const char *v) { ImportType type = _IMPORT_TYPE_INVALID; ImageClass class = _IMAGE_CLASS_INVALID; ImportVerify verify = IMPORT_VERIFY_SIGNATURE; - bool ro = false, blockdev = false, bootorigin = false; + bool ro = false, blockdev = false, bootorigin = false, runtime = in_initrd(); const char *o = options; for (;;) { @@ -100,7 +102,13 @@ static int parse_pull_expression(const char *v) { blockdev = true; else if (streq(opt, "bootorigin")) bootorigin = true; - else if ((suffix = startswith(opt, "verify="))) { + else if ((suffix = startswith(opt, "runtime="))) { + r = parse_boolean(suffix); + if (r < 0) + log_warning_errno(r, "Unknown runtime= parameter, ignoring: %s", suffix); + else + runtime = r; + } else if ((suffix = startswith(opt, "verify="))) { ImportVerify w = import_verify_from_string(suffix); if (w < 0) @@ -187,8 +195,9 @@ static int parse_pull_expression(const char *v) { if (!GREEDY_REALLOC(arg_transfers, arg_n_transfers + 1)) return log_oom(); - _cleanup_(sd_json_variant_unrefp) sd_json_variant *j = NULL; + const char *image_root = runtime ? image_root_runtime_to_string(class) : image_root_to_string(class); + _cleanup_(sd_json_variant_unrefp) sd_json_variant *j = NULL; r = sd_json_buildo( &j, SD_JSON_BUILD_PAIR("remote", SD_JSON_BUILD_STRING(remote)), @@ -196,7 +205,8 @@ static int parse_pull_expression(const char *v) { SD_JSON_BUILD_PAIR("class", JSON_BUILD_STRING_UNDERSCORIFY(image_class_to_string(class))), SD_JSON_BUILD_PAIR("type", JSON_BUILD_STRING_UNDERSCORIFY(import_type_to_string(type))), SD_JSON_BUILD_PAIR("readOnly", SD_JSON_BUILD_BOOLEAN(ro)), - SD_JSON_BUILD_PAIR("verify", JSON_BUILD_STRING_UNDERSCORIFY(import_verify_to_string(verify)))); + SD_JSON_BUILD_PAIR("verify", JSON_BUILD_STRING_UNDERSCORIFY(import_verify_to_string(verify))), + SD_JSON_BUILD_PAIR("imageRoot", SD_JSON_BUILD_STRING(image_root))); if (r < 0) return log_error_errno(r, "Failed to build import JSON object: %m"); @@ -205,6 +215,7 @@ static int parse_pull_expression(const char *v) { .type = type, .local = TAKE_PTR(local), .remote = TAKE_PTR(remote), + .image_root = image_root, .json = TAKE_PTR(j), .blockdev = blockdev, }; @@ -322,11 +333,11 @@ static int transfer_generate(const Transfer *t, size_t c) { fputs("Wants=network-online.target\n" "After=network-online.target\n", f); - _cleanup_free_ char *local_path = NULL, *loop_service = NULL; + _cleanup_free_ char *loop_service = NULL; if (t->blockdev) { assert(t->type == IMPORT_RAW); - local_path = strjoin(image_root_to_string(t->class), "/", t->local, ".raw"); + _cleanup_free_ char *local_path = strjoin(t->image_root, "/", t->local, ".raw"); if (!local_path) return log_oom(); diff --git a/src/import/importd.c b/src/import/importd.c index 324bb618a45..5a1dcb92a5d 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -1862,7 +1862,7 @@ static int vl_method_pull(sd_varlink *link, sd_json_variant *parameters, sd_varl { "force", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(struct p, force), 0 }, { "readOnly", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(struct p, read_only), 0 }, { "keepDownload", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(struct p, keep_download), 0 }, - { "imageRoot", SD_JSON_VARIANT_BOOLEAN, json_dispatch_const_path, offsetof(struct p, image_root), SD_JSON_STRICT }, + { "imageRoot", SD_JSON_VARIANT_STRING, json_dispatch_const_path, offsetof(struct p, image_root), SD_JSON_STRICT }, VARLINK_DISPATCH_POLKIT_FIELD, {}, }; diff --git a/src/shared/discover-image.c b/src/shared/discover-image.c index e2f05dca93d..d6afa53a6bf 100644 --- a/src/shared/discover-image.c +++ b/src/shared/discover-image.c @@ -110,6 +110,15 @@ static const char *const image_root_table[_IMAGE_CLASS_MAX] = { DEFINE_STRING_TABLE_LOOKUP_TO_STRING(image_root, ImageClass); +static const char *const image_root_runtime_table[_IMAGE_CLASS_MAX] = { + [IMAGE_MACHINE] = "/run/machines", + [IMAGE_PORTABLE] = "/run/portables", + [IMAGE_SYSEXT] = "/run/extensions", + [IMAGE_CONFEXT] = "/run/confexts", +}; + +DEFINE_STRING_TABLE_LOOKUP_TO_STRING(image_root_runtime, ImageClass); + static Image *image_free(Image *i) { assert(i); diff --git a/src/shared/discover-image.h b/src/shared/discover-image.h index c64d0baefb5..66dc7ef3d28 100644 --- a/src/shared/discover-image.h +++ b/src/shared/discover-image.h @@ -122,6 +122,7 @@ static inline bool IMAGE_IS_HOST(const struct Image *i) { int image_to_json(const struct Image *i, sd_json_variant **ret); const char* image_root_to_string(ImageClass c) _const_; +const char* image_root_runtime_to_string(ImageClass c) _const_; extern const struct hash_ops image_hash_ops;