Reset is_leader flag for every removal of leader key (#990)

This is the next improvement of #777
This commit is contained in:
Alexander Kukushkin
2019-03-12 22:10:46 +01:00
committed by GitHub
parent 13c88e8b7a
commit 92720882aa
2 changed files with 23 additions and 14 deletions
+17 -12
View File
@@ -419,7 +419,10 @@ class Ha(object):
time.sleep(2)
picked, allow_promote = self.state_handler.pick_synchronous_standby(self.cluster)
if allow_promote:
cluster = self.dcs.get_cluster()
try:
cluster = self.dcs.get_cluster()
except DCSError:
return logger.warning("Could not get cluster state from DCS during process_sync_replication()")
if cluster.sync.leader and cluster.sync.leader != self.state_handler.name:
logger.info("Synchronous replication key updated by someone else")
return
@@ -696,10 +699,14 @@ class Ha(object):
return self._is_healthiest_node(members.values())
def release_leader_key_voluntarily(self):
def _delete_leader(self):
self.set_is_leader(False)
self.dcs.delete_leader()
self.touch_member()
self.dcs.reset_cluster()
def release_leader_key_voluntarily(self):
self._delete_leader()
self.touch_member()
logger.info("Leader key released")
def demote(self, mode):
@@ -727,7 +734,8 @@ class Ha(object):
self.set_is_leader(False)
if mode_control['release']:
self.release_leader_key_voluntarily()
with self._async_executor:
self.release_leader_key_voluntarily()
time.sleep(2) # Give a time to somebody to take the leader lock
if mode_control['offline']:
node_to_follow, leader = None, None
@@ -875,8 +883,7 @@ class Ha(object):
if self.cluster.failover and self.cluster.failover.candidate == self.state_handler.name:
return 'waiting to become master after promote...'
self.dcs.delete_leader()
self.dcs.reset_cluster()
self._delete_leader()
return 'removed leader lock because postgres is not running as master'
if self.state_handler.is_leader() and self._leader_access_is_restricted:
@@ -1089,8 +1096,7 @@ class Ha(object):
self.watchdog.disable()
if self.has_lock():
self.state_handler.set_role('demoted')
self.dcs.delete_leader()
self.dcs.reset_cluster()
self._delete_leader()
return 'removed leader key after trying and failing to start postgres'
return 'failed to start postgres'
self._crash_recovery_executed = False
@@ -1256,16 +1262,15 @@ class Ha(object):
if not self.state_handler.is_healthy():
if self.is_paused():
if self.has_lock():
self.dcs.delete_leader()
self.dcs.reset_cluster()
self._delete_leader()
return 'removed leader lock because postgres is not running'
# Normally we don't start Postgres in a paused state. We make an exception for the demoted primary
# that needs to be started after it had been stopped by demote. When there is no need to call rewind
# the demote code follows through to starting Postgres right away, however, in the rewind case
# it returns from demote and reaches this point to start PostgreSQL again after rewind. In that
# case it makes no sense to continue to recover() unless rewind has finished successfully.
elif self.state_handler.rewind_failed or not self.state_handler.need_rewind \
or not self.state_handler.can_rewind_or_reinitialize_allowed:
elif self.state_handler.rewind_failed or not self.state_handler.rewind_executed and not \
(self.state_handler.need_rewind and self.state_handler.can_rewind_or_reinitialize_allowed):
return 'postgres is not running'
# try to start dead postgres
+6 -2
View File
@@ -864,11 +864,15 @@ class TestHa(unittest.TestCase):
self.ha.run_cycle()
self.assertEqual(self.ha.dcs.write_sync_state.call_count, 2)
# Test changing sync standby failed due to race
# Test updating sync standby key failed due to DCS being not accessible
self.ha.dcs.write_sync_state = Mock(return_value=True)
self.ha.dcs.get_cluster = Mock(side_effect=DCSError('foo'))
self.ha.run_cycle()
# Test changing sync standby failed due to race
self.ha.dcs.get_cluster = Mock(return_value=get_cluster_initialized_with_leader(sync=('somebodyelse', None)))
self.ha.run_cycle()
self.assertEqual(self.ha.dcs.write_sync_state.call_count, 1)
self.assertEqual(self.ha.dcs.write_sync_state.call_count, 2)
# Test sync set to '*' when synchronous_mode_strict is enabled
mock_set_sync.reset_mock()