[OE-core] [OE-Core][PATCH] systemd: Default to non-stateless images

Jonas Bonn jonas at norrbonn.se
Mon May 6 04:54:26 UTC 2019


Hi Alex,

The below is fine and looks good.  The one thing that bothers me about 
this is that "stateless" isn't really a property of the "distro", rather 
it's a property of the image/machine.  I suspect, in the same sense that 
we have readonly-rootfs, that we should probably have image features 
"stateless-rootfs" (no /etc, no /var) and "volatile-rootfs" (no /var).

Furthermore, if you want to boot with 'ro' on the command-line, I really 
think you need to build your image with the "readonly-rootfs" feature 
set.  The default should be writable+persistent /etc as that's the 
configuration used 99% of the time (currently).  "readonly-rootfs" does 
a bit more than just creating machine-id but it's all relevant to the 
'ro' case where /etc isn't writable.

Just for clarification:

i)  volatile-rootfs:  means there's no point in prepopulating /var 
because it's on a tmpfs and needs to be populated at boot time

ii)  stateless-rootfs:  means there's no point in prepopulating neither 
/etc nor /var because they are on a tmpfs and need to be populated at 
boot time

iii)  readonly-rootfs:  means that /etc is really not writable so it's 
important that: the systemd first-boot stuff needs to be done at build 
time:  machine-id, unit files set up, all tmpfiles.d snippets that touch 
/etc and /var need to be done in advance.

/Jonas


On 03/05/2019 18:48, Alex Kiernan wrote:
> When creating images, for anything other than the explicitly stateless
> case, touch /etc/machine-id so that the images can be booted without an
> initramfs and with `ro` set on the kernel command line, otherwise system
> refuses to start:
> 
>    [    7.222134] systemd[1]: No hostname configured.
>    [    7.227266] systemd[1]: Set hostname to <localhost>.
>    [    7.232622] systemd[1]: System cannot boot: Missing /etc/machine-id and /etc is mounted read-only.
>    [    7.241750] systemd[1]: Booting up is supported only when:
>    [    7.247362] systemd[1]: 1) /etc/machine-id exists and is populated.
>    [    7.253752] systemd[1]: 2) /etc/machine-id exists and is empty.
>    [    7.259757] systemd[1]: 3) /etc/machine-id is missing and /etc is writable.
> 
> If DISTRO_FEATURES includes `stateless` then systemctl-native is not run
> on the image leaving the image for population at runtime by systemd.
> 
> Signed-off-by: Alex Kiernan <alex.kiernan at gmail.com>
> ---
> 
>   meta/classes/image.bbclass                            | 7 +++----
>   meta/recipes-core/systemd/systemd-systemctl/systemctl | 8 ++++++++
>   2 files changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/meta/classes/image.bbclass b/meta/classes/image.bbclass
> index a23403c0827a..3cb185dd2045 100644
> --- a/meta/classes/image.bbclass
> +++ b/meta/classes/image.bbclass
> @@ -665,12 +665,11 @@ reproducible_final_image_task () {
>       fi
>   }
>   
> -IMAGE_EXTRADEPENDS += "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd-systemctl-native', '', d)}"
> -
>   systemd_preset_all () {
> -	systemctl --root="${IMAGE_ROOTFS}" --preset-mode=enable-only preset-all
> +    systemctl --root="${IMAGE_ROOTFS}" --preset-mode=enable-only preset-all
>   }
>   
> -IMAGE_PREPROCESS_COMMAND_append = " ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd_preset_all;', '', d)} reproducible_final_image_task; "
> +IMAGE_EXTRADEPENDS += "${@ 'systemd-systemctl-native' if bb.utils.contains('DISTRO_FEATURES', 'systemd', True, False, d) and not bb.utils.contains('DISTRO_FEATURES', 'stateless', True, False, d) else ''}"
> +IMAGE_PREPROCESS_COMMAND_append = " ${@ 'systemd_preset_all;' if bb.utils.contains('DISTRO_FEATURES', 'systemd', True, False, d) and not bb.utils.contains('DISTRO_FEATURES', 'stateless', True, False, d) else ''} reproducible_final_image_task; "
>   
>   CVE_PRODUCT = ""
> diff --git a/meta/recipes-core/systemd/systemd-systemctl/systemctl b/meta/recipes-core/systemd/systemd-systemctl/systemctl
> index d7d4e0d29a09..7da8f23ab893 100755
> --- a/meta/recipes-core/systemd/systemd-systemctl/systemctl
> +++ b/meta/recipes-core/systemd/systemd-systemctl/systemctl
> @@ -241,6 +241,14 @@ def preset_all(root):
>           if state == "enable" or state is None:
>               enable(root, service, location, services)
>   
> +    # If we populate the systemd links we also create /etc/machine-id, which
> +    # allows systemd to boot with the filesystem read-only before generating
> +    # a real value and then committing it back.
> +    #
> +    # For the stateless configuration, where /etc is generated at runtime
> +    # (for example on a tmpfs), this script shouldn't run at all and we
> +    # allow systemd to completely populate /etc.
> +    (root / SYSCONFDIR / "machine-id").touch()
>   
>   def mask(root, *services):
>       systemdir = root / SYSCONFDIR / "systemd" / "system"
> 


More information about the Openembedded-core mailing list