Handle PostgreSQL self-restart demotion preflight

This commit is contained in:
Lyncoln
2026-09-18 09:43:35 -04:00
parent 1e72dda238
commit 06c106c57c
3 changed files with 175 additions and 0 deletions
+53
View File
@@ -137,3 +137,56 @@ assert result["reason"] == "successor_unreachable"
print("successor_unreachable rejected")
print("DEMOTE_DATABASE_FAILURE_TEST_PASS=1")
print()
print("===== SELF-RESTART DATABASE GATE =====")
plugin.monitor = lambda config, runtime_state: {
"ha": {"ocf_rc": plugin.OCF_RUNNING_PROMOTED},
"primary": {"current_wal_lsn": "14/1C07A920"},
}
self_restart_state = {
"postgresql": {
"notification": {
"type": "pre",
"operation": "demote",
"demote_uname": "david-prodesk",
"promote_uname": "david-prodesk",
"promoted_uname": "david-prodesk",
"unpromoted_uname": "david-eve",
"received_at": time.time(),
},
},
}
connect_called = False
def must_not_connect(**kwargs):
global connect_called
connect_called = True
raise AssertionError(
"self-restart demotion must not probe a remote successor"
)
plugin.psycopg2.connect = must_not_connect
result = plugin.demote_database(
config,
self_restart_state,
{},
)
assert result["ocf_rc"] == 0
assert result["ready"] is True
assert result["mutation"] is False
assert result["final_handoff_required"] is False
assert result["handoff_mode"] == "local_restart"
assert result["reason"] == "local_restart_demotion_ready"
assert result["successor_node"] == "david-prodesk"
assert result["checks"]["local_primary"] is True
assert result["checks"]["remote_handoff_required"] is False
assert connect_called is False
print("self_restart_database accepted")
print("remote_probe_skipped accepted")
+60
View File
@@ -124,3 +124,63 @@ result = plugin.demote_prepare(
assert result["ocf_rc"] == 1
assert result["reason"] == "successor_not_configured"
print("unconfigured_successor rejected")
print()
print("===== SELF-RESTART PREPARE =====")
self_restart_state = {
"postgresql": {
"notification": {
"type": "pre",
"operation": "demote",
"demote_uname": "david-eve",
"promote_uname": "david-eve",
"promoted_uname": "david-eve",
"unpromoted_uname": "david-prodesk david-macbookpro",
"received_at": time.time(),
},
},
}
result = plugin.demote_prepare(
{
"PACEMAKER_NODE_NAME": "david-eve",
"PG_REPLICATION_PEERS": (
"david-prodesk=192.168.1.4:5432,"
"david-eve=192.168.1.3:5432"
),
},
self_restart_state,
{},
)
assert result["ocf_rc"] == 0
assert result["ready"] is False
assert result["identity_validated"] is True
assert result["reason"] == "local_restart_checks_pending"
assert result["handoff_mode"] == "local_restart"
assert result["final_handoff_required"] is False
assert result["successor_node"] == "david-eve"
assert result["checks"]["self_successor"] is True
assert result["checks"]["local_currently_promoted"] is True
print("self_restart_prepare accepted")
self_restart_state["postgresql"]["notification"]["promoted_uname"] = ""
result = plugin.demote_prepare(
{
"PACEMAKER_NODE_NAME": "david-eve",
"PG_REPLICATION_PEERS": (
"david-prodesk=192.168.1.4:5432,"
"david-eve=192.168.1.3:5432"
),
},
self_restart_state,
{},
)
assert result["ocf_rc"] == 1
assert result["reason"] == "self_restart_not_current_primary"
print("false_self_restart rejected")