def test_check_receivexlog_installed(self, command_mock):
        """
        Test for the check method of the StreamingWalArchiver class
        """
        backup_manager = build_backup_manager()
        backup_manager.server.postgres.server_txt_version = "9.2"
        command_mock.side_effect = CommandFailedException

        archiver = StreamingWalArchiver(backup_manager)
        result = archiver.get_remote_status()

        assert result == {
            "pg_receivexlog_installed": False,
            "pg_receivexlog_path": None,
            "pg_receivexlog_compatible": None,
            'pg_receivexlog_synchronous': None,
            "pg_receivexlog_version": None,
            "pg_receivexlog_supports_slots": None,
        }

        backup_manager.server.postgres.server_txt_version = "9.2"
        command_mock.side_effect = None
        command_mock.return_value.cmd = '/some/path/to/pg_receivexlog'
        command_mock.return_value.side_effect = CommandFailedException
        archiver.reset_remote_status()
        result = archiver.get_remote_status()

        assert result == {
            "pg_receivexlog_installed": True,
            "pg_receivexlog_path": "/some/path/to/pg_receivexlog",
            "pg_receivexlog_compatible": None,
            'pg_receivexlog_synchronous': None,
            "pg_receivexlog_version": None,
            "pg_receivexlog_supports_slots": None,
        }
Exemple #2
0
    def test_streamingwalarchiver_check_receivexlog_installed(
            self, command_mock, which_mock):
        """
        Test for the check method of the StreamingWalArchiver class
        """
        backup_manager = build_backup_manager()
        backup_manager.server.postgres.server_txt_version = "9.2"
        which_mock.return_value = None

        archiver = StreamingWalArchiver(backup_manager)
        result = archiver.get_remote_status()

        which_mock.assert_called_with('pg_receivexlog', ANY)
        assert result == {
            "pg_receivexlog_installed": False,
            "pg_receivexlog_path": None,
            "pg_receivexlog_compatible": None,
            "pg_receivexlog_version": None,
        }

        backup_manager.server.postgres.server_txt_version = "9.2"
        which_mock.return_value = '/some/path/to/pg_receivexlog'
        command_mock.return_value.side_effect = CommandFailedException
        result = archiver.get_remote_status()

        assert result == {
            "pg_receivexlog_installed": True,
            "pg_receivexlog_path": "/some/path/to/pg_receivexlog",
            "pg_receivexlog_compatible": None,
            "pg_receivexlog_version": None,
        }
Exemple #3
0
    def test_get_next_batch(self, from_file_mock, isfile_mock, glob_mock):
        """
        Test the FileWalArchiver.get_next_batch method
        """

        # WAL batch, with 000000010000000000000001 that is currently being
        # written
        glob_mock.return_value = ['000000010000000000000001']
        isfile_mock.return_value = True
        # This is an hack, instead of a WalFileInfo we use a simple string to
        # ease all the comparisons. The resulting string is the name enclosed
        # in colons. e.g. ":000000010000000000000001:"
        from_file_mock.side_effect = lambda wal_name, compression: (
            ':%s:' % wal_name)

        backup_manager = build_backup_manager(
            name='TestServer'
        )
        archiver = StreamingWalArchiver(backup_manager)
        backup_manager.server.archivers = [archiver]

        batch = archiver.get_next_batch()
        assert ['000000010000000000000001'] == batch.skip

        # WAL batch, with 000000010000000000000002 that is currently being
        # written and 000000010000000000000001 can be archived
        glob_mock.return_value = [
            '000000010000000000000001',
            '000000010000000000000002',
        ]
        batch = archiver.get_next_batch()
        assert [':000000010000000000000001:'] == batch
        assert ['000000010000000000000002'] == batch.skip

        # WAL batch, with two partial files.
        glob_mock.return_value = [
            '000000010000000000000001.partial',
            '000000010000000000000002.partial',
        ]
        batch = archiver.get_next_batch()
        assert ['000000010000000000000001.partial'] == batch.errors
        assert ['000000010000000000000002.partial'] == batch.skip

        # WAL batch with errors
        wrong_file_name = 'test_wrong_wal_file.2'
        glob_mock.return_value = ['test_wrong_wal_file.2']
        batch = archiver.get_next_batch()
        assert [wrong_file_name] == batch.errors
Exemple #4
0
    def test_when_streaming_connection_rejected(self, command_mock, which_mock):
        """
        Test the StreamingWalArchiver behaviour when the streaming
        connection is rejected by the PostgreSQL server and
        pg_receivexlog is installed.
        """

        # When the streaming connection is not available, the
        # server_txt_version property will have a None value.
        backup_manager = build_backup_manager()
        backup_manager.server.streaming.server_txt_version = None
        archiver = StreamingWalArchiver(backup_manager)
        which_mock.return_value = "/some/path/to/pg_receivexlog"
        command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.2"

        result = archiver.get_remote_status()
        assert result["pg_receivexlog_compatible"] is None
Exemple #5
0
    def test_when_streaming_connection_rejected(self, command_mock, which_mock):
        """
        Test the StreamingWalArchiver behaviour when the streaming
        connection is rejected by the PostgreSQL server and
        pg_receivexlog is installed.
        """

        # When the streaming connection is not available, the
        # server_txt_version property will have a None value.
        backup_manager = build_backup_manager()
        backup_manager.server.streaming.server_major_version = None
        archiver = StreamingWalArchiver(backup_manager)
        which_mock.return_value = "/some/path/to/pg_receivexlog"
        command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.2"

        result = archiver.get_remote_status()
        assert result["pg_receivexlog_compatible"] is None
    def test_get_next_batch(self, from_file_mock, isfile_mock, glob_mock,
                            caplog):
        """
        Test the FileWalArchiver.get_next_batch method
        """

        # WAL batch, with 000000010000000000000001 that is currently being
        # written
        glob_mock.return_value = ['000000010000000000000001']
        isfile_mock.return_value = True
        # This is an hack, instead of a WalFileInfo we use a simple string to
        # ease all the comparisons. The resulting string is the name enclosed
        # in colons. e.g. ":000000010000000000000001:"
        from_file_mock.side_effect = lambda wal_name, compression: (':%s:' %
                                                                    wal_name)

        backup_manager = build_backup_manager(name='TestServer')
        archiver = StreamingWalArchiver(backup_manager)
        backup_manager.server.archivers = [archiver]

        batch = archiver.get_next_batch()
        assert ['000000010000000000000001'] == batch.skip

        # WAL batch, with 000000010000000000000002 that is currently being
        # written and 000000010000000000000001 can be archived
        glob_mock.return_value = [
            '000000010000000000000001',
            '000000010000000000000002',
        ]
        batch = archiver.get_next_batch()
        assert [':000000010000000000000001:'] == batch
        assert ['000000010000000000000002'] == batch.skip

        # WAL batch, with two partial files.
        glob_mock.return_value = [
            '000000010000000000000001.partial',
            '000000010000000000000002.partial',
        ]
        batch = archiver.get_next_batch()
        assert [':000000010000000000000001.partial:'] == batch
        assert ['000000010000000000000002.partial'] == batch.skip
        assert ('Archiving partial files for server %s: '
                '000000010000000000000001.partial' %
                archiver.config.name) in caplog.text

        # WAL batch, with history files.
        glob_mock.return_value = [
            '00000001.history',
            '000000010000000000000002.partial',
        ]
        batch = archiver.get_next_batch()
        assert [':00000001.history:'] == batch
        assert ['000000010000000000000002.partial'] == batch.skip

        # WAL batch with errors
        wrong_file_name = 'test_wrong_wal_file.2'
        glob_mock.return_value = ['test_wrong_wal_file.2']
        batch = archiver.get_next_batch()
        assert [wrong_file_name] == batch.errors
Exemple #7
0
    def test_check(self, remote_mock, capsys):
        """
        Test management of check_postgres view output

        :param remote_mock: mock get_remote_status function
        :param capsys: retrieve output from consolle
        """
        # Create a backup_manager
        backup_manager = build_backup_manager()
        # Set up mock responses
        streaming = backup_manager.server.streaming
        streaming.server_txt_version = "9.5"
        # Instantiate a StreamingWalArchiver obj
        archiver = StreamingWalArchiver(backup_manager)
        # Prepare the output check strategy
        strategy = CheckOutputStrategy()
        # Case: correct configuration
        remote_mock.return_value = {
            "pg_receivexlog_installed": True,
            "pg_receivexlog_compatible": True,
            "pg_receivexlog_path": "fake/path",
        }
        # Expect out: all parameters: OK
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert out == "\tpg_receivexlog: OK\n" "\tpg_receivexlog compatible: OK\n"

        # Case: pg_receivexlog is not compatible
        remote_mock.return_value = {
            "pg_receivexlog_installed": True,
            "pg_receivexlog_compatible": False,
            "pg_receivexlog_path": "fake/path",
            "pg_receivexlog_version": "9.2",
        }
        # Expect out: some parameters: FAILED
        strategy = CheckOutputStrategy()
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert (
            out == "\tpg_receivexlog: OK\n"
            "\tpg_receivexlog compatible: FAILED "
            "(PostgreSQL version: 9.5, pg_receivexlog version: 9.2)\n"
        )
        # Case: pg_receivexlog returned error
        remote_mock.return_value = {
            "pg_receivexlog_installed": True,
            "pg_receivexlog_compatible": None,
            "pg_receivexlog_path": "fake/path",
            "pg_receivexlog_version": None,
        }
        # Expect out: all parameters: OK
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert (
            out == "\tpg_receivexlog: OK\n"
            "\tpg_receivexlog compatible: FAILED "
            "(PostgreSQL version: 9.5, pg_receivexlog version: None)\n"
        )
Exemple #8
0
    def test_check_receivexlog_installed(self, find_command):
        """
        Test for the check method of the StreamingWalArchiver class
        """
        backup_manager = build_backup_manager()
        find_command.side_effect = CommandFailedException

        archiver = StreamingWalArchiver(backup_manager)
        result = archiver.get_remote_status()

        assert result == {
            "pg_receivexlog_installed": False,
            "pg_receivexlog_path": None,
            "pg_receivexlog_compatible": None,
            "pg_receivexlog_synchronous": None,
            "pg_receivexlog_version": None,
            "pg_receivexlog_supports_slots": None,
        }

        backup_manager.server.streaming.server_major_version = "9.2"
        find_command.side_effect = None
        find_command.return_value.cmd = "/some/path/to/pg_receivexlog"
        find_command.return_value.out = ""
        archiver.reset_remote_status()
        result = archiver.get_remote_status()

        assert result == {
            "pg_receivexlog_installed": True,
            "pg_receivexlog_path": "/some/path/to/pg_receivexlog",
            "pg_receivexlog_compatible": None,
            "pg_receivexlog_synchronous": None,
            "pg_receivexlog_version": None,
            "pg_receivexlog_supports_slots": None,
        }
Exemple #9
0
    def test_is_synchronous(self):
        backup_manager = build_backup_manager(name="TestServer")
        archiver = StreamingWalArchiver(backup_manager)

        # 'barman_receive_wal' is not in the list of synchronous standby
        # names, so we expect is_synchronous to be false
        backup_manager.server.postgres.get_remote_status.return_value = {
            "synchronous_standby_names": ["a", "b", "c"]
        }
        assert not archiver._is_synchronous()

        # 'barman_receive_wal' is in the list of synchronous standby
        # names, so we expect is_synchronous to be true
        backup_manager.server.postgres.get_remote_status.return_value = {
            "synchronous_standby_names": ["a", "barman_receive_wal"]
        }
        assert archiver._is_synchronous()

        # '*' is in the list of synchronous standby names, so we expect
        # is_synchronous to be true even if 'barman_receive_wal' is not
        # explicitly referenced
        backup_manager.server.postgres.get_remote_status.return_value = {
            "synchronous_standby_names": ["a", "b", "*"]
        }
        assert archiver._is_synchronous()

        # There is only a '*' in the list of synchronous standby names,
        # so we expect every name to match
        backup_manager.server.postgres.get_remote_status.return_value = {
            "synchronous_standby_names": ["*"]
        }
        assert archiver._is_synchronous()
    def test_check_receivexlog_installed(self, command_mock):
        """
        Test for the check method of the StreamingWalArchiver class
        """
        backup_manager = build_backup_manager()
        backup_manager.server.postgres.server_txt_version = "9.2"
        command_mock.side_effect = CommandFailedException

        archiver = StreamingWalArchiver(backup_manager)
        result = archiver.get_remote_status()

        assert result == {
            "pg_receivexlog_installed": False,
            "pg_receivexlog_path": None,
            "pg_receivexlog_compatible": None,
            'pg_receivexlog_synchronous': None,
            "pg_receivexlog_version": None,
            "pg_receivexlog_supports_slots": None,
        }

        backup_manager.server.postgres.server_txt_version = "9.2"
        command_mock.side_effect = None
        command_mock.return_value.cmd = '/some/path/to/pg_receivexlog'
        command_mock.return_value.side_effect = CommandFailedException
        archiver.reset_remote_status()
        result = archiver.get_remote_status()

        assert result == {
            "pg_receivexlog_installed": True,
            "pg_receivexlog_path": "/some/path/to/pg_receivexlog",
            "pg_receivexlog_compatible": None,
            'pg_receivexlog_synchronous': None,
            "pg_receivexlog_version": None,
            "pg_receivexlog_supports_slots": None,
        }
Exemple #11
0
    def test_streamingwalarchiver_check_receivexlog_is_compatible(
            self, command_mock, which_mock):
        """
        Test for the compatibility checks between versions of pg_receivexlog
        and PostgreSQL
        """
        # pg_receivexlog 9.2 is compatible only with PostgreSQL 9.2
        backup_manager = build_backup_manager()
        backup_manager.server.streaming.server_txt_version = "9.2.0"
        archiver = StreamingWalArchiver(backup_manager)
        which_mock.return_value = '/some/path/to/pg_receivexlog'

        command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.2"
        result = archiver.get_remote_status()
        assert result["pg_receivexlog_compatible"] is True

        command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.5"
        result = archiver.get_remote_status()
        assert result["pg_receivexlog_compatible"] is False

        # Every pg_receivexlog is compatible with older PostgreSQL
        backup_manager.server.streaming.server_txt_version = "9.3.0"
        command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.5"
        result = archiver.get_remote_status()
        assert result["pg_receivexlog_compatible"] is True

        backup_manager.server.streaming.server_txt_version = "9.5.0"
        command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.3"
        result = archiver.get_remote_status()
        assert result["pg_receivexlog_compatible"] is False

        # Check for minor versions
        backup_manager.server.streaming.server_txt_version = "9.4.5"
        command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.4.4"
        result = archiver.get_remote_status()
        assert result["pg_receivexlog_compatible"] is True
Exemple #12
0
    def test_check(self, remote_mock, capsys):
        """
        Test management of check_postgres view output

        :param remote_mock: mock get_remote_status function
        :param capsys: retrieve output from consolle
        """
        # Create a backup_manager
        backup_manager = build_backup_manager()
        # Set up mock responses
        streaming = backup_manager.server.streaming
        streaming.server_txt_version = '9.5'
        # Instantiate a StreamingWalArchiver obj
        archiver = StreamingWalArchiver(backup_manager)
        # Prepare the output check strategy
        strategy = CheckOutputStrategy()
        # Case: correct configuration
        remote_mock.return_value = {
            'pg_receivexlog_installed': True,
            'pg_receivexlog_compatible': True,
            'pg_receivexlog_path': 'fake/path',
        }
        # Expect out: all parameters: OK
        backup_manager.server.process_manager.list.return_value = []
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert out == \
            "\tpg_receivexlog: OK\n" \
            "\tpg_receivexlog compatible: OK\n" \
            "\treceive-wal running: FAILED " \
            "(See the Barman log file for more details)\n"

        # Case: pg_receivexlog is not compatible
        remote_mock.return_value = {
            'pg_receivexlog_installed': True,
            'pg_receivexlog_compatible': False,
            'pg_receivexlog_path': 'fake/path',
            'pg_receivexlog_version': '9.2',
        }
        # Expect out: some parameters: FAILED
        strategy = CheckOutputStrategy()
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert out == \
            "\tpg_receivexlog: OK\n" \
            "\tpg_receivexlog compatible: FAILED " \
            "(PostgreSQL version: 9.5, pg_receivexlog version: 9.2)\n" \
            "\treceive-wal running: FAILED " \
            "(See the Barman log file for more details)\n"
        # Case: pg_receivexlog returned error
        remote_mock.return_value = {
            'pg_receivexlog_installed': True,
            'pg_receivexlog_compatible': None,
            'pg_receivexlog_path': 'fake/path',
            'pg_receivexlog_version': None,
        }
        # Expect out: all parameters: OK
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert out == \
            "\tpg_receivexlog: OK\n" \
            "\tpg_receivexlog compatible: FAILED " \
            "(PostgreSQL version: 9.5, pg_receivexlog version: None)\n" \
            "\treceive-wal running: FAILED " \
            "(See the Barman log file for more details)\n"

        # Case: receive-wal running
        backup_manager.server.process_manager.list.return_value = [
            ProcessInfo(pid=1,
                        server_name=backup_manager.config.name,
                        task="receive-wal")
        ]
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert out == \
            "\tpg_receivexlog: OK\n" \
            "\tpg_receivexlog compatible: FAILED " \
            "(PostgreSQL version: 9.5, pg_receivexlog version: None)\n" \
            "\treceive-wal running: OK\n"
Exemple #13
0
    def test_receive_wal(self, receivexlog_mock, remote_mock, tmpdir):
        backup_manager = build_backup_manager(
            main_conf={"backup_directory": tmpdir},
        )
        streaming_mock = backup_manager.server.streaming
        streaming_mock.server_txt_version = "9.4.0"
        streaming_mock.get_connection_string.return_value = (
            "host=pg01.nowhere user=postgres port=5432 "
            "application_name=barman_receive_wal"
        )
        streaming_mock.get_remote_status.return_value = {
            "streaming_supported": True,
            "timeline": 1,
        }
        postgres_mock = backup_manager.server.postgres
        replication_slot_status = MagicMock(restart_lsn="F/A12D687", active=False)
        postgres_mock.get_remote_status.return_value = {
            "current_xlog": "000000010000000F0000000A",
            "current_lsn": "F/A12D687",
            "replication_slot": replication_slot_status,
            "xlog_segment_size": 16777216,
        }
        backup_manager.server.streaming.conn_parameters = {
            "host": "pg01.nowhere",
            "user": "******",
            "port": "5432",
        }
        streaming_dir = tmpdir.join("streaming")
        streaming_dir.ensure(dir=True)
        # Test: normal run
        archiver = StreamingWalArchiver(backup_manager)
        archiver.server.streaming.server_version = 90400
        remote_mock.return_value = {
            "pg_receivexlog_installed": True,
            "pg_receivexlog_compatible": True,
            "pg_receivexlog_synchronous": None,
            "pg_receivexlog_path": "fake/path",
            "pg_receivexlog_supports_slots": True,
            "pg_receivexlog_version": "9.4",
        }

        # Test: execute a reset request
        partial = streaming_dir.join("000000010000000100000001.partial")
        partial.ensure()
        archiver.receive_wal(reset=True)
        assert not partial.check()
        assert streaming_dir.join("000000010000000F0000000A.partial").check()

        archiver.receive_wal(reset=False)
        receivexlog_mock.assert_called_once_with(
            app_name="barman_receive_wal",
            synchronous=None,
            connection=ANY,
            destination=streaming_dir.strpath,
            err_handler=ANY,
            out_handler=ANY,
            path=ANY,
            slot_name=None,
            command="fake/path",
            version="9.4",
        )
        receivexlog_mock.return_value.execute.assert_called_once_with()

        # Test: pg_receivexlog from 9.2
        receivexlog_mock.reset_mock()
        remote_mock.return_value = {
            "pg_receivexlog_installed": True,
            "pg_receivexlog_compatible": True,
            "pg_receivexlog_synchronous": False,
            "pg_receivexlog_path": "fake/path",
            "pg_receivexlog_supports_slots": False,
            "pg_receivexlog_version": "9.2",
        }
        archiver.receive_wal(reset=False)
        receivexlog_mock.assert_called_once_with(
            app_name="barman_receive_wal",
            synchronous=False,
            connection=ANY,
            destination=streaming_dir.strpath,
            err_handler=ANY,
            out_handler=ANY,
            path=ANY,
            command="fake/path",
            slot_name=None,
            version="9.2",
        )
        receivexlog_mock.return_value.execute.assert_called_once_with()

        # Test: incompatible pg_receivexlog
        with pytest.raises(ArchiverFailure):
            remote_mock.return_value = {
                "pg_receivexlog_installed": True,
                "pg_receivexlog_compatible": False,
                "pg_receivexlog_supports_slots": False,
                "pg_receivexlog_synchronous": False,
                "pg_receivexlog_path": "fake/path",
            }
            archiver.receive_wal()

        # Test: missing pg_receivexlog
        with pytest.raises(ArchiverFailure):
            remote_mock.return_value = {
                "pg_receivexlog_installed": False,
                "pg_receivexlog_compatible": True,
                "pg_receivexlog_supports_slots": False,
                "pg_receivexlog_synchronous": False,
                "pg_receivexlog_path": "fake/path",
            }
            archiver.receive_wal()
        # Test: impossible to connect with streaming protocol
        with pytest.raises(ArchiverFailure):
            backup_manager.server.streaming.get_remote_status.return_value = {
                "streaming_supported": None
            }
            remote_mock.return_value = {
                "pg_receivexlog_installed": True,
                "pg_receivexlog_supports_slots": False,
                "pg_receivexlog_compatible": True,
                "pg_receivexlog_synchronous": False,
                "pg_receivexlog_path": "fake/path",
            }
            archiver.receive_wal()
        # Test: PostgreSQL too old
        with pytest.raises(ArchiverFailure):
            backup_manager.server.streaming.get_remote_status.return_value = {
                "streaming_supported": False
            }
            remote_mock.return_value = {
                "pg_receivexlog_installed": True,
                "pg_receivexlog_compatible": True,
                "pg_receivexlog_synchronous": False,
                "pg_receivexlog_path": "fake/path",
            }
            archiver.receive_wal()
        # Test: general failure executing pg_receivexlog
        with pytest.raises(ArchiverFailure):
            remote_mock.return_value = {
                "pg_receivexlog_installed": True,
                "pg_receivexlog_compatible": True,
                "pg_receivexlog_synchronous": False,
                "pg_receivexlog_path": "fake/path",
            }
            receivexlog_mock.return_value.execute.side_effect = CommandFailedException
            archiver.receive_wal()
Exemple #14
0
    def test_check_receivexlog_is_compatible(self, command_mock, which_mock):
        """
        Test for the compatibility checks between versions of pg_receivexlog
        and PostgreSQL
        """
        # pg_receivexlog 9.2 is compatible only with PostgreSQL 9.2
        backup_manager = build_backup_manager()
        backup_manager.server.streaming.server_major_version = "9.2"
        archiver = StreamingWalArchiver(backup_manager)
        which_mock.return_value = "/some/path/to/pg_receivexlog"

        command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.2.1"
        result = archiver.get_remote_status()
        assert result["pg_receivexlog_compatible"] is True

        command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.5.3"
        archiver.reset_remote_status()
        result = archiver.get_remote_status()
        assert result["pg_receivexlog_compatible"] is False

        # Every pg_receivexlog is compatible with older PostgreSQL
        backup_manager.server.streaming.server_major_version = "9.3"
        command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.5.3"
        archiver.reset_remote_status()
        result = archiver.get_remote_status()
        assert result["pg_receivexlog_compatible"] is True

        backup_manager.server.streaming.server_major_version = "9.5"
        command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.3.0"
        archiver.reset_remote_status()
        result = archiver.get_remote_status()
        assert result["pg_receivexlog_compatible"] is False

        # Check for minor versions
        backup_manager.server.streaming.server_major_version = "9.4"
        command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.4.4"
        archiver.reset_remote_status()
        result = archiver.get_remote_status()
        assert result["pg_receivexlog_compatible"] is True
        assert result["pg_receivexlog_synchronous"] is False
Exemple #15
0
 def test_init(self):
     """
     Basic init test for the StreamingWalArchiver class
     """
     backup_manager = build_backup_manager()
     StreamingWalArchiver(backup_manager)
Exemple #16
0
    def test_receive_wal(self, receivexlog_mock, remote_mock):
        backup_manager = build_backup_manager()
        backup_manager.server.streaming.server_txt_version = "9.4.0"
        backup_manager.server.streaming.get_remote_status.return_value = {"streaming_supported": True}

        # Test: normal run
        archiver = StreamingWalArchiver(backup_manager)
        remote_mock.return_value = {
            "pg_receivexlog_installed": True,
            "pg_receivexlog_compatible": True,
            "pg_receivexlog_path": "fake/path",
        }
        archiver.receive_wal()
        receivexlog_mock.assert_called_once_with(
            "fake/path", "host=pg01.nowhere user=postgres port=5432", "/some/barman/home/main/streaming"
        )
        receivexlog_mock.return_value.execute.assert_called_once_with()

        # Test: incompatible pg_receivexlog
        with pytest.raises(ArchiverFailure):
            remote_mock.return_value = {
                "pg_receivexlog_installed": True,
                "pg_receivexlog_compatible": False,
                "pg_receivexlog_path": "fake/path",
            }
            archiver.receive_wal()

        # Test: missing pg_receivexlog
        with pytest.raises(ArchiverFailure):
            remote_mock.return_value = {
                "pg_receivexlog_installed": False,
                "pg_receivexlog_compatible": True,
                "pg_receivexlog_path": "fake/path",
            }
            archiver.receive_wal()
        # Test: impossible to connect with streaming protocol
        with pytest.raises(ArchiverFailure):
            backup_manager.server.streaming.get_remote_status.return_value = {"streaming_supported": None}
            remote_mock.return_value = {
                "pg_receivexlog_installed": True,
                "pg_receivexlog_compatible": True,
                "pg_receivexlog_path": "fake/path",
            }
            archiver.receive_wal()
        # Test: PostgreSQL too old
        with pytest.raises(ArchiverFailure):
            backup_manager.server.streaming.get_remote_status.return_value = {"streaming_supported": False}
            remote_mock.return_value = {
                "pg_receivexlog_installed": True,
                "pg_receivexlog_compatible": True,
                "pg_receivexlog_path": "fake/path",
            }
            archiver.receive_wal()
        # Test: general failure executing pg_receivexlog
        with pytest.raises(ArchiverFailure):
            remote_mock.return_value = {
                "pg_receivexlog_installed": True,
                "pg_receivexlog_compatible": True,
                "pg_receivexlog_path": "fake/path",
            }
            receivexlog_mock.return_value.execute.side_effect = CommandFailedException
            archiver.receive_wal()
Exemple #17
0
    def test_check(self, remote_mock, capsys):
        """
        Test management of check_postgres view output

        :param remote_mock: mock get_remote_status function
        :param capsys: retrieve output from consolle
        """
        # Create a backup_manager
        backup_manager = build_backup_manager()
        # Set up mock responses
        streaming = backup_manager.server.streaming
        streaming.server_txt_version = "9.5"
        # Instantiate a StreamingWalArchiver obj
        archiver = StreamingWalArchiver(backup_manager)
        # Prepare the output check strategy
        strategy = CheckOutputStrategy()
        # Case: correct configuration
        remote_mock.return_value = {
            "pg_receivexlog_installed": True,
            "pg_receivexlog_compatible": True,
            "pg_receivexlog_path": "fake/path",
            "incoming_wals_count": 0,
        }
        # Expect out: all parameters: OK
        backup_manager.server.process_manager.list.return_value = []
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert (
            out == "\tpg_receivexlog: OK\n"
            "\tpg_receivexlog compatible: OK\n"
            "\treceive-wal running: FAILED "
            "(See the Barman log file for more details)\n"
        )

        # Case: pg_receivexlog is not compatible
        remote_mock.return_value = {
            "pg_receivexlog_installed": True,
            "pg_receivexlog_compatible": False,
            "pg_receivexlog_path": "fake/path",
            "pg_receivexlog_version": "9.2",
            "incoming_wals_count": 0,
        }
        # Expect out: some parameters: FAILED
        strategy = CheckOutputStrategy()
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert (
            out == "\tpg_receivexlog: OK\n"
            "\tpg_receivexlog compatible: FAILED "
            "(PostgreSQL version: 9.5, pg_receivexlog version: 9.2)\n"
            "\treceive-wal running: FAILED "
            "(See the Barman log file for more details)\n"
        )
        # Case: pg_receivexlog returned error
        remote_mock.return_value = {
            "pg_receivexlog_installed": True,
            "pg_receivexlog_compatible": None,
            "pg_receivexlog_path": "fake/path",
            "pg_receivexlog_version": None,
            "incoming_wals_count": 0,
        }
        # Expect out: all parameters: OK
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert (
            out == "\tpg_receivexlog: OK\n"
            "\tpg_receivexlog compatible: FAILED "
            "(PostgreSQL version: 9.5, pg_receivexlog version: None)\n"
            "\treceive-wal running: FAILED "
            "(See the Barman log file for more details)\n"
        )

        # Case: receive-wal running
        backup_manager.server.process_manager.list.return_value = [
            ProcessInfo(
                pid=1, server_name=backup_manager.config.name, task="receive-wal"
            )
        ]
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert (
            out == "\tpg_receivexlog: OK\n"
            "\tpg_receivexlog compatible: FAILED "
            "(PostgreSQL version: 9.5, pg_receivexlog version: None)\n"
            "\treceive-wal running: OK\n"
        )

        # Case: streaming connection not configured
        backup_manager.server.streaming = None
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert (
            out == "\tpg_receivexlog: OK\n"
            "\tpg_receivexlog compatible: FAILED "
            "(PostgreSQL version: Unknown, pg_receivexlog version: None)\n"
            "\treceive-wal running: OK\n"
        )
        # Case: too many wal files in the incoming queue
        archiver.config.max_incoming_wals_queue = 10
        remote_mock.return_value = {
            "pg_receivexlog_installed": True,
            "pg_receivexlog_compatible": None,
            "pg_receivexlog_path": "fake/path",
            "pg_receivexlog_version": None,
            "incoming_wals_count": 20,
        }
        # Expect out: the wals incoming queue is too big
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert (
            out == "\tpg_receivexlog: OK\n"
            "\tpg_receivexlog compatible: FAILED "
            "(PostgreSQL version: Unknown, pg_receivexlog version: None)\n"
            "\treceive-wal running: OK\n"
        )
Exemple #18
0
    def test_receive_wal(self, receivexlog_mock, remote_mock, tmpdir):
        backup_manager = build_backup_manager(
            main_conf={
                'backup_directory': tmpdir
            },
        )
        backup_manager.server.streaming.server_txt_version = "9.4.0"
        backup_manager.server.streaming.get_remote_status.return_value = {
            "streaming_supported": True
        }
        backup_manager.server.streaming.conn_parameters = {
            'host': 'pg01.nowhere',
            'user': '******',
            'port': '5432',
        }
        streaming_dir = tmpdir.join('streaming')
        streaming_dir.ensure(dir=True)
        # Test: normal run
        archiver = StreamingWalArchiver(backup_manager)
        remote_mock.return_value = {
            'pg_receivexlog_installed': True,
            'pg_receivexlog_compatible': True,
            'pg_receivexlog_path': 'fake/path',
            'pg_receivexlog_version': '9.4',
        }

        # Test: execute a reset request
        partial = streaming_dir.join('test.partial')
        partial.ensure()
        archiver.receive_wal(reset=True)
        assert not partial.check()

        archiver.receive_wal(reset=False)
        receivexlog_mock.assert_called_once_with(
            'fake/path',
            conn_string='host=pg01.nowhere user=postgres port=5432 '
                        'application_name=barman_receive_wal',
            dest=streaming_dir.strpath,
            out_handler=ANY,
            err_handler=ANY,
        )
        receivexlog_mock.return_value.execute.assert_called_once_with()

        # Test: pg_receivexlog from 9.2
        receivexlog_mock.reset_mock()
        remote_mock.return_value = {
            'pg_receivexlog_installed': True,
            'pg_receivexlog_compatible': True,
            'pg_receivexlog_path': 'fake/path',
            'pg_receivexlog_version': '9.2',
        }
        archiver.receive_wal(reset=False)
        receivexlog_mock.assert_called_once_with(
            'fake/path',
            host='pg01.nowhere',
            user='******',
            port='5432',
            dest=streaming_dir.strpath,
            out_handler=ANY,
            err_handler=ANY,
        )
        receivexlog_mock.return_value.execute.assert_called_once_with()

        # Test: incompatible pg_receivexlog
        with pytest.raises(ArchiverFailure):
            remote_mock.return_value = {
                'pg_receivexlog_installed': True,
                'pg_receivexlog_compatible': False,
                'pg_receivexlog_path': 'fake/path'
            }
            archiver.receive_wal()

        # Test: missing pg_receivexlog
        with pytest.raises(ArchiverFailure):
            remote_mock.return_value = {
                'pg_receivexlog_installed': False,
                'pg_receivexlog_compatible': True,
                'pg_receivexlog_path': 'fake/path'
            }
            archiver.receive_wal()
        # Test: impossible to connect with streaming protocol
        with pytest.raises(ArchiverFailure):
            backup_manager.server.streaming.get_remote_status.return_value = {
                'streaming_supported': None
            }
            remote_mock.return_value = {
                'pg_receivexlog_installed': True,
                'pg_receivexlog_compatible': True,
                'pg_receivexlog_path': 'fake/path'
            }
            archiver.receive_wal()
        # Test: PostgreSQL too old
        with pytest.raises(ArchiverFailure):
            backup_manager.server.streaming.get_remote_status.return_value = {
                'streaming_supported': False
            }
            remote_mock.return_value = {
                'pg_receivexlog_installed': True,
                'pg_receivexlog_compatible': True,
                'pg_receivexlog_path': 'fake/path'
            }
            archiver.receive_wal()
        # Test: general failure executing pg_receivexlog
        with pytest.raises(ArchiverFailure):
            remote_mock.return_value = {
                'pg_receivexlog_installed': True,
                'pg_receivexlog_compatible': True,
                'pg_receivexlog_path': 'fake/path'
            }
            receivexlog_mock.return_value.execute.side_effect = \
                CommandFailedException
            archiver.receive_wal()
Exemple #19
0
    def test_receive_wal(self, receivexlog_mock, remote_mock, tmpdir):
        backup_manager = build_backup_manager(
            main_conf={
                'backup_directory': tmpdir
            },
        )
        streaming_mock = backup_manager.server.streaming
        streaming_mock.server_txt_version = "9.4.0"
        streaming_mock.get_connection_string.return_value = (
            'host=pg01.nowhere user=postgres port=5432 '
            'application_name=barman_receive_wal')
        streaming_mock.get_remote_status.return_value = {
            "streaming_supported": True
        }
        backup_manager.server.streaming.conn_parameters = {
            'host': 'pg01.nowhere',
            'user': '******',
            'port': '5432',
        }
        streaming_dir = tmpdir.join('streaming')
        streaming_dir.ensure(dir=True)
        # Test: normal run
        archiver = StreamingWalArchiver(backup_manager)
        archiver.server.streaming.server_version = 90400
        remote_mock.return_value = {
            'pg_receivexlog_installed': True,
            'pg_receivexlog_compatible': True,
            'pg_receivexlog_synchronous': None,
            'pg_receivexlog_path': 'fake/path',
            'pg_receivexlog_supports_slots': True,
            'pg_receivexlog_version': '9.4',
        }

        # Test: execute a reset request
        partial = streaming_dir.join('test.partial')
        partial.ensure()
        archiver.receive_wal(reset=True)
        assert not partial.check()

        archiver.receive_wal(reset=False)
        receivexlog_mock.assert_called_once_with(
            app_name='barman_receive_wal',
            synchronous=None,
            connection=ANY,
            destination=streaming_dir.strpath,
            err_handler=ANY,
            out_handler=ANY,
            path=ANY,
            slot_name=None,
            command='fake/path',
            version='9.4')
        receivexlog_mock.return_value.execute.assert_called_once_with()

        # Test: pg_receivexlog from 9.2
        receivexlog_mock.reset_mock()
        remote_mock.return_value = {
            'pg_receivexlog_installed': True,
            'pg_receivexlog_compatible': True,
            'pg_receivexlog_synchronous': False,
            'pg_receivexlog_path': 'fake/path',
            'pg_receivexlog_supports_slots': False,
            'pg_receivexlog_version': '9.2',
        }
        archiver.receive_wal(reset=False)
        receivexlog_mock.assert_called_once_with(
            app_name='barman_receive_wal',
            synchronous=False,
            connection=ANY,
            destination=streaming_dir.strpath,
            err_handler=ANY,
            out_handler=ANY,
            path=ANY,
            command='fake/path',
            slot_name=None,
            version='9.2'
        )
        receivexlog_mock.return_value.execute.assert_called_once_with()

        # Test: incompatible pg_receivexlog
        with pytest.raises(ArchiverFailure):
            remote_mock.return_value = {
                'pg_receivexlog_installed': True,
                'pg_receivexlog_compatible': False,
                'pg_receivexlog_supports_slots': False,
                'pg_receivexlog_synchronous': False,
                'pg_receivexlog_path': 'fake/path'
            }
            archiver.receive_wal()

        # Test: missing pg_receivexlog
        with pytest.raises(ArchiverFailure):
            remote_mock.return_value = {
                'pg_receivexlog_installed': False,
                'pg_receivexlog_compatible': True,
                'pg_receivexlog_supports_slots': False,
                'pg_receivexlog_synchronous': False,
                'pg_receivexlog_path': 'fake/path'
            }
            archiver.receive_wal()
        # Test: impossible to connect with streaming protocol
        with pytest.raises(ArchiverFailure):
            backup_manager.server.streaming.get_remote_status.return_value = {
                'streaming_supported': None
            }
            remote_mock.return_value = {
                'pg_receivexlog_installed': True,
                'pg_receivexlog_supports_slots': False,
                'pg_receivexlog_compatible': True,
                'pg_receivexlog_synchronous': False,
                'pg_receivexlog_path': 'fake/path'
            }
            archiver.receive_wal()
        # Test: PostgreSQL too old
        with pytest.raises(ArchiverFailure):
            backup_manager.server.streaming.get_remote_status.return_value = {
                'streaming_supported': False
            }
            remote_mock.return_value = {
                'pg_receivexlog_installed': True,
                'pg_receivexlog_compatible': True,
                'pg_receivexlog_synchronous': False,
                'pg_receivexlog_path': 'fake/path'
            }
            archiver.receive_wal()
        # Test: general failure executing pg_receivexlog
        with pytest.raises(ArchiverFailure):
            remote_mock.return_value = {
                'pg_receivexlog_installed': True,
                'pg_receivexlog_compatible': True,
                'pg_receivexlog_synchronous': False,
                'pg_receivexlog_path': 'fake/path'
            }
            receivexlog_mock.return_value.execute.side_effect = \
                CommandFailedException
            archiver.receive_wal()
Exemple #20
0
    def test_get_next_batch(
        self, from_file_mock, isfile_mock, exists_mock, glob_mock, caplog
    ):
        """
        Test the FileWalArchiver.get_next_batch method
        """
        # See all logs
        caplog.set_level(0)

        # WAL batch, with 000000010000000000000001 that is currently being
        # written
        glob_mock.return_value = ["000000010000000000000001"]
        isfile_mock.return_value = True
        # This is an hack, instead of a WalFileInfo we use a simple string to
        # ease all the comparisons. The resulting string is the name enclosed
        # in colons. e.g. ":000000010000000000000001:"
        from_file_mock.side_effect = lambda wal_name, compression: (":%s:" % wal_name)

        backup_manager = build_backup_manager(name="TestServer")
        archiver = StreamingWalArchiver(backup_manager)
        backup_manager.server.archivers = [archiver]

        caplog_reset(caplog)
        batch = archiver.get_next_batch()
        assert ["000000010000000000000001"] == batch.skip
        assert "" == caplog.text

        # WAL batch, with 000000010000000000000002 that is currently being
        # written and 000000010000000000000001 can be archived
        caplog_reset(caplog)
        glob_mock.return_value = [
            "000000010000000000000001",
            "000000010000000000000002",
        ]
        batch = archiver.get_next_batch()
        assert [":000000010000000000000001:"] == batch
        assert ["000000010000000000000002"] == batch.skip
        assert "" == caplog.text

        # WAL batch, with two partial files.
        caplog_reset(caplog)
        glob_mock.return_value = [
            "000000010000000000000001.partial",
            "000000010000000000000002.partial",
        ]
        batch = archiver.get_next_batch()
        assert [":000000010000000000000001.partial:"] == batch
        assert ["000000010000000000000002.partial"] == batch.skip
        assert (
            "Archiving partial files for server %s: "
            "000000010000000000000001.partial" % archiver.config.name
        ) in caplog.text

        # WAL batch, with history files.
        caplog_reset(caplog)
        glob_mock.return_value = [
            "00000001.history",
            "000000010000000000000002.partial",
        ]
        batch = archiver.get_next_batch()
        assert [":00000001.history:"] == batch
        assert ["000000010000000000000002.partial"] == batch.skip
        assert "" == caplog.text

        # WAL batch with errors
        wrong_file_name = "test_wrong_wal_file.2"
        glob_mock.return_value = ["test_wrong_wal_file.2"]
        batch = archiver.get_next_batch()
        assert [wrong_file_name] == batch.errors

        # WAL batch, with two partial files, but one has been just renamed.
        caplog_reset(caplog)
        exists_mock.side_effect = [False, True]
        glob_mock.return_value = [
            "000000010000000000000001.partial",
            "000000010000000000000002.partial",
        ]
        batch = archiver.get_next_batch()
        assert len(batch) == 0
        assert ["000000010000000000000002.partial"] == batch.skip
        assert "" in caplog.text
    def test_check(self, remote_mock, capsys):
        """
        Test management of check_postgres view output

        :param remote_mock: mock get_remote_status function
        :param capsys: retrieve output from consolle
        """
        # Create a backup_manager
        backup_manager = build_backup_manager()
        # Set up mock responses
        streaming = backup_manager.server.streaming
        streaming.server_txt_version = '9.5'
        # Instantiate a StreamingWalArchiver obj
        archiver = StreamingWalArchiver(backup_manager)
        # Prepare the output check strategy
        strategy = CheckOutputStrategy()
        # Case: correct configuration
        remote_mock.return_value = {
            'pg_receivexlog_installed': True,
            'pg_receivexlog_compatible': True,
            'pg_receivexlog_path': 'fake/path',
        }
        # Expect out: all parameters: OK
        backup_manager.server.process_manager.list.return_value = []
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert out == \
            "\tpg_receivexlog: OK\n" \
            "\tpg_receivexlog compatible: OK\n" \
            "\treceive-wal running: FAILED " \
            "(See the Barman log file for more details)\n"

        # Case: pg_receivexlog is not compatible
        remote_mock.return_value = {
            'pg_receivexlog_installed': True,
            'pg_receivexlog_compatible': False,
            'pg_receivexlog_path': 'fake/path',
            'pg_receivexlog_version': '9.2',
        }
        # Expect out: some parameters: FAILED
        strategy = CheckOutputStrategy()
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert out == \
            "\tpg_receivexlog: OK\n" \
            "\tpg_receivexlog compatible: FAILED " \
            "(PostgreSQL version: 9.5, pg_receivexlog version: 9.2)\n" \
            "\treceive-wal running: FAILED " \
            "(See the Barman log file for more details)\n"
        # Case: pg_receivexlog returned error
        remote_mock.return_value = {
            'pg_receivexlog_installed': True,
            'pg_receivexlog_compatible': None,
            'pg_receivexlog_path': 'fake/path',
            'pg_receivexlog_version': None,
        }
        # Expect out: all parameters: OK
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert out == \
            "\tpg_receivexlog: OK\n" \
            "\tpg_receivexlog compatible: FAILED " \
            "(PostgreSQL version: 9.5, pg_receivexlog version: None)\n" \
            "\treceive-wal running: FAILED " \
            "(See the Barman log file for more details)\n"

        # Case: receive-wal running
        backup_manager.server.process_manager.list.return_value = [
            ProcessInfo(pid=1,
                        server_name=backup_manager.config.name,
                        task="receive-wal")
        ]
        archiver.check(strategy)
        (out, err) = capsys.readouterr()
        assert out == \
            "\tpg_receivexlog: OK\n" \
            "\tpg_receivexlog compatible: FAILED " \
            "(PostgreSQL version: 9.5, pg_receivexlog version: None)\n" \
            "\treceive-wal running: OK\n"