LUO: only deserialize on boot, add version and structure to JSON payload (#42607)
This commit is contained in:
+47
-8
@@ -53,7 +53,7 @@ int manager_luo_restore_fd_stores(Manager *m) {
|
||||
_cleanup_close_ int device_fd = -EBADF;
|
||||
_cleanup_(luo_session_finishp) int session_fd = -EBADF;
|
||||
const char *unit_id;
|
||||
sd_json_variant *fds_json;
|
||||
sd_json_variant *unit_json;
|
||||
int r, n_total = 0;
|
||||
|
||||
assert(m);
|
||||
@@ -83,18 +83,39 @@ int manager_luo_restore_fd_stores(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
struct {
|
||||
uint64_t version;
|
||||
sd_json_variant *units;
|
||||
} q = {};
|
||||
|
||||
static const sd_json_dispatch_field mapping_dispatch_table[] = {
|
||||
{ "version", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, voffsetof(q, version), SD_JSON_MANDATORY },
|
||||
{ "units", SD_JSON_VARIANT_OBJECT, sd_json_dispatch_variant_noref, voffsetof(q, units), 0 },
|
||||
{}
|
||||
};
|
||||
|
||||
r = sd_json_dispatch(mapping, mapping_dispatch_table, SD_JSON_ALLOW_EXTENSIONS|SD_JSON_LOG, &q);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (q.version > LUO_PROTOCOL_VERSION) {
|
||||
log_warning("LUO mapping has unsupported version %" PRIu64 ", skipping state restoration.", q.version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Retrieve all fds from the session and dispatch each to the named unit, eagerly loading the
|
||||
* unit if necessary. */
|
||||
JSON_VARIANT_OBJECT_FOREACH(unit_id, fds_json, mapping) {
|
||||
sd_json_variant *entry;
|
||||
JSON_VARIANT_OBJECT_FOREACH(unit_id, unit_json, q.units) {
|
||||
sd_json_variant *entry, *fds_json;
|
||||
|
||||
if (!unit_name_is_valid(unit_id, UNIT_NAME_ANY)) {
|
||||
log_warning("Invalid unit name '%s' in LUO mapping, skipping.", unit_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
fds_json = sd_json_variant_by_key(unit_json, "fdstore");
|
||||
if (!sd_json_variant_is_array(fds_json)) {
|
||||
log_warning("LUO mapping for unit '%s' is not a JSON array, skipping.", unit_id);
|
||||
log_warning("LUO mapping fdstore for unit '%s' is not a JSON array, skipping.", unit_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -172,7 +193,7 @@ int manager_luo_restore_fd_stores(Manager *m) {
|
||||
}
|
||||
|
||||
int manager_luo_serialize_fd_stores(Manager *m, FILE **ret_f, FDSet **ret_fds) {
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *root = NULL;
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *root = NULL, *units = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_fdset_free_ FDSet *fds = NULL;
|
||||
Unit *u;
|
||||
@@ -192,8 +213,9 @@ int manager_luo_serialize_fd_stores(Manager *m, FILE **ret_f, FDSet **ret_fds) {
|
||||
if (!fds)
|
||||
return log_oom();
|
||||
|
||||
/* Build a JSON object: { "unit_id": [ { "type": "fd", "name": "...", "fd": N },
|
||||
* { "type": "luo_session", "name": "...", "fd": N, "sessionName": "..." } ], ... }
|
||||
/* Build a JSON object: { "version": 1,
|
||||
* "units": { "unit_id": { "fdstore": [ { "type": "fd", "name": "...", "fd": N },
|
||||
* { "type": "luo_session", "name": "...", "fd": N, "sessionName": "..." } ] }, ... } }
|
||||
* This is passed to systemd-shutdown which will create a LUO session and preserve the fds. */
|
||||
HASHMAP_FOREACH(u, m->units) {
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *entries = NULL;
|
||||
@@ -247,7 +269,17 @@ int manager_luo_serialize_fd_stores(Manager *m, FILE **ret_f, FDSet **ret_fds) {
|
||||
n_serialized++;
|
||||
}
|
||||
|
||||
r = sd_json_variant_set_field(&root, u->id, entries);
|
||||
if (!entries)
|
||||
continue;
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *unit_json = NULL;
|
||||
r = sd_json_buildo(
|
||||
&unit_json,
|
||||
SD_JSON_BUILD_PAIR_VARIANT("fdstore", entries));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to build LUO unit object: %m");
|
||||
|
||||
r = sd_json_variant_set_field(&units, u->id, unit_json);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add unit to LUO serialization JSON: %m");
|
||||
}
|
||||
@@ -259,6 +291,13 @@ int manager_luo_serialize_fd_stores(Manager *m, FILE **ret_f, FDSet **ret_fds) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_json_buildo(
|
||||
&root,
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("version", LUO_PROTOCOL_VERSION),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(!!units, "units", SD_JSON_BUILD_VARIANT(units)));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to build LUO serialization JSON: %m");
|
||||
|
||||
r = open_serialization_file("luo-fd-store", &f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create LUO serialization file: %m");
|
||||
|
||||
+4
-2
@@ -2194,8 +2194,10 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds, Hashmap *named_
|
||||
m->soft_reboots_count++;
|
||||
|
||||
/* If a LUO (Live Update Orchestrator) session from a previous kexec is available, restore
|
||||
* preserved file descriptors into the appropriate service fd stores now, before coldplug. */
|
||||
(void) manager_luo_restore_fd_stores(m);
|
||||
* preserved file descriptors into the appropriate service fd stores now, before coldplug.
|
||||
* Only do this when booting up (i.e., skip on reexec/soft reboot/etc.) */
|
||||
if (m->previous_objective < 0)
|
||||
(void) manager_luo_restore_fd_stores(m);
|
||||
|
||||
/* Pick up fds passed via the LISTEN_FDS=/LISTEN_FDNAMES= protocol that are tagged with a
|
||||
* unit id ("unit-id|fdname"), and route them into the matching unit's fd store. Untagged
|
||||
|
||||
Reference in New Issue
Block a user