# Sourced by managed-container; uses the shared OCF and parameter environment. OCF_RESKEY_service_user_default="david" OCF_RESKEY_service_name_default="postgres.service" OCF_RESKEY_container_name_default="postgres" OCF_RESKEY_pg_os_user_default="postgres" OCF_RESKEY_db_user_default="david" OCF_RESKEY_db_name_default="david" OCF_RESKEY_rejoin_source_host_default="" OCF_RESKEY_rejoin_source_port_default="5432" OCF_RESKEY_replication_user_default="replicator" OCF_RESKEY_replication_slot_default="" OCF_RESKEY_application_name_default="" OCF_RESKEY_rejoin_allow_basebackup_default="false" : "${OCF_RESKEY_service_user:=${OCF_RESKEY_service_user_default}}" : "${OCF_RESKEY_service_name:=${OCF_RESKEY_service_name_default}}" : "${OCF_RESKEY_container_name:=${OCF_RESKEY_container_name_default}}" : "${OCF_RESKEY_pg_os_user:=${OCF_RESKEY_pg_os_user_default}}" : "${OCF_RESKEY_db_user:=${OCF_RESKEY_db_user_default}}" : "${OCF_RESKEY_db_name:=${OCF_RESKEY_db_name_default}}" : "${OCF_RESKEY_rejoin_source_host:=${OCF_RESKEY_rejoin_source_host_default}}" : "${OCF_RESKEY_rejoin_source_port:=${OCF_RESKEY_rejoin_source_port_default}}" : "${OCF_RESKEY_replication_user:=${OCF_RESKEY_replication_user_default}}" : "${OCF_RESKEY_replication_slot:=${OCF_RESKEY_replication_slot_default}}" : "${OCF_RESKEY_application_name:=${OCF_RESKEY_application_name_default}}" : "${OCF_RESKEY_rejoin_allow_basebackup:=${OCF_RESKEY_rejoin_allow_basebackup_default}}" SERVICE_USER="${OCF_RESKEY_service_user}" SERVICE_NAME="${OCF_RESKEY_service_name}" CONTAINER_NAME="${OCF_RESKEY_container_name}" PG_OS_USER="${OCF_RESKEY_pg_os_user}" DB_USER="${OCF_RESKEY_db_user}" DB_NAME="${OCF_RESKEY_db_name}" REJOIN_SOURCE_HOST="${OCF_RESKEY_rejoin_source_host}" REJOIN_SOURCE_PORT="${OCF_RESKEY_rejoin_source_port}" REPLICATION_USER="${OCF_RESKEY_replication_user}" REPLICATION_SLOT="${OCF_RESKEY_replication_slot}" APPLICATION_NAME="${OCF_RESKEY_application_name}" REJOIN_ALLOW_BASEBACKUP="${OCF_RESKEY_rejoin_allow_basebackup}" if [ -z "${APPLICATION_NAME}" ]; then APPLICATION_NAME="$(hostname -s)" fi meta_data() { cat < 1.0 Manage an application inside a persistent rootless container. Version 0.4 implements role-aware monitoring, promotion, and demotion. The systemd user Quadlet owns the container lifecycle while pg_ctl owns the PostgreSQL lifecycle inside the container. Manage PostgreSQL independently inside a persistent container Linux user owning the rootless systemd/Podman service. Rootless service owner systemd user service generated by Quadlet. Quadlet service name Podman container containing PostgreSQL. Container name Operating-system user running PostgreSQL inside the container. PostgreSQL OS user PostgreSQL database user used for health queries. Database user PostgreSQL database used for health queries. Database name PostgreSQL primary host used as the source for rejoin operations. Rejoin source host PostgreSQL port on the rejoin source. Rejoin source port PostgreSQL role used for replication and pg_rewind. Replication user Physical replication slot used by this standby. Physical replication slot PostgreSQL replication application_name. Defaults to the local hostname. Replication application name Allow rejoin to fall back to pg_basebackup when pg_rewind cannot repair the local PostgreSQL data directory. The old PGDATA is preserved before replacement. This must only be enabled when the operator has established that this node may safely discard its divergent PostgreSQL history. Allow pg_basebackup rejoin fallback EOF_META } validate_all() { if ! id "${SERVICE_USER}" >/dev/null 2>&1; then ocf_exit_reason "Service user '${SERVICE_USER}' does not exist" return "${OCF_ERR_CONFIGURED}" fi for cmd in runuser systemctl podman getent; do if ! command -v "${cmd}" >/dev/null 2>&1; then ocf_exit_reason "Required command '${cmd}' is not installed" return "${OCF_ERR_INSTALLED}" fi done if [ ! -d "/run/user/$(service_uid)" ]; then ocf_exit_reason \ "Runtime directory /run/user/$(service_uid) does not exist" return "${OCF_ERR_GENERIC}" fi if ! mc_lifecycle_cat "${SERVICE_NAME}" >/dev/null 2>&1 then ocf_exit_reason \ "User service '${SERVICE_NAME}' cannot be found for ${SERVICE_USER}" return "${OCF_ERR_CONFIGURED}" fi local podman_error podman_error="$( mc_runtime_info 2>&1 >/dev/null )" local podman_rc=$? if [ "${podman_rc}" -ne 0 ]; then ocf_exit_reason \ "Rootless Podman failed for ${SERVICE_USER}: ${podman_error}" return "${OCF_ERR_GENERIC}" fi return "${OCF_SUCCESS}" } # Keep the original metadata function intact; advertise the added policy here. mc_promotion_metadata() { meta_data | sed '/<\/parameters>/i\ \ Maximum age in seconds of a verified streaming observation for disconnected promotion eligibility. Default 300; 0 disables disconnected eligibility. Requires fencing managed by Pacemaker. PostgreSQL restart requires fresh streaming verification.\ Disconnected standby observation lifetime\ \ ' } MC_APPLICATION_API=1 MC_APPLICATION_DIR="${MC_MODULE_DIR}/applications/postgresql" for MC_PG_MODULE in postgres auth replication notify promote demote rejoin; do if ! . "${MC_APPLICATION_DIR}/${MC_PG_MODULE}.sh"; then ocf_exit_reason "Unable to load resource-agent module ${MC_APPLICATION_DIR}/${MC_PG_MODULE}.sh" return "${OCF_ERR_CONFIGURED}" fi done unset MC_PG_MODULE mc_application_monitor() { managed_monitor } mc_application_standby_score() { mc_pg_standby_score } mc_application_validate() { validate_all } mc_application_metadata() { mc_promotion_metadata } mc_application_notify() { managed_notify } mc_application_action() { case "$1" in start|stop|promote|demote|rejoin) "managed_$1" ;; *) return "${OCF_ERR_UNIMPLEMENTED}" ;; esac }