portable: include base and extension images in log fields

When a portable service uses extensions, we use the 'main' image name
(the one where the unit was found in) as PORTABLE=. It is useful to
also list all the images actually used at runtime, as they might
contain libraries and so on.

Use PORTABLE_ROOT= for the image/directory that is used as RootImage=
or RootDirectory=, and PORTABLE_EXTENSION= for the image/directory that
is used as ExtensionImages= or ExtensionDirectories=.

Note that these new fields are only added if extensions are used,
there's no change for single-DDI portables.

Example with a base and two extensions, with the unit coming from the
first extension:

[Service]
RootImage=/home/bluca/git/systemd/base.raw
Environment=PORTABLE=app0.raw
BindReadOnlyPaths=/etc/os-release:/run/host/os-release
LogExtraFields=PORTABLE=app0.raw
LogExtraFields=PORTABLE_ROOT=base.raw

ExtensionImages=/home/bluca/git/systemd/app0.raw
LogExtraFields=PORTABLE_EXTENSION=app0.raw

ExtensionImages=/home/bluca/git/systemd/app1.raw
LogExtraFields=PORTABLE_EXTENSION=app1.raw
This commit is contained in:
Luca Boccassi
2023-03-22 22:44:31 +00:00
parent 62b7c23f79
commit 8c8331fc50
2 changed files with 47 additions and 4 deletions

View File

@@ -335,6 +335,27 @@ service data may be placed on the host file system. Use `StateDirectory=` in
the unit files to enable such behaviour and add a local data directory to the
services copied onto the host.
## Logging
Several fields are autotmatically added to log messages generated by a portable
service (or about a portable service, e.g.: start/stop logs from systemd).
The `PORTABLE=` field will refer to the name of the portable image where the unit
was loaded from. In case extensions are used, additionally there will be a
`PORTABLE_ROOT=` field, referring to the name of image used as the base layer
(i.e.: `RootImage=` or `RootDirectory=`), and one `PORTABLE_EXTENSION=` field per
each extension image used.
For example, a portable service `app0` using two extensions `app0.raw` and
`app1.raw`, and a base layer `base.raw`, will create log entries with the
following fields:
```
PORTABLE=app0.raw
PORTABLE_ROOT=base.raw
PORTABLE_EXTENSION=app0.raw
PORTABLE_EXTENSION=app1.raw
```
## Links
[`portablectl(1)`](https://www.freedesktop.org/software/systemd/man/portablectl.html)<br>

View File

@@ -994,19 +994,41 @@ static int install_chroot_dropin(
"LogExtraFields=PORTABLE=", base_name, "\n"))
return -ENOMEM;
if (!ordered_hashmap_isempty(extension_images)) {
_cleanup_free_ char *root_base_name = NULL;
r = path_extract_filename(image_path, &root_base_name);
if (r < 0)
return log_debug_errno(r, "Failed to extract basename from '%s': %m", image_path);
if (!strextend(&text, "LogExtraFields=PORTABLE_ROOT=", root_base_name, "\n"))
return -ENOMEM;
}
if (m->image_path && !path_equal(m->image_path, image_path))
ORDERED_HASHMAP_FOREACH(ext, extension_images)
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)
return log_debug_errno(r, "Failed to extract basename from '%s': %m", ext->path);
if (!strextend(&text,
"\n",
extension_setting_from_image(ext->type),
ext->path,
/* With --force tell PID1 to avoid enforcing that the image <name> and
* extension-release.<name> have to match. */
!IN_SET(type, IMAGE_DIRECTORY, IMAGE_SUBVOLUME) &&
FLAGS_SET(flags, PORTABLE_FORCE_SYSEXT) ?
":x-systemd.relax-extension-release-check" :
"",
"\n"))
":x-systemd.relax-extension-release-check\n" :
"\n",
/* In PORTABLE= we list the 'main' image name for this unit
* (the image where the unit was extracted from), but we are
* stacking multiple images, so list those too. */
"LogExtraFields=PORTABLE_EXTENSION=", extension_base_name, "\n"))
return -ENOMEM;
}
}
r = write_string_file(dropin, text, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);