summaryrefslogtreecommitdiffstats
path: root/classes/container-cross-install.bbclass
diff options
context:
space:
mode:
Diffstat (limited to 'classes/container-cross-install.bbclass')
-rw-r--r--classes/container-cross-install.bbclass157
1 files changed, 156 insertions, 1 deletions
diff --git a/classes/container-cross-install.bbclass b/classes/container-cross-install.bbclass
index d18c6436..bb2547e0 100644
--- a/classes/container-cross-install.bbclass
+++ b/classes/container-cross-install.bbclass
@@ -98,6 +98,27 @@
98# The runtime is determined by the subdirectory (docker/ vs podman/), 98# The runtime is determined by the subdirectory (docker/ vs podman/),
99# which is set by container-bundle.bbclass based on CONTAINER_BUNDLE_RUNTIME. 99# which is set by container-bundle.bbclass based on CONTAINER_BUNDLE_RUNTIME.
100# 100#
101# ===========================================================================
102# Custom Service Files (CONTAINER_SERVICE_FILE)
103# ===========================================================================
104#
105# For containers requiring specific startup configuration (ports, volumes,
106# capabilities, dependencies), provide custom service files instead of
107# auto-generated ones using the CONTAINER_SERVICE_FILE varflag:
108#
109# CONTAINER_SERVICE_FILE[container-name] = "${UNPACKDIR}/myservice.service"
110# CONTAINER_SERVICE_FILE[other-container] = "${UNPACKDIR}/other.container"
111#
112# Usage in image recipe:
113# SRC_URI += "file://myapp.service"
114# BUNDLED_CONTAINERS = "myapp-container:docker:autostart"
115# CONTAINER_SERVICE_FILE[myapp-container] = "${UNPACKDIR}/myapp.service"
116#
117# The custom file replaces the auto-generated service. For Docker, provide
118# a .service file; for Podman, provide a .container Quadlet file.
119#
120# See docs/container-bundling.md for detailed examples.
121#
101# See also: container-bundle.bbclass 122# See also: container-bundle.bbclass
102 123
103# Inherit shared functions for multiconfig/machine/arch mapping 124# Inherit shared functions for multiconfig/machine/arch mapping
@@ -164,6 +185,26 @@ python __anonymous() {
164 d.appendVarFlag('do_rootfs', 'depends', deps) 185 d.appendVarFlag('do_rootfs', 'depends', deps)
165} 186}
166 187
188# Build CONTAINER_SERVICE_FILE_MAP from varflags for shell access
189# Format: container1=/path/to/file1;container2=/path/to/file2
190def get_container_service_file_map(d):
191 """Build a semicolon-separated map of container names to custom service files"""
192 bundled = (d.getVar('BUNDLED_CONTAINERS') or "").split()
193 if not bundled:
194 return ""
195
196 mappings = []
197 for entry in bundled:
198 parts = entry.split(':')
199 container_name = parts[0]
200 custom_file = d.getVarFlag('CONTAINER_SERVICE_FILE', container_name)
201 if custom_file:
202 mappings.append(f"{container_name}={custom_file}")
203
204 return ";".join(mappings)
205
206CONTAINER_SERVICE_FILE_MAP = "${@get_container_service_file_map(d)}"
207
167# Path to vrunner.sh from vcontainer-native 208# Path to vrunner.sh from vcontainer-native
168VRUNNER_PATH = "${STAGING_BINDIR_NATIVE}/vrunner.sh" 209VRUNNER_PATH = "${STAGING_BINDIR_NATIVE}/vrunner.sh"
169 210
@@ -419,7 +460,21 @@ merge_installed_bundles() {
419 460
420 bbnote "Creating autostart service for $source ($runtime_type, restart=$restart_policy)" 461 bbnote "Creating autostart service for $source ($runtime_type, restart=$restart_policy)"
421 462
463 # Check for custom service file in bundle's services directory
464 # Custom files are stored as: services/<source-sanitized>.(service|container)
465 local source_sanitized=$(echo "$source" | sed 's|[/:]|_|g')
466 local custom_service_file=""
467
422 if [ "$runtime_type" = "docker" ]; then 468 if [ "$runtime_type" = "docker" ]; then
469 custom_service_file="${BUNDLES_DIR}/${runtime_type}/services/${source_sanitized}.service"
470 elif [ "$runtime_type" = "podman" ]; then
471 custom_service_file="${BUNDLES_DIR}/${runtime_type}/services/${source_sanitized}.container"
472 fi
473
474 if [ -n "$custom_service_file" ] && [ -f "$custom_service_file" ]; then
475 bbnote "Using custom service file from bundle: $custom_service_file"
476 install_custom_service_from_bundle "$source" "$service_name" "$runtime_type" "$custom_service_file"
477 elif [ "$runtime_type" = "docker" ]; then
423 generate_docker_service_from_bundle "$service_name" "$image_name" "$image_tag" "$restart_policy" 478 generate_docker_service_from_bundle "$service_name" "$image_name" "$image_tag" "$restart_policy"
424 elif [ "$runtime_type" = "podman" ]; then 479 elif [ "$runtime_type" = "podman" ]; then
425 generate_podman_service_from_bundle "$service_name" "$image_name" "$image_tag" "$restart_policy" 480 generate_podman_service_from_bundle "$service_name" "$image_name" "$image_tag" "$restart_policy"
@@ -434,6 +489,51 @@ merge_installed_bundles() {
434 return 0 489 return 0
435} 490}
436 491
492# Install a custom service file from a bundle package
493# Args: source service_name runtime_type custom_file
494install_custom_service_from_bundle() {
495 local source="$1"
496 local service_name="$2"
497 local runtime_type="$3"
498 local custom_file="$4"
499
500 if [ ! -f "$custom_file" ]; then
501 bbwarn "Custom service file not found: $custom_file (for container $source)"
502 return 1
503 fi
504
505 if [ "$runtime_type" = "docker" ]; then
506 # Docker: Install as systemd service
507 local service_dir="${IMAGE_ROOTFS}/lib/systemd/system"
508 local service_file="${service_dir}/${service_name}.service"
509
510 mkdir -p "$service_dir"
511 install -m 0644 "$custom_file" "$service_file"
512
513 # Enable the service via symlink
514 local wants_dir="${IMAGE_ROOTFS}/etc/systemd/system/multi-user.target.wants"
515 mkdir -p "$wants_dir"
516 ln -sf "/lib/systemd/system/${service_name}.service" "${wants_dir}/${service_name}.service"
517
518 bbnote "Installed custom service from bundle: $custom_file -> ${service_name}.service"
519
520 elif [ "$runtime_type" = "podman" ]; then
521 # Podman: Install as Quadlet container file
522 local quadlet_dir="${IMAGE_ROOTFS}/etc/containers/systemd"
523 local container_file="${quadlet_dir}/${service_name}.container"
524
525 mkdir -p "$quadlet_dir"
526 install -m 0644 "$custom_file" "$container_file"
527
528 bbnote "Installed custom Quadlet file from bundle: $custom_file -> ${service_name}.container"
529 else
530 bbwarn "Unknown runtime '$runtime_type' for custom service file from bundle, skipping"
531 return 1
532 fi
533
534 return 0
535}
536
437# Generate Docker systemd service (for bundle packages) 537# Generate Docker systemd service (for bundle packages)
438generate_docker_service_from_bundle() { 538generate_docker_service_from_bundle() {
439 local service_name="$1" 539 local service_name="$1"
@@ -648,6 +748,47 @@ EOF
648 bbnote "Created Quadlet file ${service_name}.container for Podman container ${image_name}:${image_tag}" 748 bbnote "Created Quadlet file ${service_name}.container for Podman container ${image_name}:${image_tag}"
649 } 749 }
650 750
751 # Install a custom service file provided by the user
752 # Args: container_name service_name runtime_type custom_file
753 install_custom_service() {
754 local container_name="$1"
755 local service_name="$2"
756 local runtime_type="$3"
757 local custom_file="$4"
758
759 if [ ! -f "$custom_file" ]; then
760 bbfatal "Custom service file not found: $custom_file (for container $container_name)"
761 fi
762
763 if [ "$runtime_type" = "docker" ]; then
764 # Docker: Install as systemd service
765 local service_dir="${IMAGE_ROOTFS}/lib/systemd/system"
766 local service_file="${service_dir}/${service_name}.service"
767
768 mkdir -p "$service_dir"
769 install -m 0644 "$custom_file" "$service_file"
770
771 # Enable the service via symlink
772 local wants_dir="${IMAGE_ROOTFS}/etc/systemd/system/multi-user.target.wants"
773 mkdir -p "$wants_dir"
774 ln -sf "/lib/systemd/system/${service_name}.service" "${wants_dir}/${service_name}.service"
775
776 bbnote "Installed custom service: $custom_file -> ${service_name}.service"
777
778 elif [ "$runtime_type" = "podman" ]; then
779 # Podman: Install as Quadlet container file
780 local quadlet_dir="${IMAGE_ROOTFS}/etc/containers/systemd"
781 local container_file="${quadlet_dir}/${service_name}.container"
782
783 mkdir -p "$quadlet_dir"
784 install -m 0644 "$custom_file" "$container_file"
785
786 bbnote "Installed custom Quadlet file: $custom_file -> ${service_name}.container"
787 else
788 bbwarn "Unknown runtime '$runtime_type' for custom service file, skipping"
789 fi
790 }
791
651 # Install autostart services for containers with autostart policy 792 # Install autostart services for containers with autostart policy
652 install_autostart_services() { 793 install_autostart_services() {
653 bbnote "Processing container autostart services..." 794 bbnote "Processing container autostart services..."
@@ -697,7 +838,21 @@ EOF
697 838
698 bbnote "Creating autostart service for $container_name ($runtime_type, restart=$restart_policy)" 839 bbnote "Creating autostart service for $container_name ($runtime_type, restart=$restart_policy)"
699 840
700 if [ "$runtime_type" = "docker" ]; then 841 # Check for custom service file via CONTAINER_SERVICE_FILE varflag
842 # This is evaluated at rootfs time, so we use a Python helper
843 local custom_service_file="${CONTAINER_SERVICE_FILE_MAP}"
844 local custom_file=""
845
846 # Parse the map to find this container's custom file
847 # Format: container1=/path/to/file1;container2=/path/to/file2
848 if [ -n "$custom_service_file" ]; then
849 custom_file=$(echo "$custom_service_file" | tr ';' '\n' | grep "^${container_name}=" | cut -d= -f2-)
850 fi
851
852 if [ -n "$custom_file" ] && [ -f "$custom_file" ]; then
853 bbnote "Using custom service file for $container_name: $custom_file"
854 install_custom_service "$container_name" "$service_name" "$runtime_type" "$custom_file"
855 elif [ "$runtime_type" = "docker" ]; then
701 generate_docker_service "$service_name" "${CONTAINER_IMAGE_NAME}" "${CONTAINER_IMAGE_TAG}" "$restart_policy" 856 generate_docker_service "$service_name" "${CONTAINER_IMAGE_NAME}" "${CONTAINER_IMAGE_TAG}" "$restart_policy"
702 elif [ "$runtime_type" = "podman" ]; then 857 elif [ "$runtime_type" = "podman" ]; then
703 generate_podman_service "$service_name" "${CONTAINER_IMAGE_NAME}" "${CONTAINER_IMAGE_TAG}" "$restart_policy" 858 generate_podman_service "$service_name" "${CONTAINER_IMAGE_NAME}" "${CONTAINER_IMAGE_TAG}" "$restart_policy"