Use create_replica_methods from standby_cluster for replica bootstrap (#981)

It might happen that the standby cluster is configured to be created and replay WAL files from the different source than when it is running not in standby mode.  This is necessary to avoid writing WAL files and backups into the old place after promotion.

The easiest way to achieve such behavior is passing RemoteMember object to `Postgresql.clone` method instead of the usual Member object.
This commit is contained in:
Alexander Kukushkin
2019-02-21 11:37:50 +01:00
committed by GitHub
parent c6e70a9910
commit e670122c80
2 changed files with 13 additions and 5 deletions
+11 -4
View File
@@ -206,6 +206,9 @@ class Ha(object):
return self.dcs.touch_member(data)
def clone(self, clone_member=None, msg='(without leader)'):
if self.is_standby_cluster() and not isinstance(clone_member, RemoteMember):
clone_member = self.get_remote_member(clone_member)
if self.state_handler.clone(clone_member):
logger.info('bootstrapped %s', msg)
cluster = self.dcs.get_cluster()
@@ -1341,7 +1344,7 @@ class Ha(object):
This usually happens on the master or if the node is running async action"""
self.dcs.event.set()
def get_remote_master(self):
def get_remote_member(self, member=None):
""" In case of standby cluster this will tel us from which remote
master to stream. Config can be both patroni config or
cluster.config.data
@@ -1349,12 +1352,16 @@ class Ha(object):
cluster_params = self.get_standby_cluster_config()
if cluster_params:
unique_name = 'remote_master:{}'.format(uuid.uuid1())
name = member.name if member else 'remote_master:{}'.format(uuid.uuid1())
data = {k: v for k, v in cluster_params.items() if k in RemoteMember.allowed_keys()}
data['no_replication_slot'] = 'primary_slot_name' not in cluster_params
conn_kwargs = {k: cluster_params[k] for k in ('host', 'port') if k in cluster_params}
conn_kwargs = member.conn_kwargs() if member else \
{k: cluster_params[k] for k in ('host', 'port') if k in cluster_params}
if conn_kwargs:
data['conn_kwargs'] = conn_kwargs
return RemoteMember(unique_name, data)
return RemoteMember(name, data)
def get_remote_master(self):
return self.get_remote_member()
+2 -1
View File
@@ -211,7 +211,8 @@ class TestHa(unittest.TestCase):
self.assertEqual(self.ha.run_cycle(), 'trying to bootstrap a new standby leader')
@patch.object(Cluster, 'get_clone_member',
Mock(return_value=Member(0, 'test', 1, {'api_url': 'http://127.0.0.1:8011/patroni'})))
Mock(return_value=Member(0, 'test', 1, {'api_url': 'http://127.0.0.1:8011/patroni',
'conn_url': 'postgres://127.0.0.1:5432/postgres'})))
@patch.object(Postgresql, 'create_replica', Mock(return_value=0))
def test_start_as_cascade_replica_in_standby_cluster(self):
self.p.data_directory_empty = true