diff --git a/patroni/postgresql.py b/patroni/postgresql.py index f75324e7..b4e8ff94 100644 --- a/patroni/postgresql.py +++ b/patroni/postgresql.py @@ -485,19 +485,23 @@ recovery_target_timeline = 'latest' def save_configuration_files(self): """ - copy postgresql.conf to postgresql.conf.backup to preserve it in the WAL-e backup. - see http://comments.gmane.org/gmane.comp.db.postgresql.wal-e/239 + copy postgresql.conf to postgresql.conf.backup to be able to retrive configuration files + - originally stored as symlinks, those are normally skipped by pg_basebackup + - in case of WAL-E basebackup (see http://comments.gmane.org/gmane.comp.db.postgresql.wal-e/239) """ - for f in self.configuration_to_save: - shutil.copy(f, f + '.backup') + try: + for f in self.configuration_to_save: + os.path.isfile(f) and shutil.copy(f, f + '.backup') + except: + logger.exception('unable to create backup copies of configuration files') def restore_configuration_files(self): """ restore a previously saved postgresql.conf """ try: for f in self.configuration_to_save: - shutil.copy(f + '.backup', f) + not os.path.isfile(f) and os.path.isfile(f+'.backup') and shutil.copy(f + '.backup', f) except: - logger.exception('unable to restore configuration from WAL-E backup') + logger.exception('unable to restore configuration files from backup') def promote(self): if self.role == 'master': @@ -585,6 +589,7 @@ recovery_target_timeline = 'latest' raise PostgresException("Could not bootstrap master PostgreSQL") else: if self.sync_from_leader(current_leader): + self.restore_configuration_files() self.write_recovery_conf(current_leader) ret = self.start() return ret diff --git a/tests/test_postgresql.py b/tests/test_postgresql.py index 9a02ece6..ca60760f 100644 --- a/tests/test_postgresql.py +++ b/tests/test_postgresql.py @@ -19,6 +19,11 @@ from test_ha import false import subprocess +def is_file_raise_on_backup(*args, **kwargs): + if args[0].endswith('.backup'): + raise Exception("foo") + + class MockCursor: def __init__(self, connection): @@ -429,3 +434,15 @@ class TestPostgresql(unittest.TestCase): self.p.cleanup_archive_status() mock_unlink.assert_not_called() mock_remove.assert_not_called() + + @patch('os.path.isfile', MagicMock(return_value=True)) + @patch('shutil.copy', side_effect=Exception) + def test_save_configuration_files(self, mock_copy): + shutil.copy = mock_copy + self.p.save_configuration_files() + + @patch('os.path.isfile', MagicMock(side_effect=is_file_raise_on_backup)) + @patch('shutil.copy', side_effect=Exception) + def test_restore_configuration_files(self, mock_copy): + shutil.copy = mock_copy + self.p.restore_configuration_files()