Add read-only PostgreSQL demotion preparation
This commit is contained in:
@@ -5,7 +5,8 @@
|
||||
"actions": [
|
||||
"monitor",
|
||||
"notify",
|
||||
"notify.target"
|
||||
"notify.target",
|
||||
"demote.prepare"
|
||||
],
|
||||
"required_config": [
|
||||
"PGHOST",
|
||||
|
||||
@@ -529,3 +529,114 @@ def notify_target(config, runtime_state, request_parameters):
|
||||
"node": node_name,
|
||||
"age_seconds": age,
|
||||
}
|
||||
|
||||
|
||||
def demote_prepare(config, runtime_state, request_parameters):
|
||||
"""
|
||||
Read-only demotion preparation.
|
||||
|
||||
Validates the latest Pacemaker demotion notification against this local
|
||||
daemon and reports the successor. PostgreSQL mutation remains outside this
|
||||
action until candidate and WAL checks are migrated.
|
||||
"""
|
||||
del request_parameters
|
||||
|
||||
node_name = str(
|
||||
config.get("PACEMAKER_NODE_NAME", "")
|
||||
).strip().lower()
|
||||
|
||||
if not node_name:
|
||||
raise ValueError(
|
||||
"PACEMAKER_NODE_NAME is required for demote.prepare"
|
||||
)
|
||||
|
||||
notification = _postgres_runtime_state(
|
||||
runtime_state
|
||||
).get("notification")
|
||||
|
||||
if not isinstance(notification, dict):
|
||||
return {
|
||||
"ocf_rc": 1,
|
||||
"ready": False,
|
||||
"reason": "notification_missing",
|
||||
"node": node_name,
|
||||
}
|
||||
|
||||
if notification.get("type") != "pre":
|
||||
return {
|
||||
"ocf_rc": 1,
|
||||
"ready": False,
|
||||
"reason": "notification_type_invalid",
|
||||
"node": node_name,
|
||||
}
|
||||
|
||||
if notification.get("operation") != "demote":
|
||||
return {
|
||||
"ocf_rc": 1,
|
||||
"ready": False,
|
||||
"reason": "notification_operation_invalid",
|
||||
"node": node_name,
|
||||
}
|
||||
|
||||
received_at = notification.get("received_at")
|
||||
|
||||
if not isinstance(received_at, (int, float)):
|
||||
return {
|
||||
"ocf_rc": 1,
|
||||
"ready": False,
|
||||
"reason": "notification_timestamp_invalid",
|
||||
"node": node_name,
|
||||
}
|
||||
|
||||
age = time.time() - received_at
|
||||
|
||||
if age < 0 or age > NOTIFY_TARGET_MAX_AGE_SECONDS:
|
||||
return {
|
||||
"ocf_rc": 1,
|
||||
"ready": False,
|
||||
"reason": "notification_stale",
|
||||
"age_seconds": age,
|
||||
"node": node_name,
|
||||
}
|
||||
|
||||
target_node = str(
|
||||
notification.get("demote_uname", "")
|
||||
).strip().lower()
|
||||
|
||||
successor_node = str(
|
||||
notification.get("promote_uname", "")
|
||||
).strip().lower()
|
||||
|
||||
if target_node != node_name:
|
||||
return {
|
||||
"ocf_rc": 1,
|
||||
"ready": False,
|
||||
"reason": "local_node_not_target",
|
||||
"node": node_name,
|
||||
"target_node": target_node,
|
||||
"successor_node": successor_node,
|
||||
}
|
||||
|
||||
if not successor_node:
|
||||
return {
|
||||
"ocf_rc": 1,
|
||||
"ready": False,
|
||||
"reason": "successor_missing",
|
||||
"node": node_name,
|
||||
}
|
||||
|
||||
return {
|
||||
"ocf_rc": 0,
|
||||
"ready": True,
|
||||
"mutation": False,
|
||||
"node": node_name,
|
||||
"target_node": target_node,
|
||||
"successor_node": successor_node,
|
||||
"age_seconds": age,
|
||||
"checks": {
|
||||
"notification": True,
|
||||
"local_target": True,
|
||||
"successor_selected": True,
|
||||
"postgresql_mutated": False,
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user