From 2da298408ead1a535bcd615773f683d160c54285 Mon Sep 17 00:00:00 2001 From: Francisco Gil Date: Tue, 10 Mar 2026 11:37:19 +0100 Subject: [PATCH] dey-image-container: add final artifact bundle generation Add the artifact packaging stage that assembles deployable LXC/Podman bundles with a normalized layout (manifest, payload, checksums, metadata). The task also computes digests/metadata and removes intermediate build outputs once final artifacts are produced. https://onedigi.atlassian.net/browse/DEL-10004 Signed-off-by: Francisco Gil Signed-off-by: Isaac Hermida --- meta-digi-containers/README.md | 236 ++++++++++++++++++ .../custom/artifact/metadata/README.txt | 1 + .../custom/artifact/metadata/changelog.txt | 1 + .../custom/configs_lxc/config_lxc_ccimx95-dvk | 17 ++ .../custom/configs_lxc/config_lxc_ccmp25-dvk | 17 ++ .../containers/custom/rootfs_files/.keep | 0 .../lvgl/artifact/metadata/README.txt | 1 + .../lvgl/artifact/metadata/changelog.txt | 1 + .../lvgl/configs_lxc/config_lxc_ccimx95-dvk | 30 +++ .../lvgl/configs_lxc/config_lxc_ccmp25-dvk | 30 +++ .../containers/lvgl/rootfs_files/.keep | 0 .../lvgl/rootfs_files/start-lvgl-demo.sh | 26 ++ .../webkit/artifact/metadata/README.txt | 1 + .../webkit/artifact/metadata/changelog.txt | 1 + .../webkit/configs_lxc/config_lxc_ccimx95-dvk | 55 ++++ .../webkit/configs_lxc/config_lxc_ccmp25-dvk | 53 ++++ .../webkit/rootfs_files/start-webkit-demo.sh | 36 +++ .../images/dey-image-container-artifact.inc | 153 ++++++++++++ .../images/dey-image-container-lxc.inc | 2 +- .../images/dey-image-container.bb | 33 ++- 20 files changed, 691 insertions(+), 3 deletions(-) create mode 100644 meta-digi-containers/README.md create mode 100644 meta-digi-containers/containers/custom/artifact/metadata/README.txt create mode 100644 meta-digi-containers/containers/custom/artifact/metadata/changelog.txt create mode 100644 meta-digi-containers/containers/custom/configs_lxc/config_lxc_ccimx95-dvk create mode 100644 meta-digi-containers/containers/custom/configs_lxc/config_lxc_ccmp25-dvk create mode 100644 meta-digi-containers/containers/custom/rootfs_files/.keep create mode 100644 meta-digi-containers/containers/lvgl/artifact/metadata/README.txt create mode 100644 meta-digi-containers/containers/lvgl/artifact/metadata/changelog.txt create mode 100644 meta-digi-containers/containers/lvgl/configs_lxc/config_lxc_ccimx95-dvk create mode 100644 meta-digi-containers/containers/lvgl/configs_lxc/config_lxc_ccmp25-dvk create mode 100644 meta-digi-containers/containers/lvgl/rootfs_files/.keep create mode 100644 meta-digi-containers/containers/lvgl/rootfs_files/start-lvgl-demo.sh create mode 100644 meta-digi-containers/containers/webkit/artifact/metadata/README.txt create mode 100644 meta-digi-containers/containers/webkit/artifact/metadata/changelog.txt create mode 100644 meta-digi-containers/containers/webkit/configs_lxc/config_lxc_ccimx95-dvk create mode 100644 meta-digi-containers/containers/webkit/configs_lxc/config_lxc_ccmp25-dvk create mode 100644 meta-digi-containers/containers/webkit/rootfs_files/start-webkit-demo.sh create mode 100644 meta-digi-containers/recipes-core/images/dey-image-container-artifact.inc diff --git a/meta-digi-containers/README.md b/meta-digi-containers/README.md new file mode 100644 index 000000000..18ef0ae2d --- /dev/null +++ b/meta-digi-containers/README.md @@ -0,0 +1,236 @@ +# meta-digi-containers + +Yocto layer for Digi container-focused image generation and packaging. + +This layer provides the `dey-image-container` image recipe and related logic to produce: + +- A base rootfs (`tar.xz`) +- An OCI image output +- A Podman archive (`*.tar`) +- An LXC bundle (`*.tar.xz`) +- Final container artifacts (`*.tar.gz`) with: + - `manifest.json` + - `payload/` + - `checksums/sha256sums.txt` + - optional `metadata/` + +Note: Podman archive generation requires an OCI image output as intermediate input. +The recipe keeps `oci` in `IMAGE_FSTYPES` because `do_image_podman_archive` converts +that OCI artifact into a `docker-archive` tar using `skopeo`. + +## Layer Scope + +Main recipe: + +- `recipes-core/images/dey-image-container.bb` + +Recipe includes: + +- `dey-image-container-fragments.inc` +- `dey-image-container-lxc.inc` +- `dey-image-container-podman.inc` +- `dey-image-container-artifact.inc` + +Container support files: + +- `containers//configs_lxc/` (profile LXC config fragments) +- `containers//rootfs_files/` (profile rootfs overlays) +- `containers//artifact/` (optional artifact metadata template) + +## Add The Layer + +In your build environment: + +```bash +bitbake-layers add-layer /path/to/sources/meta-digi/meta-digi-containers +bitbake-layers add-layer /path/to/sources/meta-virtualization +bitbake-layers add-layer /path/to/sources/meta-openembedded/meta-filesystems +``` + +Or add it manually to `conf/bblayers.conf`. + +## Basic Usage + +Set profile and naming in `conf/local.conf`: + +```conf +DISTRO_FEATURES:append = " virtualization" +CONTAINER_TYPE = "webkit" # or: lvgl, base, custom profile +CONTAINER_NAME = "webkit-example" +# PODMAN_TAG defaults to "${CONTAINER_NAME}-tag" +``` + +Build: + +```bash +bitbake dey-image-container +``` + +Outputs are generated in: + +- `tmp/deploy/images/${MACHINE}/` + +Final outputs: + +- `${CONTAINER_NAME}_artifact_podman_${MACHINE}.tar.gz` +- `${CONTAINER_NAME}_artifact_lxc_${MACHINE}.tar.gz` + +Intermediate outputs generated during the build (LXC bundle, Podman archive, OCI/rootfs files) +are removed automatically at the end of artifact creation. + +## Profiles + +Profile-specific behavior is controlled with: + +- `CONTAINER_TYPE` +- `OVERRIDES:append = ":container-${CONTAINER_TYPE}"` (handled in recipe) + +Current built-in profile examples: + +- `container-lvgl` +- `container-webkit` + +You can add new profiles by appending variables with `:container-` overrides. + +For customer-defined profiles, use: + +```conf +CONTAINER_TYPE = "myprofile" +CONTAINER_NAME = "myprofile-demo" +PODMAN_TAG = "myprofile-demo-tag" + +IMAGE_INSTALL:append:container-myprofile = " package-a package-b" +CONTAINER_INIT_MANAGER:container-myprofile = "/usr/bin/docker-init" +CONTAINER_INIT_SCRIPT:container-myprofile = "/usr/bin/my-app --foreground" + +# Manifest-related overrides can also be profile-specific: +CONTAINER_ARTIFACT_VERSION:container-myprofile = "1.2.0" +CONTAINER_FIRMWARE_VERSIONS:container-myprofile = ">=25.01" +CONTAINER_DEVICE_TYPES_JSON:container-myprofile = "[\"ccmp25-dvk\"]" +CONTAINER_ARTIFACT_DESCRIPTION:container-myprofile = "My profile demo container" +CONTAINER_ARTIFACT_LABELS_JSON:container-myprofile = "{\"vendor\":\"digi\",\"component\":\"demo\"}" + +``` + +## Rootfs Overlay + +Use the following variables to inject directories into the container rootfs: + +```conf +CONTAINER_ROOTFS_OVERLAY_DIRS = "/absolute/path/to/overlay" +CONTAINER_ROOTFS_OVERLAY_TARBALLS = "/absolute/path/to/overlay.tar.gz" +``` + +Notes: + +- Multiple entries are supported (space-separated). +- `*.sh` files copied from overlay directories are marked executable automatically. +- If `CONTAINER_ROOTFS_OVERLAY_DIRS` is not set + and `containers/${CONTAINER_TYPE}/rootfs_files` exists, + it is used automatically. + +## LXC Fragment Configuration + +LXC fragments are loaded from: + +- `containers/${CONTAINER_TYPE}/configs_lxc/` + +Config file naming: + +- `config_lxc_` + +Example: + +- `config_lxc_ccmp25-dvk` + +`` matches the full `MACHINE` value. + +Supported placeholders in LXC config fragments: + +- `@LXC_ARCH@` +- `@LXC_FOLDER@` +- `@CONTAINER_NAME@` +- `@CONTAINER_INIT_MANAGER@` +- `@CONTAINER_INIT_SCRIPT@` + +## Artifact Manifest Fields + +The artifact manifest is generated automatically and includes: + +- `package_id` +- `version` +- `runtime` +- `artifact_type` +- `create_args` [optional] for Podman artifacts (only when non-empty) +- `created_at` +- `digest` +- `device_types` +- `firmware_versions` +- `size_bytes` +- `build_id` +- `description` +- `labels` + +`build_id` behavior: + +- Uses `CONTAINER_ARTIFACT_BUILD_ID` if explicitly set. +- Otherwise uses the current `meta-digi` git commit SHA (`git rev-parse HEAD`). + +Relevant variables: + +- `CONTAINER_PACKAGE_ID` +- `CONTAINER_ARTIFACT_VERSION` +- `CONTAINER_CREATE_ARGS_PODMAN` +- `CONTAINER_FIRMWARE_VERSIONS` +- `CONTAINER_DEVICE_TYPES_JSON` +- `CONTAINER_ARTIFACT_DESCRIPTION` +- `CONTAINER_ARTIFACT_BUILD_ID` +- `CONTAINER_ARTIFACT_LABELS_JSON` + +## Optional Artifact Metadata Template + +If you set: + +```conf +CONTAINER_ARTIFACT_TEMPLATE_DIR = "/path/to/artifact-template" +``` + +and the template contains `metadata/`, it is copied into final artifact bundles. + +`manifest.json`, `payload/*`, and `checksums/sha256sums.txt` are always generated during +build time and should not be pre-created in the template. + +If `CONTAINER_ARTIFACT_TEMPLATE_DIR` is not set and `containers/${CONTAINER_TYPE}/artifact` exists, +it is used automatically. + +## Container Folder Layout + +Each profile is self-contained under `containers/`: + +```text +containers/ + lvgl/ + rootfs_files/ + configs_lxc/ + artifact/ + webkit/ + rootfs_files/ + configs_lxc/ + artifact/ + custom/ + rootfs_files/ + configs_lxc/ + artifact/ +``` + +To create a new profile: + +1. Create `containers//configs_lxc/config_lxc_`. +2. Optionally add `containers//rootfs_files/` for rootfs content. +3. Set `CONTAINER_TYPE = ""` in `local.conf`. +4. Add profile packages with `IMAGE_INSTALL:append:container- = " ... "`. + +## Notes + +- Intermediate container artifacts from the current build are removed at the end of the artifact task. +- If `dey-image-container` is not found, verify the layer is present in `BBLAYERS`. diff --git a/meta-digi-containers/containers/custom/artifact/metadata/README.txt b/meta-digi-containers/containers/custom/artifact/metadata/README.txt new file mode 100644 index 000000000..fe3b4711a --- /dev/null +++ b/meta-digi-containers/containers/custom/artifact/metadata/README.txt @@ -0,0 +1 @@ +Placeholder metadata for custom container artifacts. diff --git a/meta-digi-containers/containers/custom/artifact/metadata/changelog.txt b/meta-digi-containers/containers/custom/artifact/metadata/changelog.txt new file mode 100644 index 000000000..8ddbf0080 --- /dev/null +++ b/meta-digi-containers/containers/custom/artifact/metadata/changelog.txt @@ -0,0 +1 @@ +Placeholder changelog for custom container artifacts. diff --git a/meta-digi-containers/containers/custom/configs_lxc/config_lxc_ccimx95-dvk b/meta-digi-containers/containers/custom/configs_lxc/config_lxc_ccimx95-dvk new file mode 100644 index 000000000..b526c0df3 --- /dev/null +++ b/meta-digi-containers/containers/custom/configs_lxc/config_lxc_ccimx95-dvk @@ -0,0 +1,17 @@ +# LXC base config for custom profile on CCIMX95. +# Placeholders are replaced by the image recipe. +lxc.arch = @LXC_ARCH@ +lxc.rootfs.path = dir:@LXC_FOLDER@/@CONTAINER_NAME@/rootfs +lxc.uts.name = @CONTAINER_NAME@ + +lxc.mount.auto = cgroup:mixed proc:mixed +lxc.mount.entry = /sys sys none bind,create=dir +lxc.mount.entry = tmpfs run tmpfs rw,nosuid,nodev,mode=0755,create=dir + +# custom prompt +lxc.environment = 'PS1=\h:\w$ ' + +# no network +lxc.net.0.type = empty + +lxc.init.cmd = @CONTAINER_INIT_MANAGER@ @CONTAINER_INIT_SCRIPT@ diff --git a/meta-digi-containers/containers/custom/configs_lxc/config_lxc_ccmp25-dvk b/meta-digi-containers/containers/custom/configs_lxc/config_lxc_ccmp25-dvk new file mode 100644 index 000000000..3d513c330 --- /dev/null +++ b/meta-digi-containers/containers/custom/configs_lxc/config_lxc_ccmp25-dvk @@ -0,0 +1,17 @@ +# LXC base config for custom profile on CCMP25. +# Placeholders are replaced by the image recipe. +lxc.arch = @LXC_ARCH@ +lxc.rootfs.path = dir:@LXC_FOLDER@/@CONTAINER_NAME@/rootfs +lxc.uts.name = @CONTAINER_NAME@ + +lxc.mount.auto = cgroup:mixed proc:mixed +lxc.mount.entry = /sys sys none bind,create=dir +lxc.mount.entry = tmpfs run tmpfs rw,nosuid,nodev,mode=0755,create=dir + +# custom prompt +lxc.environment = 'PS1=\h:\w$ ' + +# no network +lxc.net.0.type = empty + +lxc.init.cmd = @CONTAINER_INIT_MANAGER@ @CONTAINER_INIT_SCRIPT@ diff --git a/meta-digi-containers/containers/custom/rootfs_files/.keep b/meta-digi-containers/containers/custom/rootfs_files/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/meta-digi-containers/containers/lvgl/artifact/metadata/README.txt b/meta-digi-containers/containers/lvgl/artifact/metadata/README.txt new file mode 100644 index 000000000..c7ffcb2c8 --- /dev/null +++ b/meta-digi-containers/containers/lvgl/artifact/metadata/README.txt @@ -0,0 +1 @@ +Placeholder metadata for lvgl container artifacts. diff --git a/meta-digi-containers/containers/lvgl/artifact/metadata/changelog.txt b/meta-digi-containers/containers/lvgl/artifact/metadata/changelog.txt new file mode 100644 index 000000000..4bd4b9671 --- /dev/null +++ b/meta-digi-containers/containers/lvgl/artifact/metadata/changelog.txt @@ -0,0 +1 @@ +Placeholder changelog for lvgl container artifacts. diff --git a/meta-digi-containers/containers/lvgl/configs_lxc/config_lxc_ccimx95-dvk b/meta-digi-containers/containers/lvgl/configs_lxc/config_lxc_ccimx95-dvk new file mode 100644 index 000000000..b2333b746 --- /dev/null +++ b/meta-digi-containers/containers/lvgl/configs_lxc/config_lxc_ccimx95-dvk @@ -0,0 +1,30 @@ +# LXC config for LVGL on CCIMX95. +# Placeholders are replaced by the image recipe. +lxc.arch = @LXC_ARCH@ +lxc.rootfs.path = dir:@LXC_FOLDER@/@CONTAINER_NAME@/rootfs +lxc.uts.name = @CONTAINER_NAME@ + +lxc.mount.auto = cgroup:mixed proc:mixed +lxc.mount.entry = /sys sys none bind,create=dir +lxc.mount.entry = tmpfs run tmpfs rw,nosuid,nodev,mode=0755,create=dir + +# custom prompt +lxc.environment = 'PS1=\h:\w$ ' + +# no network +lxc.net.0.type = empty + +lxc.init.cmd = @CONTAINER_INIT_MANAGER@ @CONTAINER_INIT_SCRIPT@ +lxc.mount.entry = /dev/dri dev/dri none bind,create=dir +lxc.mount.entry = /dev/input dev/input none bind,create=dir +lxc.mount.entry = tmpfs dev/shm tmpfs rw,nosuid,nodev,mode=1777,create=dir +lxc.mount.entry = /dev/dri dev/dri none bind,create=dir +lxc.mount.entry = /dev/mali0 dev/mali0 none bind,create=file +lxc.mount.entry = /dev/input dev/input none bind,create=dir +lxc.mount.entry = /dev/tty dev/tty none bind,create=file +lxc.mount.entry = /dev/tty0 dev/tty0 none bind,create=file +lxc.mount.entry = /dev/tty1 dev/tty1 none bind,create=file +lxc.mount.entry = /dev/tty7 dev/tty7 none bind,create=file +lxc.mount.entry = /run/udev run/udev none bind,ro,create=dir +lxc.pty.max = 1024 +lxc.mount.entry = devpts dev/pts devpts rw,nosuid,noexec,relatime,mode=0620,ptmxmod diff --git a/meta-digi-containers/containers/lvgl/configs_lxc/config_lxc_ccmp25-dvk b/meta-digi-containers/containers/lvgl/configs_lxc/config_lxc_ccmp25-dvk new file mode 100644 index 000000000..ecae7bbf9 --- /dev/null +++ b/meta-digi-containers/containers/lvgl/configs_lxc/config_lxc_ccmp25-dvk @@ -0,0 +1,30 @@ +# LXC config for LVGL on CCMP25. +# Placeholders are replaced by the image recipe. +lxc.arch = @LXC_ARCH@ +lxc.rootfs.path = dir:@LXC_FOLDER@/@CONTAINER_NAME@/rootfs +lxc.uts.name = @CONTAINER_NAME@ + +lxc.mount.auto = cgroup:mixed proc:mixed +lxc.mount.entry = /sys sys none bind,create=dir +lxc.mount.entry = tmpfs run tmpfs rw,nosuid,nodev,mode=0755,create=dir + +# custom prompt +lxc.environment = 'PS1=\h:\w$ ' + +# no network +lxc.net.0.type = empty + +lxc.init.cmd = @CONTAINER_INIT_MANAGER@ @CONTAINER_INIT_SCRIPT@ +lxc.mount.entry = tmpfs dev/shm tmpfs rw,nosuid,nodev,mode=1777,create=dir +lxc.mount.entry = /dev/dri dev/dri none bind,create=dir +lxc.mount.entry = /dev/input dev/input none bind,create=dir +lxc.mount.entry = /dev/dri dev/dri none bind,create=dir +lxc.mount.entry = /dev/galcore dev/galcore none bind,create=file +lxc.mount.entry = /dev/input dev/input none bind,create=dir +lxc.mount.entry = /dev/tty dev/tty none bind,create=file +lxc.mount.entry = /dev/tty0 dev/tty0 none bind,create=file +lxc.mount.entry = /dev/tty1 dev/tty1 none bind,create=file +lxc.mount.entry = /dev/tty7 dev/tty7 none bind,create=file +lxc.mount.entry = /run/udev run/udev none bind,ro,create=dir +lxc.pty.max = 1024 +lxc.mount.entry = devpts dev/pts devpts rw,nosuid,noexec,relatime,mode=0620,ptmxmod diff --git a/meta-digi-containers/containers/lvgl/rootfs_files/.keep b/meta-digi-containers/containers/lvgl/rootfs_files/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/meta-digi-containers/containers/lvgl/rootfs_files/start-lvgl-demo.sh b/meta-digi-containers/containers/lvgl/rootfs_files/start-lvgl-demo.sh new file mode 100644 index 000000000..a5937890d --- /dev/null +++ b/meta-digi-containers/containers/lvgl/rootfs_files/start-lvgl-demo.sh @@ -0,0 +1,26 @@ +#!/bin/sh +export XDG_RUNTIME_DIR="/run/user/0" +export WAYLAND_DISPLAY="@WAYLAND_DISPLAY@" + +rm -rf "$XDG_RUNTIME_DIR" +mkdir -p "$XDG_RUNTIME_DIR" +chmod 0700 "$XDG_RUNTIME_DIR" +chown root:root "$XDG_RUNTIME_DIR" + +rm -rf /tmp/.X11-unix +mkdir -p /tmp/.X11-unix +chmod 1777 /tmp/.X11-unix + +rm -f /tmp/weston.log + +weston --backend=drm-backend.so --idle-time=0 --log=/tmp/weston.log & + +while :; do + if [ -S "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" ]; then + break + fi + sleep 0.1 +done +sleep 0.1 + +exec /usr/bin/lvgl-demo \ No newline at end of file diff --git a/meta-digi-containers/containers/webkit/artifact/metadata/README.txt b/meta-digi-containers/containers/webkit/artifact/metadata/README.txt new file mode 100644 index 000000000..66dfb3828 --- /dev/null +++ b/meta-digi-containers/containers/webkit/artifact/metadata/README.txt @@ -0,0 +1 @@ +Placeholder metadata for webkit container artifacts. diff --git a/meta-digi-containers/containers/webkit/artifact/metadata/changelog.txt b/meta-digi-containers/containers/webkit/artifact/metadata/changelog.txt new file mode 100644 index 000000000..a8a8e9675 --- /dev/null +++ b/meta-digi-containers/containers/webkit/artifact/metadata/changelog.txt @@ -0,0 +1 @@ +Placeholder changelog for webkit container artifacts. diff --git a/meta-digi-containers/containers/webkit/configs_lxc/config_lxc_ccimx95-dvk b/meta-digi-containers/containers/webkit/configs_lxc/config_lxc_ccimx95-dvk new file mode 100644 index 000000000..571852efc --- /dev/null +++ b/meta-digi-containers/containers/webkit/configs_lxc/config_lxc_ccimx95-dvk @@ -0,0 +1,55 @@ +# LXC config for WebKit on CCIMX95. +# Placeholders are replaced by the image recipe. +lxc.arch = @LXC_ARCH@ +lxc.rootfs.path = dir:@LXC_FOLDER@/@CONTAINER_NAME@/rootfs +lxc.uts.name = @CONTAINER_NAME@ + +lxc.mount.auto = cgroup:mixed proc:mixed +lxc.mount.entry = /sys sys none bind,create=dir +lxc.mount.entry = tmpfs run tmpfs rw,nosuid,nodev,mode=0755,create=dir + +# use host network +lxc.net.0.type = none + +lxc.init.cmd = @CONTAINER_INIT_MANAGER@ @CONTAINER_INIT_SCRIPT@ +lxc.environment = 'PS1=webkit-ccimx95:\w$ ' + +# audio +lxc.mount.entry = /dev/snd dev/snd none bind,create=dir +lxc.mount.entry = /etc/asound.conf etc/asound.conf none bind,create=file +lxc.mount.entry = /run/pulse run/pulse none bind,create=dir +lxc.environment = PULSE_SERVER=unix:/run/pulse/native + +# bluetooth +lxc.mount.entry = /run/dbus/system_bus_socket run/dbus/system_bus_socket none bind,create=file + +# python logging +lxc.mount.entry = /dev/log dev/log none bind,create=file +lxc.mount.entry = /run/systemd/journal run/systemd/journal none bind,create=dir + +# fw_printenv +lxc.mount.entry = /etc/fw_env.config etc/fw_env.config none bind,create=file +lxc.mount.entry = /dev/mmcblk0boot0 dev/mmcblk0boot0 none bind,optional,create=file +lxc.mount.entry = /dev/mmcblk0boot1 dev/mmcblk0boot1 none bind,optional,create=file + +# gpu for ccimx95 +lxc.mount.entry = /dev/dri dev/dri none bind,create=dir +lxc.mount.entry = /dev/galcore dev/galcore none bind,create=file +lxc.mount.entry = /dev/fb0 dev/fb0 none bind,create=file +lxc.mount.entry = /dev/input dev/input none bind,create=dir + +# tty +lxc.mount.entry = /dev/tty dev/tty none bind,create=file +lxc.mount.entry = /dev/tty0 dev/tty0 none bind,create=file +lxc.mount.entry = /dev/tty1 dev/tty1 none bind,create=file +lxc.mount.entry = /dev/tty7 dev/tty7 none bind,create=file + +# udev + pty +lxc.mount.entry = /run/udev run/udev none bind,ro,create=dir +lxc.pty.max = 1024 +lxc.mount.entry = devpts dev/pts devpts rw,nosuid,noexec,relatime,mode=0620,ptmxmode=0666,newinstance 0 0 + +# gpiochip access for webkit demo +# NEED TO BE UPDATED +lxc.mount.entry = /dev/gpiochip5 dev/gpiochip5 none bind,create=file +lxc.mount.entry = /dev/gpiochip5 dev/gpiochip5 none bind,create=file diff --git a/meta-digi-containers/containers/webkit/configs_lxc/config_lxc_ccmp25-dvk b/meta-digi-containers/containers/webkit/configs_lxc/config_lxc_ccmp25-dvk new file mode 100644 index 000000000..b443eb856 --- /dev/null +++ b/meta-digi-containers/containers/webkit/configs_lxc/config_lxc_ccmp25-dvk @@ -0,0 +1,53 @@ +# LXC config for WebKit on CCMP25. +# Placeholders are replaced by the image recipe. +lxc.arch = @LXC_ARCH@ +lxc.rootfs.path = dir:@LXC_FOLDER@/@CONTAINER_NAME@/rootfs +lxc.uts.name = @CONTAINER_NAME@ + +lxc.mount.auto = cgroup:mixed proc:mixed +lxc.mount.entry = /sys sys none bind,create=dir +lxc.mount.entry = tmpfs run tmpfs rw,nosuid,nodev,mode=0755,create=dir + +# use host network +lxc.net.0.type = none + +lxc.init.cmd = @CONTAINER_INIT_MANAGER@ @CONTAINER_INIT_SCRIPT@ +lxc.environment = 'PS1=webkit-ccmp25:\w$ ' + +# audio +lxc.mount.entry = /dev/snd dev/snd none bind,create=dir +lxc.mount.entry = /etc/asound.conf etc/asound.conf none bind,create=file +lxc.mount.entry = /run/pulse run/pulse none bind,create=dir +lxc.environment = PULSE_SERVER=unix:/run/pulse/native + +# bluetooth +lxc.mount.entry = /run/dbus/system_bus_socket run/dbus/system_bus_socket none bind,create=file + +# python logging +lxc.mount.entry = /dev/log dev/log none bind,create=file +lxc.mount.entry = /run/systemd/journal run/systemd/journal none bind,create=dir + +# fw_printenv +lxc.mount.entry = /etc/fw_env.config etc/fw_env.config none bind,create=file +lxc.mount.entry = /dev/mmcblk0boot0 dev/mmcblk0boot0 none bind,create=file +lxc.mount.entry = /dev/mmcblk0boot1 dev/mmcblk0boot1 none bind,create=file + +# gpu for ccmp25 +lxc.mount.entry = /dev/dri dev/dri none bind,create=dir +lxc.mount.entry = /dev/galcore dev/galcore none bind,create=file +lxc.mount.entry = /dev/fb0 dev/fb0 none bind,create=file +lxc.mount.entry = /dev/input dev/input none bind,create=dir + +# tty +lxc.mount.entry = /dev/tty dev/tty none bind,create=file +lxc.mount.entry = /dev/tty0 dev/tty0 none bind,create=file +lxc.mount.entry = /dev/tty1 dev/tty1 none bind,create=file +lxc.mount.entry = /dev/tty7 dev/tty7 none bind,create=file + +# udev + pty +lxc.mount.entry = /run/udev run/udev none bind,ro,create=dir +lxc.pty.max = 1024 +lxc.mount.entry = devpts dev/pts devpts rw,nosuid,noexec,relatime,mode=0620,ptmxmode=0666,newinstance 0 0 + +# gpiochip access for webkit demo +lxc.mount.entry = /dev/gpiochip5 dev/gpiochip5 none bind,create=file diff --git a/meta-digi-containers/containers/webkit/rootfs_files/start-webkit-demo.sh b/meta-digi-containers/containers/webkit/rootfs_files/start-webkit-demo.sh new file mode 100644 index 000000000..d5b758483 --- /dev/null +++ b/meta-digi-containers/containers/webkit/rootfs_files/start-webkit-demo.sh @@ -0,0 +1,36 @@ +#!/bin/sh +export XDG_RUNTIME_DIR="/run/user/0" +export WAYLAND_DISPLAY="@WAYLAND_DISPLAY@" + +rm -rf "$XDG_RUNTIME_DIR" +mkdir -p "$XDG_RUNTIME_DIR" +chmod 0700 "$XDG_RUNTIME_DIR" +chown root:root "$XDG_RUNTIME_DIR" + +rm -rf /tmp/.X11-unix +mkdir -p /tmp/.X11-unix +chmod 1777 /tmp/.X11-unix + +rm -f /tmp/weston.log + +weston --backend=drm-backend.so --idle-time=0 --log=/tmp/weston.log & + +while :; do + if [ -S "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" ]; then + break + fi + sleep 0.1 +done +sleep 0.1 + +/etc/connectcore-demo-server start + +# wait for server to be ready +until nc -w 1 localhost 9090 /dev/null 2>&1; do + sleep 0.1 +done + +/etc/connectcore-demo-example-webkit start +# We need a process waiting indefinetily, if not the "init" process dies +# and there is not any remaining process +exec /usr/bin/docker-init -- sleep infinity \ No newline at end of file diff --git a/meta-digi-containers/recipes-core/images/dey-image-container-artifact.inc b/meta-digi-containers/recipes-core/images/dey-image-container-artifact.inc new file mode 100644 index 000000000..794388023 --- /dev/null +++ b/meta-digi-containers/recipes-core/images/dey-image-container-artifact.inc @@ -0,0 +1,153 @@ +# +# Copyright (C) 2026, Digi International Inc. +# +######################## +# Unified artifact bundles +######################## +do_image_container_artifacts() { + lxc_bundle="${DEPLOY_DIR_IMAGE}/${LXC_OUTPUT_NAME}" + podman_archive="${DEPLOY_DIR_IMAGE}/${PODMAN_OUTPUT_NAME}" + template_dir="${CONTAINER_ARTIFACT_TEMPLATE_DIR}" + default_template_dir="${CONTAINER_DEFAULT_ARTIFACT_TEMPLATE_DIR}" + image_prefix="${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}" + workdir="$(mktemp -d)" + trap 'rm -rf "${workdir}"' EXIT + + if [ -z "${template_dir}" ] && [ -d "${default_template_dir}" ]; then + template_dir="${default_template_dir}" + bbnote "Using default artifact template dir: ${default_template_dir}" + fi + + if [ ! -f "${lxc_bundle}" ]; then + bbfatal "Expected LXC bundle not found: ${lxc_bundle}" + fi + if [ ! -f "${podman_archive}" ]; then + bbfatal "Expected Podman archive not found: ${podman_archive}" + fi + + copy_template_files() { + artifact_dir="$1" + + if [ -z "${template_dir}" ]; then + return 0 + fi + if [ ! -d "${template_dir}" ]; then + bbfatal "CONTAINER_ARTIFACT_TEMPLATE_DIR does not exist: ${template_dir}" + fi + + if [ -d "${template_dir}/metadata" ]; then + cp -a "${template_dir}/metadata" "${artifact_dir}/metadata" + fi + } + + json_escape() { + printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g' + } + + write_manifest() { + artifact_dir="$1" + runtime="$2" + artifact_type="$3" + payload_name="$4" + digest="$5" + size_bytes="$6" + created_at="$7" + create_args="$8" + build_id="$9" + + package_id_esc="$(json_escape "${CONTAINER_PACKAGE_ID}")" + version_esc="$(json_escape "${CONTAINER_ARTIFACT_VERSION}")" + create_args_esc="$(json_escape "${create_args}")" + fw_versions_esc="$(json_escape "${CONTAINER_FIRMWARE_VERSIONS}")" + description_esc="$(json_escape "${CONTAINER_ARTIFACT_DESCRIPTION}")" + build_id_esc="$(json_escape "${build_id}")" + + printf '%s\n' \ + '{' \ + " \"package_id\": \"${package_id_esc}\"," \ + " \"version\": \"${version_esc}\"," \ + " \"runtime\": \"${runtime}\"," \ + " \"artifact_type\": \"${artifact_type}\"," \ + > "${artifact_dir}/manifest.json" + + if [ -n "${create_args}" ]; then + printf '%s\n' " \"create_args\": \"${create_args_esc}\"," >> "${artifact_dir}/manifest.json" + fi + + printf '%s\n' \ + " \"created_at\": \"${created_at}\"," \ + " \"digest\": \"sha256:${digest}\"," \ + " \"device_types\": ${CONTAINER_DEVICE_TYPES_JSON}," \ + " \"firmware_versions\": \"${fw_versions_esc}\"," \ + " \"size_bytes\": ${size_bytes}," \ + " \"build_id\": \"${build_id_esc}\"," \ + " \"description\": \"${description_esc}\"," \ + " \"labels\": ${CONTAINER_ARTIFACT_LABELS_JSON}" \ + '}' \ + >> "${artifact_dir}/manifest.json" + } + + create_artifact_bundle() { + runtime="$1" + src_payload="$2" + payload_name="$3" + output_name="$4" + mode="$5" + artifact_type="$6" + create_args="$7" + bundle_dir="${workdir}/bundle-${runtime}" + artifact_dir="${bundle_dir}" + + rm -rf "${bundle_dir}" + mkdir -p "${artifact_dir}/payload" "${artifact_dir}/checksums" + + copy_template_files "${artifact_dir}" + + if [ "${mode}" = "lxc" ]; then + lxc_unpack="${workdir}/lxc-unpack" + rm -rf "${lxc_unpack}" + mkdir -p "${lxc_unpack}" + tar -xJf "${src_payload}" -C "${lxc_unpack}" + + if [ ! -d "${lxc_unpack}/${CONTAINER_NAME}/rootfs" ] || [ ! -f "${lxc_unpack}/${CONTAINER_NAME}/config" ]; then + bbfatal "LXC bundle does not contain expected ${CONTAINER_NAME}/rootfs and ${CONTAINER_NAME}/config" + fi + + tar -C "${lxc_unpack}/${CONTAINER_NAME}" \ + -czf "${artifact_dir}/payload/${payload_name}" \ + rootfs config + else + cp "${src_payload}" "${artifact_dir}/payload/${payload_name}" + fi + + digest="$(sha256sum "${artifact_dir}/payload/${payload_name}" | awk '{print $1}')" + size_bytes="$(stat -c %s "${artifact_dir}/payload/${payload_name}")" + created_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)" + build_id="${CONTAINER_ARTIFACT_BUILD_ID}" + if [ -z "${build_id}" ]; then + if command -v git >/dev/null 2>&1; then + build_id="$(git -C "${META_DIGI_REPO_DIR}" rev-parse HEAD 2>/dev/null || true)" + fi + fi + printf '%s %s\n' "${digest}" "payload/${payload_name}" > "${artifact_dir}/checksums/sha256sums.txt" + write_manifest "${artifact_dir}" "${runtime}" "${artifact_type}" "${payload_name}" "${digest}" "${size_bytes}" "${created_at}" "${create_args}" "${build_id}" + + tar -C "${bundle_dir}" -czf "${DEPLOY_DIR_IMAGE}/${output_name}" . + + if [ ! -s "${DEPLOY_DIR_IMAGE}/${output_name}" ]; then + bbfatal "Container artifact bundle not generated correctly: ${DEPLOY_DIR_IMAGE}/${output_name}" + fi + + bbnote "Container ${runtime} artifact ready: ${DEPLOY_DIR_IMAGE}/${output_name}" + } + + create_artifact_bundle "lxc" "${lxc_bundle}" "rootfs_and_config.tgz" "${LXC_ARTIFACT_OUTPUT_NAME}" "lxc" "lxc-tgz" "" + create_artifact_bundle "podman" "${podman_archive}" "image.tar" "${PODMAN_ARTIFACT_OUTPUT_NAME}" "podman" "podman-image-tar" "${CONTAINER_CREATE_ARGS_PODMAN}" + + bbnote "Removing intermediate container artifacts from this build..." + rm -f "${lxc_bundle}" "${podman_archive}" + rm -f "${image_prefix}.tar.xz" "${image_prefix}.rootfs-oci.tar" "${image_prefix}.rootfs-oci-dir.tar" + rm -rf "${image_prefix}.rootfs-oci" +} + +addtask image_container_artifacts after do_image_lxc_bundle do_image_podman_archive before do_build diff --git a/meta-digi-containers/recipes-core/images/dey-image-container-lxc.inc b/meta-digi-containers/recipes-core/images/dey-image-container-lxc.inc index 08780ade8..cce78b070 100644 --- a/meta-digi-containers/recipes-core/images/dey-image-container-lxc.inc +++ b/meta-digi-containers/recipes-core/images/dey-image-container-lxc.inc @@ -25,7 +25,7 @@ do_image_lxc_bundle() { config_in="${LXC_CONFIG_FILE}" if [ ! -f "${config_in}" ]; then - bbfatal "LXC config file not found for CONTAINER_TYPE='${CONTAINER_TYPE}' and platform='${LXC_PLATFORM}': ${config_in}" + bbfatal "LXC config file not found for CONTAINER_TYPE='${CONTAINER_TYPE}' and MACHINE='${MACHINE}': ${config_in}" fi sed \ diff --git a/meta-digi-containers/recipes-core/images/dey-image-container.bb b/meta-digi-containers/recipes-core/images/dey-image-container.bb index 884206dde..e92745640 100644 --- a/meta-digi-containers/recipes-core/images/dey-image-container.bb +++ b/meta-digi-containers/recipes-core/images/dey-image-container.bb @@ -48,11 +48,10 @@ PODMAN_ARTIFACT_OUTPUT_NAME ?= "${CONTAINER_NAME}_artifact_podman_${MACHINE}.tar ######################## CONTAINERS_DIR ?= "${THISDIR}/../../containers" LXC_FOLDER ?= "/var/lib/lxc" -LXC_PLATFORM ?= "${@d.getVar('MACHINE').split('-')[0]}" LXC_OUTPUT_NAME ?= "${CONTAINER_NAME}_lxc_${MACHINE}.tar.xz" LXC_ARTIFACT_OUTPUT_NAME ?= "${CONTAINER_NAME}_artifact_lxc_${MACHINE}.tar.gz" LXC_CONFIG_DIR ?= "${CONTAINER_PROFILE_DIR}/configs_lxc" -LXC_CONFIG_FILE ?= "${LXC_CONFIG_DIR}/config_lxc_${LXC_PLATFORM}" +LXC_CONFIG_FILE ?= "${LXC_CONFIG_DIR}/config_lxc_${MACHINE}" ######################## # Artifact layout knobs @@ -95,3 +94,33 @@ IMAGE_INSTALL = " \ netbase \ tini \ " + +######################## +# Container type customizations LVGL +######################## +CONTAINER_INIT_SCRIPT:container-lvgl = "/start-lvgl-demo.sh" +IMAGE_INSTALL:append:container-lvgl = " lvgl-demo weston" +DISTRO_FEATURES:remove:container-lvgl = " wayland" + +######################## +# Container type customizations webkit +######################## +CONTAINER_INIT_SCRIPT:container-webkit = "/start-webkit-demo.sh" +IMAGE_INSTALL:append:container-webkit = " \ + alsa-utils \ + bluez5 \ + connectcore-demo-example \ + dbus \ + libdrm \ + libgpiod-tools \ + libinput \ + libubootenv-bin \ + mesa \ + networkmanager-nmcli \ + packagegroup-dey-webkit \ + pulseaudio-server \ + python3-dbus \ + wayland \ + wayland-protocols \ + weston \ +"