| #!/bin/sh |
| set -eu |
| |
| # Configuration |
| # Persistent configuration paths |
| PERSISTENT_TRUE_HITLESS_CONFIG_DIR="/var/google/true-hitless" |
| PERSISTENT_SERVICE_LIST_FILE="${PERSISTENT_TRUE_HITLESS_CONFIG_DIR}/true-hitless-service-list.txt" |
| # Systemd configuration directories |
| SYSTEMD_RUNTIME_OVERRIDE_DIR="/run/systemd/system" |
| # Content for block-override.conf |
| BLOCK_OVERRIDE_CONTENT="# True-hitless block-override configuration |
| # Blocks True-hitless services from multi-user.target |
| # Services will only start after one of the postprocessing services completes |
| [Unit] |
| # Check for completion flags created by postprocessing scripts |
| # Using subfolder /run/true-hitless/ for better organization |
| # The -complete suffix indicates the postprocessing is complete |
| # Removed After=emmc-available-postprocessing.service to avoid deadlock during install |
| ConditionPathExists=|/run/true-hitless/emmc-available-postprocessing-complete |
| ConditionPathExists=|/run/true-hitless/emmc-unavailable-postprocessing-complete" |
| # Systemd folder paths |
| SYSTEMD_USR_LIB_DIR="/usr/lib/systemd/system" |
| SYSTEMD_ETC_DIR="/etc/systemd/system" |
| # Systemd target configuration |
| SYSTEMD_DISABLE_FROM_TARGETS="multi-user.target.wants" |
| SYSTEMD_ENABLE_TO_TARGETS="emmc-available.target.wants" |
| changes_made=0 |
| |
| ################################################################################ |
| # 1. Verify true-hitless package installation and enablement |
| ################################################################################ |
| if [ ! -d "${PERSISTENT_TRUE_HITLESS_CONFIG_DIR}" ]; then |
| echo "True-hitless package is not installed (true-hitless directory not found at ${PERSISTENT_TRUE_HITLESS_CONFIG_DIR})" >&2 |
| exit 0 |
| fi |
| if [ ! -f "${PERSISTENT_SERVICE_LIST_FILE}" ]; then |
| echo "True-hitless is not enabled (true-hitless service list file not found at ${PERSISTENT_SERVICE_LIST_FILE})" >&2 |
| exit 0 |
| fi |
| echo "True-hitless is enabled" >&2 |
| echo "Starting true-hitless initialization..." >&2 |
| |
| |
| ################################################################################ |
| # 2. Read and parse service list |
| ################################################################################ |
| # Service list file format: One service per line with .service suffix |
| # Example: |
| # phosphor-abc@.service |
| # xyz.openbmc_project.abcd@.service |
| # my-service.service |
| # No comments, no empty lines, no extra whitespace |
| ################################################################################ |
| echo "Reading service list from ${PERSISTENT_SERVICE_LIST_FILE}..." >&2 |
| service_list=$(cat "${PERSISTENT_SERVICE_LIST_FILE}") |
| |
| if [ -z "$service_list" ]; then |
| echo "No services found in ${PERSISTENT_SERVICE_LIST_FILE}" >&2 |
| exit 0 |
| fi |
| echo "Services to process: $service_list" >&2 |
| |
| ################################################################################ |
| # 3. Process each service |
| ################################################################################ |
| # Create target directories if they don't exist |
| for target in $SYSTEMD_ENABLE_TO_TARGETS; do |
| mkdir -p "${SYSTEMD_ETC_DIR}/$target" |
| done |
| |
| for service in $service_list; do |
| echo "Processing service: ${service}" >&2 |
| |
| service_override_dir="${SYSTEMD_RUNTIME_OVERRIDE_DIR}/${service}.d" |
| mkdir -p "$service_override_dir" |
| |
| block_override_file="${service_override_dir}/block-override.conf" |
| echo " Generating block-override.conf" >&2 |
| echo "$BLOCK_OVERRIDE_CONTENT" > "$block_override_file" |
| |
| # Find the service unit file |
| service_unit_path="${SYSTEMD_USR_LIB_DIR}/${service}" |
| if [ ! -f "$service_unit_path" ]; then |
| service_unit_path="${SYSTEMD_ETC_DIR}/${service}" |
| fi |
| |
| if [ ! -f "$service_unit_path" ]; then |
| echo " Warning: Service unit file not found: ${service}" >&2 |
| continue |
| fi |
| |
| case "$service" in |
| *@.service) |
| echo " Template service detected, finding instances..." >&2 |
| instances=$(systemctl list-units --all --no-legend "${service%@.service}@*.service" 2>/dev/null | awk '{print $1}') |
| |
| if [ -z "$instances" ]; then |
| echo " No instances found" >&2 |
| continue |
| fi |
| ;; |
| *) |
| echo " Regular service detected" >&2 |
| # Treat regular service as a single instance |
| instances="$service" |
| ;; |
| esac |
| |
| # Process all services |
| for instance in $instances; do |
| echo " Processing instance: $instance" >&2 |
| done |
| |
| changes_made=1 |
| done |
| |
| # Reload systemd if any changes were made |
| if [ "$changes_made" -eq 1 ]; then |
| echo "Reloading systemd daemon..." >&2 |
| systemctl daemon-reload |
| echo "True-hitless initialization completed successfully" >&2 |
| else |
| echo "No services processed" >&2 |
| fi |