portable: log structured message when attach/detach succeeds

Currently portabled is completely silent (when not using debug level). But
when the system state is changed (ie: a portable is attached or detached)
there are no traces left in the journal. Log at info level when either of
those operations succeed, as they are effectively changing the state of
the system.

Create new MESSAGE_IDs for these logs, and also append PORTABLE_ROOT=
(and PORTABLE_EXTENSION= if any), like the units themselves are
configured to do via LogExtraFields=, so that the same metadata can
be found in the attach/detach messages and in logs from the units
themselves.
This commit is contained in:
Luca Boccassi 2024-01-18 19:32:47 +00:00 committed by Lennart Poettering
parent c03a321ef6
commit a0cca4d1b0
3 changed files with 115 additions and 0 deletions

View file

@ -748,3 +748,23 @@ Compatibility support for System V services in systemd is deprecated. Please
make sure to update the package in question to provide proper, native systemd
unit files. Contact vendor if necessary. Compatibility support for System V
services is deprecated and will be removed soon.
-- 187c62eb1e7f463bb530394f52cb090f
Subject: A Portable Service has been attached
Defined-By: systemd
Support: %SUPPORT_URL%
Documentation: https://systemd.io/PORTABLE_SERVICES/
A new Portable Service @PORTABLE_ROOT@ (with extensions: @PORTABLE_EXTENSION@) has
been attached to the system and is now available for use. The list of attached
Portable Services can be queried with 'portablectl list'.
-- 76c5c754d628490d8ecba4c9d042112b
Subject: A Portable Service has been detached
Defined-By: systemd
Support: %SUPPORT_URL%
Documentation: https://systemd.io/PORTABLE_SERVICES/
A Portable Service @PORTABLE_ROOT@ (with extensions: @PORTABLE_EXTENSION@) has been
detached from the system and is no longer available for use. The list of attached
Portable Services can be queried with 'portablectl list'.

View file

@ -2,6 +2,8 @@
#include <linux/loop.h>
#include "sd-messages.h"
#include "bus-common-errors.h"
#include "bus-error.h"
#include "bus-locator.h"
@ -1430,6 +1432,78 @@ static bool prefix_matches_compatible(char **matches, char **valid_prefixes) {
return true;
}
static void log_portable_verb(
const char *verb,
const char *message_id,
const char *image_path,
OrderedHashmap *extension_images,
char **extension_image_paths,
PortableFlags flags) {
_cleanup_free_ char *root_base_name = NULL, *extensions_joined = NULL;
_cleanup_strv_free_ char **extension_base_names = NULL;
Image *ext;
int r;
assert(verb);
assert(message_id);
assert(image_path);
assert(!extension_images || !extension_image_paths);
/* Use the same structured metadata as it is attached to units via LogExtraFields=. The main image
* is logged as PORTABLE_ROOT= and extensions, if any, as individual PORTABLE_EXTENSION= fields. */
r = path_extract_filename(image_path, &root_base_name);
if (r < 0)
log_debug_errno(r, "Failed to extract basename from '%s', ignoring: %m", image_path);
ORDERED_HASHMAP_FOREACH(ext, extension_images) {
_cleanup_free_ char *extension_base_name = NULL;
r = path_extract_filename(ext->path, &extension_base_name);
if (r < 0) {
log_debug_errno(r, "Failed to extract basename from '%s', ignoring: %m", ext->path);
continue;
}
r = strv_extendf(&extension_base_names, "PORTABLE_EXTENSION=%s", extension_base_name);
if (r < 0)
log_oom_debug();
if (!strextend_with_separator(&extensions_joined, ", ", ext->path))
log_oom_debug();
}
STRV_FOREACH(e, extension_image_paths) {
_cleanup_free_ char *extension_base_name = NULL;
r = path_extract_filename(*e, &extension_base_name);
if (r < 0) {
log_debug_errno(r, "Failed to extract basename from '%s', ignoring: %m", *e);
continue;
}
r = strv_extendf(&extension_base_names, "PORTABLE_EXTENSION=%s", extension_base_name);
if (r < 0)
log_oom_debug();
if (!strextend_with_separator(&extensions_joined, ", ", *e))
log_oom_debug();
}
LOG_CONTEXT_PUSH_STRV(extension_base_names);
log_struct(LOG_INFO,
LOG_MESSAGE("Successfully %s%s '%s%s%s'",
verb,
FLAGS_SET(flags, PORTABLE_RUNTIME) ? " ephemeral" : "",
image_path,
isempty(extensions_joined) ? "" : "' and its extension(s) '",
strempty(extensions_joined)),
message_id,
"PORTABLE_ROOT=%s", strna(root_base_name));
}
int portable_attach(
sd_bus *bus,
const char *name_or_path,
@ -1538,6 +1612,14 @@ int portable_attach(
* operation otherwise. */
(void) install_image_and_extensions_symlinks(image, extension_images, flags, changes, n_changes);
log_portable_verb(
"attached",
"MESSAGE_ID=" SD_MESSAGE_PORTABLE_ATTACHED_STR,
image->path,
extension_images,
/* extension_image_paths= */ NULL,
flags);
return 0;
}
@ -1861,6 +1943,14 @@ int portable_detach(
if (rmdir(where) >= 0)
portable_changes_add(changes, n_changes, PORTABLE_UNLINK, where, NULL);
log_portable_verb(
"detached",
"MESSAGE_ID=" SD_MESSAGE_PORTABLE_DETACHED_STR,
name_or_path,
/* extension_images= */ NULL,
extension_image_paths,
flags);
return ret;
not_found:

View file

@ -267,6 +267,11 @@ _SD_BEGIN_DECLARATIONS;
#define SD_MESSAGE_SYSV_GENERATOR_DEPRECATED SD_ID128_MAKE(a8,fa,8d,ac,db,1d,44,3e,95,03,b8,be,36,7a,6a,db)
#define SD_MESSAGE_SYSV_GENERATOR_DEPRECATED_STR SD_ID128_MAKE_STR(a8,fa,8d,ac,db,1d,44,3e,95,03,b8,be,36,7a,6a,db)
#define SD_MESSAGE_PORTABLE_ATTACHED SD_ID128_MAKE(18,7c,62,eb,1e,7f,46,3b,b5,30,39,4f,52,cb,09,0f)
#define SD_MESSAGE_PORTABLE_ATTACHED_STR SD_ID128_MAKE_STR(18,7c,62,eb,1e,7f,46,3b,b5,30,39,4f,52,cb,09,0f)
#define SD_MESSAGE_PORTABLE_DETACHED SD_ID128_MAKE(76,c5,c7,54,d6,28,49,0d,8e,cb,a4,c9,d0,42,11,2b)
#define SD_MESSAGE_PORTABLE_DETACHED_STR SD_ID128_MAKE_STR(76,c5,c7,54,d6,28,49,0d,8e,cb,a4,c9,d0,42,11,2b)
_SD_END_DECLARATIONS;
#endif