Validate demotion successor against peer map

This commit is contained in:
Lyncoln
2026-09-17 17:58:11 -04:00
parent 12a34710df
commit 10df464b00
2 changed files with 68 additions and 1 deletions
+33
View File
@@ -625,6 +625,36 @@ def demote_prepare(config, runtime_state, request_parameters):
"node": node_name, "node": node_name,
} }
try:
peers = parse_replication_peers(
config.get("PG_REPLICATION_PEERS", "")
)
except (TypeError, ValueError):
return {
"ocf_rc": 1,
"ready": False,
"reason": "peer_map_invalid",
"node": node_name,
"successor_node": successor_node,
}
successor_peer = next(
(
peer for peer in peers
if peer["name"].strip().lower() == successor_node
),
None,
)
if successor_peer is None:
return {
"ocf_rc": 1,
"ready": False,
"reason": "successor_not_configured",
"node": node_name,
"successor_node": successor_node,
}
return { return {
"ocf_rc": 0, "ocf_rc": 0,
"ready": False, "ready": False,
@@ -634,8 +664,11 @@ def demote_prepare(config, runtime_state, request_parameters):
"node": node_name, "node": node_name,
"target_node": target_node, "target_node": target_node,
"successor_node": successor_node, "successor_node": successor_node,
"successor_host": successor_peer["host"],
"successor_port": successor_peer["port"],
"age_seconds": age, "age_seconds": age,
"checks": { "checks": {
"peer_map": True,
"notification": True, "notification": True,
"local_target": True, "local_target": True,
"successor_selected": True, "successor_selected": True,
+35 -1
View File
@@ -37,7 +37,13 @@ runtime_state = {
} }
result = plugin.demote_prepare( result = plugin.demote_prepare(
{"PACEMAKER_NODE_NAME": "david-eve"}, {
"PACEMAKER_NODE_NAME": "david-eve",
"PG_REPLICATION_PEERS": (
"david-prodesk=192.168.1.4:5432,"
"david-eve=192.168.1.3:5432"
),
},
runtime_state, runtime_state,
{}, {},
) )
@@ -47,6 +53,9 @@ assert result["ready"] is False
assert result["identity_validated"] is True assert result["identity_validated"] is True
assert result["reason"] == "database_checks_pending" assert result["reason"] == "database_checks_pending"
assert result["checks"]["database_checks"] is False assert result["checks"]["database_checks"] is False
assert result["checks"]["peer_map"] is True
assert result["successor_host"] == "192.168.1.4"
assert result["successor_port"] == 5432
assert result["mutation"] is False assert result["mutation"] is False
assert result["successor_node"] == "david-prodesk" assert result["successor_node"] == "david-prodesk"
print("valid_prepare accepted") print("valid_prepare accepted")
@@ -90,3 +99,28 @@ print("missing_successor rejected")
print() print()
print("DEMOTE_PREPARE_TEST_PASS=1") print("DEMOTE_PREPARE_TEST_PASS=1")
result = plugin.demote_prepare(
{
"PACEMAKER_NODE_NAME": "david-eve",
"PG_REPLICATION_PEERS": (
"david-macbookpro=192.168.1.5:5432"
),
},
{
"postgresql": {
"notification": {
"type": "pre",
"operation": "demote",
"demote_uname": "david-eve",
"promote_uname": "david-prodesk",
"received_at": time.time(),
},
},
},
{},
)
assert result["ocf_rc"] == 1
assert result["reason"] == "successor_not_configured"
print("unconfigured_successor rejected")