Add PostgreSQL HA OCF agent modular baseline

This commit is contained in:
Lyncoln
2026-09-12 01:28:33 -04:00
commit 4a358ae0f6
30 changed files with 7119 additions and 0 deletions
+101
View File
@@ -0,0 +1,101 @@
# Refactor inventory and module plan
Prepared before implementation. The frozen reference is authoritative.
## Parameters and globals
| OCF parameter | Default | Runtime global |
| --- | --- | --- |
| `service_user` | `david` | `SERVICE_USER` |
| `service_name` | `postgres.service` | `SERVICE_NAME` |
| `container_name` | `postgres` | `CONTAINER_NAME` |
| `pg_os_user` | `postgres` | `PG_OS_USER` |
| `db_user` | `david` | `DB_USER` |
| `db_name` | `david` | `DB_NAME` |
| `rejoin_source_host` | `` | `REJOIN_SOURCE_HOST` |
| `rejoin_source_port` | `5432` | `REJOIN_SOURCE_PORT` |
| `replication_user` | `replicator` | `REPLICATION_USER` |
| `replication_slot` | `` | `REPLICATION_SLOT` |
| `application_name` | `` | `APPLICATION_NAME` |
| `rejoin_allow_basebackup` | `false` | `REJOIN_ALLOW_BASEBACKUP` |
`application_name` falls back to `hostname -s`. Each parameter has an OCF_RESKEY input and an OCF_RESKEY_*_default global. Other framework globals: OCF_ROOT, OCF_FUNCTIONS_DIR, OCF_RUNNING_PROMOTED (normalized from OCF_RUNNING_MASTER), OCF_SUCCESS, OCF_NOT_RUNNING, OCF_ERR_GENERIC, OCF_ERR_CONFIGURED, OCF_ERR_INSTALLED, OCF_ERR_UNIMPLEMENTED, OCF_RESOURCE_INSTANCE. The validate_all loop also assigns the existing nonlocal variable cmd.
Notification inputs: OCF_RESKEY_CRM_meta_notify_{type,operation,promote_uname,demote_uname,promoted_uname,unpromoted_uname}. State persists under /run/loxthelion; demote accepts matching pre-demote state aged 0–120 seconds.
Container inputs: PGDATA, POSTGRES_REPLICATION_PASSWORD, POSTGRES_REPLICATION_USER, POSTGRES_HA_SLOTS. Container command locals include BINDIR, blocks and the explicitly injected RA_PRIMARY_HOST, RA_PRIMARY_PORT, RA_REPLICATION_USER, RA_REPLICATION_SLOT, RA_APPLICATION_NAME. PGPASSWORD is exported only in the container authentication subprocess. The rootless wrapper sets HOME and XDG_RUNTIME_DIR for that subprocess.
## Actions
Dispatcher: start, stop, monitor (status alias), promote, demote, notify, rejoin, meta-data, validate-all. Start/promote/demote/rejoin call validate_all first. Metadata advertises eight actions and omits rejoin/status; preserve this exactly.
## Module ownership and dependencies
All modules are sourced once by the entrypoint before dispatch. common initializes original defaults. Source order: common, container, postgres, auth, replication, notify, promote, demote, rejoin. Functions resolve dependencies when invoked; common validation can therefore call container functions without a source cycle.
Initial extraction retains original function names and bodies to enable exact comparison, including existing unused service_home. Namespacing and recovery deduplication are deferred from this first mechanical extraction so it can serve as a verified modular baseline. No shell option, SQL, quoting, log, or error-handling cleanup is included.
### common.sh
- `meta_data` → external commands / OCF library only
- `validate_all` → `service_uid`, `as_service_user`
### container.sh
- `service_uid` → external commands / OCF library only
- `service_home` → external commands / OCF library only
- `as_service_user` → external commands / OCF library only
- `service_running` → `as_service_user`
- `container_running` → `as_service_user`
### postgres.sh
- `pg_command` → `as_service_user`
- `pgdata_path` → `pg_command`
- `pg_running` → `pg_command`
- `pg_ready` → `as_service_user`
- `pg_role` → `as_service_user`
- `pg_wal_receiver_status` → `as_service_user`
- `managed_monitor` → `service_running`, `container_running`, `pg_running`, `pg_ready`, `pg_role`
- `managed_start` → `as_service_user`, `service_running`, `container_running`, `pg_command`, `pg_running`, `managed_monitor`
- `managed_stop` → `as_service_user`, `service_running`, `container_running`, `pg_command`, `pg_running`
### auth.sh
- `pg_replication_exec` → `as_service_user`
- `ensure_rewind_privileges` → `pg_command`
### replication.sh
- `pg_remote_query` → `pg_replication_exec`
- `ensure_local_ha_slots` → `pg_command`
- `ensure_remote_slot` → `pg_replication_exec`
- `candidate_caught_up` → `pg_command`
- `candidate_is_standby` → `pg_replication_exec`
### notify.sh
- `demote_target` → external commands / OCF library only
- `managed_notify` → external commands / OCF library only
### promote.sh
- `managed_promote` → `pg_command`, `pg_role`, `managed_monitor`, `ensure_rewind_privileges`, `ensure_local_ha_slots`
### demote.sh
- `node_to_addr` → external commands / OCF library only
- `managed_demote` → `as_service_user`, `service_running`, `container_running`, `pg_command`, `pg_running`, `pg_role`, `pg_wal_receiver_status`, `managed_monitor`, `node_to_addr`, `candidate_caught_up`, `demote_target`, `ensure_remote_slot`, `candidate_is_standby`
### rejoin.sh
- `managed_rejoin` → `as_service_user`, `service_running`, `container_running`, `pg_command`, `pg_replication_exec`, `pgdata_path`, `pg_running`, `pg_role`, `pg_remote_query`, `pg_wal_receiver_status`, `ensure_remote_slot`
## Incremental implementation and validation
1. Extract verbatim functions to the modules above in a new refactored/ tree; preserve both reference files.
2. Keep original OCF initialization and dispatcher; add script-relative module loading with a configured-error failure if any module cannot load.
3. Compare every function body, original defaults and dispatcher against the reference; run bash -n on every shell file.
4. Compare real meta-data output and parsed XML; exercise validate-all and record environmental limitations.
5. Exercise isolated action scenarios using mocked external boundaries; do not operate the live cluster.
6. Report hashes, install commands, and the operator-run lab comparison sequence.