diff --git a/patroni/postgresql/__init__.py b/patroni/postgresql/__init__.py index 566494db..248c3a59 100644 --- a/patroni/postgresql/__init__.py +++ b/patroni/postgresql/__init__.py @@ -653,6 +653,15 @@ class Postgresql(object): return False return True + def get_guc_value(self, name): + cmd = [self.pgcommand('postgres'), self._data_dir, '-C', name] + try: + data = subprocess.check_output(cmd) + if data: + return data.decode('utf-8').strip() + except Exception as e: + logger.error('Failed to execute %s: %r', cmd, e) + def controldata(self): """ return the contents of pg_controldata, or non-True value if pg_controldata call failed """ # Don't try to call pg_controldata during backup restore diff --git a/patroni/postgresql/rewind.py b/patroni/postgresql/rewind.py index 87a3626b..268e6699 100644 --- a/patroni/postgresql/rewind.py +++ b/patroni/postgresql/rewind.py @@ -173,9 +173,13 @@ class Rewind(object): env['PGOPTIONS'] = '-c statement_timeout=0' dsn = self._postgresql.config.format_dsn(r, True) logger.info('running pg_rewind from %s', dsn) + + cmd = [self._postgresql.pgcommand('pg_rewind')] + if self._postgresql.major_version >= 130000 and self._postgresql.get_guc_value('restore_command'): + cmd.append('--restore-target-wal') + cmd.extend(['-D', self._postgresql.data_dir, '--source-server', dsn]) try: - return self._postgresql.cancellable.call([self._postgresql.pgcommand('pg_rewind'), '-D', - self._postgresql.data_dir, '--source-server', dsn], env=env) == 0 + return self._postgresql.cancellable.call(cmd, env=env) == 0 except OSError: return False diff --git a/tests/test_rewind.py b/tests/test_rewind.py index 20739903..272eb79a 100644 --- a/tests/test_rewind.py +++ b/tests/test_rewind.py @@ -35,13 +35,16 @@ class TestRewind(BaseTestPostgresql): self.p.config._config['use_pg_rewind'] = False self.assertFalse(self.r.can_rewind) + @patch.object(Postgresql, 'major_version', PropertyMock(return_value=130000)) @patch.object(CancellableSubprocess, 'call') def test_pg_rewind(self, mock_cancellable_subprocess_call): r = {'user': '', 'host': '', 'port': '', 'database': '', 'password': ''} mock_cancellable_subprocess_call.return_value = 0 - self.assertTrue(self.r.pg_rewind(r)) + with patch('subprocess.check_output', Mock(return_value=b'foo')): + self.assertTrue(self.r.pg_rewind(r)) mock_cancellable_subprocess_call.side_effect = OSError - self.assertFalse(self.r.pg_rewind(r)) + with patch('subprocess.check_output', Mock(side_effect=Exception)): + self.assertFalse(self.r.pg_rewind(r)) @patch.object(Rewind, 'can_rewind', PropertyMock(return_value=True)) def test__get_local_timeline_lsn(self):