Bugfix. It wasn't possible to start the old cluster if all its members were shutdown.

Basically this is rollback to the original decision tree with the small exception:
1 - If leader is defined and it's not me - then slave would be started immidiately
with the correct recovery conf.
2 - If leader is defined in and it's my host, then it will start instance in
readonly (but without primary_conninfo in recovery.conf)
3 - And the third case - if the leader is not defined - it also will start
instance in readonly, without primary_conninfo.
After performing 2 or 3 it will perform usual decision tree.
This commit is contained in:
Alexander Kukushkin
2015-05-12 10:19:45 +02:00
parent be7677a1b8
commit 9dcbc75fd2
+25 -27
View File
@@ -45,65 +45,63 @@ class Ha:
def run_cycle(self):
try:
self.load_cluster_from_etcd()
if not self.state_handler.is_healthy():
has_lock = self.has_lock()
self.state_handler.write_recovery_conf(None if has_lock else self.cluster.leader)
self.state_handler.start()
if not has_lock:
return 'started as a secondary'
logging.info('started as readonly because i had the session lock')
self.load_cluster_from_etcd()
if self.is_unlocked():
if not self.state_handler.is_healthy():
return 'no action. not healthy enough to do anything.'
elif self.state_handler.is_healthiest_node(self.cluster.members):
if self.state_handler.is_healthiest_node(self.cluster.members):
if self.acquire_lock():
if not self.state_handler.is_leader():
self.state_handler.promote()
return "promoted self to leader by acquiring session lock"
return "acquired session lock as a leader"
return 'promoted self to leader by acquiring session lock'
return 'acquired session lock as a leader'
else:
self.load_cluster_from_etcd()
if self.state_handler.is_leader():
self.demote()
return "demoted self due after trying and failing to obtain lock"
return 'demoted self due after trying and failing to obtain lock'
else:
self.follow_the_leader()
return "following new leader after trying and failing to obtain lock"
return 'following new leader after trying and failing to obtain lock'
else:
self.load_cluster_from_etcd()
if self.state_handler.is_leader():
self.demote()
return "demoting self because i am not the healthiest node"
return 'demoting self because i am not the healthiest node'
else:
self.follow_the_leader()
return "following a different leader because i am not the healthiest node"
return 'following a different leader because i am not the healthiest node'
else:
if self.has_lock() and not self.state_handler.is_healthy():
self.state_handler.write_recovery_conf(None)
self.state_handler.start()
self.load_cluster_from_etcd()
if self.has_lock() and self.update_lock():
try:
if not self.state_handler.is_leader():
self.state_handler.promote()
return "promoted self to leader because i had the session lock"
return 'promoted self to leader because i had the session lock'
else:
return "no action. i am the leader with the lock"
return 'no action. i am the leader with the lock'
finally:
# create replication slots
self.state_handler.create_replication_slots([m.hostname for m in self.cluster.members])
else:
logger.info("does not have lock")
if not self.state_handler.is_healthy():
self.state_handler.write_recovery_conf(self.cluster.leader)
self.state_handler.start()
return 'starting as a secondary'
elif self.state_handler.is_leader():
logger.info('does not have lock')
if self.state_handler.is_leader():
self.demote()
return "demoting self because i do not have the lock and i was a leader"
return 'demoting self because i do not have the lock and i was a leader'
else:
self.follow_the_leader()
return "no action. i am a secondary and i am following a leader"
return 'no action. i am a secondary and i am following a leader'
except EtcdError:
logger.error("Error communicating with Etcd")
logger.error('Error communicating with Etcd')
except OperationalError:
logger.error("Error communicating with Postgresql. Will try again.")
logger.error('Error communicating with Postgresql. Will try again')
except HealthiestMemberError:
logger.error("failed to determine healthiest member fromt etcd")
logger.error('failed to determine healthiest member fromt etcd')
def run(self):
while True: