diff options
| author | Bruce Ashfield <bruce.ashfield@gmail.com> | 2026-02-06 03:54:16 +0000 |
|---|---|---|
| committer | Bruce Ashfield <bruce.ashfield@gmail.com> | 2026-02-09 03:34:12 +0000 |
| commit | cd5081a5e9ff1c6f5eb74ab90326d602142248f9 (patch) | |
| tree | 942b4954cb73e217d5c914d381d262b231ee8ab8 /classes/container-bundle.bbclass | |
| parent | b4ad3f9eb2f022b6f69b2e78dbca80974d5bf84a (diff) | |
| download | meta-virtualization-cd5081a5e9ff1c6f5eb74ab90326d602142248f9.tar.gz | |
container-cross-install: add CONTAINER_SERVICE_FILE support
Add support for custom systemd service files (Docker) or Quadlet
container files (Podman) instead of auto-generated ones for container
autostart.
For containers requiring specific startup configuration (ports, volumes,
capabilities, dependencies), users can now provide custom service files
using the CONTAINER_SERVICE_FILE varflag:
CONTAINER_SERVICE_FILE[container-name] = "${UNPACKDIR}/myservice.service"
For BUNDLED_CONTAINERS in image recipes:
SRC_URI += "file://myapp.service"
BUNDLED_CONTAINERS = "myapp-container:docker:autostart"
CONTAINER_SERVICE_FILE[myapp-container] = "${UNPACKDIR}/myapp.service"
For container-bundle packages:
SRC_URI = "file://myapp.service"
CONTAINER_BUNDLES = "myapp-container:autostart"
CONTAINER_SERVICE_FILE[myapp-container] = "${UNPACKDIR}/myapp.service"
Implementation:
- container-cross-install.bbclass: Add get_container_service_file_map()
to build varflag map, install_custom_service() for BUNDLED_CONTAINERS,
and install_custom_service_from_bundle() for bundle packages
- container-bundle.bbclass: Install custom service files to
${datadir}/container-bundles/${runtime}/services/
Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Diffstat (limited to 'classes/container-bundle.bbclass')
| -rw-r--r-- | classes/container-bundle.bbclass | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/classes/container-bundle.bbclass b/classes/container-bundle.bbclass index 3d3f3a16..3c8ad030 100644 --- a/classes/container-bundle.bbclass +++ b/classes/container-bundle.bbclass | |||
| @@ -141,6 +141,30 @@ | |||
| 141 | # The runtime subdirectory (docker/ vs podman/) tells container-cross-install | 141 | # The runtime subdirectory (docker/ vs podman/) tells container-cross-install |
| 142 | # which vrunner runtime to use for import. | 142 | # which vrunner runtime to use for import. |
| 143 | # | 143 | # |
| 144 | # =========================================================================== | ||
| 145 | # Custom Service Files (CONTAINER_SERVICE_FILE) | ||
| 146 | # =========================================================================== | ||
| 147 | # | ||
| 148 | # For containers requiring specific startup configuration, provide custom | ||
| 149 | # service files instead of auto-generated ones: | ||
| 150 | # | ||
| 151 | # SRC_URI = "file://myapp.service file://mydb.container" | ||
| 152 | # | ||
| 153 | # CONTAINER_BUNDLES = "\ | ||
| 154 | # myapp-container:autostart \ | ||
| 155 | # mydb-container:autostart \ | ||
| 156 | # " | ||
| 157 | # | ||
| 158 | # CONTAINER_SERVICE_FILE[myapp-container] = "${UNPACKDIR}/myapp.service" | ||
| 159 | # CONTAINER_SERVICE_FILE[mydb-container] = "${UNPACKDIR}/mydb.container" | ||
| 160 | # | ||
| 161 | # Custom files are installed to ${datadir}/container-bundles/${RUNTIME}/services/ | ||
| 162 | # and used by container-cross-install instead of generating default services. | ||
| 163 | # | ||
| 164 | # For Docker, provide a .service file; for Podman, provide a .container Quadlet. | ||
| 165 | # | ||
| 166 | # See docs/container-bundling.md for detailed examples. | ||
| 167 | # | ||
| 144 | # See also: container-cross-install.bbclass | 168 | # See also: container-cross-install.bbclass |
| 145 | 169 | ||
| 146 | CONTAINER_BUNDLES ?= "" | 170 | CONTAINER_BUNDLES ?= "" |
| @@ -247,6 +271,29 @@ python __anonymous() { | |||
| 247 | d.setVar('_REMOTE_CONTAINERS', ' '.join(remote_urls)) | 271 | d.setVar('_REMOTE_CONTAINERS', ' '.join(remote_urls)) |
| 248 | d.setVar('_PROCESSED_BUNDLES', ' '.join(processed_bundles)) | 272 | d.setVar('_PROCESSED_BUNDLES', ' '.join(processed_bundles)) |
| 249 | d.setVar('_BUNDLE_RUNTIME', runtime) | 273 | d.setVar('_BUNDLE_RUNTIME', runtime) |
| 274 | |||
| 275 | # Build service file map for custom service files | ||
| 276 | # Format: container1=/path/to/file1;container2=/path/to/file2 | ||
| 277 | service_mappings = [] | ||
| 278 | for bundle in bundles: | ||
| 279 | # Extract container name (handle both local and remote formats) | ||
| 280 | if is_remote_container(bundle): | ||
| 281 | if bundle.endswith(':autostart') or bundle.endswith(':always') or \ | ||
| 282 | bundle.endswith(':unless-stopped') or bundle.endswith(':on-failure') or \ | ||
| 283 | bundle.endswith(':no'): | ||
| 284 | last_colon = bundle.rfind(':') | ||
| 285 | source = bundle[:last_colon] | ||
| 286 | else: | ||
| 287 | source = bundle | ||
| 288 | else: | ||
| 289 | parts = bundle.split(':') | ||
| 290 | source = parts[0] | ||
| 291 | |||
| 292 | custom_file = d.getVarFlag('CONTAINER_SERVICE_FILE', source) | ||
| 293 | if custom_file: | ||
| 294 | service_mappings.append(f"{source}={custom_file}") | ||
| 295 | |||
| 296 | d.setVar('_CONTAINER_SERVICE_FILE_MAP', ';'.join(service_mappings)) | ||
| 250 | } | 297 | } |
| 251 | 298 | ||
| 252 | # S must be a real directory | 299 | # S must be a real directory |
| @@ -402,6 +449,39 @@ do_install() { | |||
| 402 | install -m 0644 ${B}/bundle-metadata.txt \ | 449 | install -m 0644 ${B}/bundle-metadata.txt \ |
| 403 | ${D}${datadir}/container-bundles/${PN}.meta | 450 | ${D}${datadir}/container-bundles/${PN}.meta |
| 404 | fi | 451 | fi |
| 452 | |||
| 453 | # Install custom service files from CONTAINER_SERVICE_FILE varflags | ||
| 454 | # Format: container1=/path/to/file1;container2=/path/to/file2 | ||
| 455 | if [ -n "${_CONTAINER_SERVICE_FILE_MAP}" ]; then | ||
| 456 | install -d ${D}${datadir}/container-bundles/${RUNTIME}/services | ||
| 457 | echo "${_CONTAINER_SERVICE_FILE_MAP}" | tr ';' '\n' | while IFS='=' read -r container_name service_file; do | ||
| 458 | [ -z "$container_name" ] && continue | ||
| 459 | [ -z "$service_file" ] && continue | ||
| 460 | |||
| 461 | if [ ! -f "$service_file" ]; then | ||
| 462 | bbwarn "Custom service file not found: $service_file (for container $container_name)" | ||
| 463 | continue | ||
| 464 | fi | ||
| 465 | |||
| 466 | # Sanitize container name for filename (replace / and : with _) | ||
| 467 | local sanitized_name=$(echo "$container_name" | sed 's|[/:]|_|g') | ||
| 468 | |||
| 469 | # Determine file extension based on runtime and source file | ||
| 470 | local dest_file | ||
| 471 | if [ "${RUNTIME}" = "docker" ]; then | ||
| 472 | dest_file="${sanitized_name}.service" | ||
| 473 | elif [ "${RUNTIME}" = "podman" ]; then | ||
| 474 | dest_file="${sanitized_name}.container" | ||
| 475 | else | ||
| 476 | # Keep original extension | ||
| 477 | dest_file="${sanitized_name}.$(echo "$service_file" | sed 's/.*\.//')" | ||
| 478 | fi | ||
| 479 | |||
| 480 | bbnote "Installing custom service file: $service_file -> services/${dest_file}" | ||
| 481 | install -m 0644 "$service_file" \ | ||
| 482 | ${D}${datadir}/container-bundles/${RUNTIME}/services/${dest_file} | ||
| 483 | done | ||
| 484 | fi | ||
| 405 | } | 485 | } |
| 406 | 486 | ||
| 407 | FILES:${PN} = "${datadir}/container-bundles" | 487 | FILES:${PN} = "${datadir}/container-bundles" |
