├── sphinx
├── .gitignore
├── requirements.txt
├── README.md
├── docs
│ └── index.rst
├── generate_docs.sh
└── Makefile
├── doc
├── .gitignore
├── manual
│ ├── .gitignore
│ ├── 20-server_setup.en.md
│ ├── Makefile
│ ├── 00-head.en.md
│ ├── 22-config_file.en.md
│ ├── 26-rsync_backup.en.md
│ ├── 02-before_you_start.en.md
│ ├── 27-windows-support.en.md
│ ├── 25-streaming_backup.en.md
│ ├── 65-troubleshooting.en.md
│ ├── 70-feature-matrix.en.md
│ ├── 41-global-commands.en.md
│ ├── 24-wal_archiving.en.md
│ ├── 15-system_requirements.en.md
│ ├── 99-references.en.md
│ ├── 16-installation.en.md
│ ├── 17-configuration.en.md
│ ├── 01-intro.en.md
│ ├── 66-about.en.md
│ ├── 23-wal_streaming.en.md
│ ├── 43-backup-commands.en.md
│ ├── 21-preliminary_steps.en.md
│ ├── 42-server-commands.en.md
│ └── 10-design.en.md
├── images
│ ├── barman-architecture-scenario1.png
│ ├── barman-architecture-scenario2.png
│ ├── barman-architecture-scenario1b.png
│ └── barman-architecture-scenario2b.png
├── Makefile
├── barman.d
│ ├── ssh-server.conf-template
│ └── streaming-server.conf-template
└── barman.conf
├── scripts
├── barman.bash_completion
├── release.sh
└── gitlog-to-changelog
├── setup.cfg
├── INSTALL
├── .travis.yml
├── MANIFEST.in
├── .gitignore
├── rpm
├── rhel5
│ ├── setup.cfg.patch
│ ├── python26-argh.spec
│ ├── python26-argcomplete.spec
│ ├── python-dateutil-1.4.1-remove-embedded-timezone-data.patch
│ ├── python26-dateutil.spec
│ └── python26-psycopg2.spec
├── rhel6
│ ├── python-argh.spec
│ └── python-argcomplete.spec
├── rhel7
│ └── python-argh.spec
└── barman.spec
├── TODO
├── barman
├── version.py
├── __init__.py
├── remote_status.py
├── diagnose.py
├── process.py
├── exceptions.py
├── hooks.py
└── lockfile.py
├── bin
└── barman
├── tox.ini
├── AUTHORS
├── README.rst
├── setup.py
└── tests
├── test_process.py
├── test_compressor.py
└── test_cli.py
/sphinx/.gitignore:
--------------------------------------------------------------------------------
1 | _build/
2 | docs/*.rst
3 | docs/!index.rst
4 |
--------------------------------------------------------------------------------
/doc/.gitignore:
--------------------------------------------------------------------------------
1 | barman-tutorial.en.pdf
2 | barman-tutorial.en.html
3 |
--------------------------------------------------------------------------------
/doc/manual/.gitignore:
--------------------------------------------------------------------------------
1 | barman-manual.en.html
2 | barman-manual.en.pdf
3 |
--------------------------------------------------------------------------------
/scripts/barman.bash_completion:
--------------------------------------------------------------------------------
1 | eval "$(register-python-argcomplete barman)"
2 |
--------------------------------------------------------------------------------
/doc/images/barman-architecture-scenario1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/secwall/barman/HEAD/doc/images/barman-architecture-scenario1.png
--------------------------------------------------------------------------------
/doc/images/barman-architecture-scenario2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/secwall/barman/HEAD/doc/images/barman-architecture-scenario2.png
--------------------------------------------------------------------------------
/doc/images/barman-architecture-scenario1b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/secwall/barman/HEAD/doc/images/barman-architecture-scenario1b.png
--------------------------------------------------------------------------------
/doc/images/barman-architecture-scenario2b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/secwall/barman/HEAD/doc/images/barman-architecture-scenario2b.png
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [bdist_wheel]
2 | universal = 1
3 |
4 | [aliases]
5 | test=pytest
6 |
7 | [isort]
8 | known_first_party=barman
9 | known_third_party=setuptools,distutils,argh,argcomplete,dateutil,psycopg2,mock,pytest
10 | skip=.tox
11 |
--------------------------------------------------------------------------------
/INSTALL:
--------------------------------------------------------------------------------
1 | Barman INSTALL instructions
2 | Copyright (C) 2011-2016 2ndQuadrant Italia Srl
3 |
4 | For further information, see the "Installation" section in the
5 | official manual of Barman or the Markdown source file:
6 | doc/manual/16-installation.en.md.
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: python
3 | python:
4 | - "3.5"
5 | env:
6 | - TOX_ENV=py26
7 | - TOX_ENV=py27
8 | - TOX_ENV=py33
9 | - TOX_ENV=py34
10 | - TOX_ENV=py35
11 | - TOX_ENV=flake8
12 | - TOX_ENV=minimal
13 | install:
14 | - travis_retry pip install tox
15 | script:
16 | - tox -e $TOX_ENV
17 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | recursive-include barman *.py
2 | recursive-include rpm *
3 | recursive-include doc *.md
4 | recursive-include doc/barman.d *
5 | include doc/Makefile doc/barman.1 doc/barman.5 doc/barman.conf
6 | include scripts/barman.bash_completion
7 | include AUTHORS NEWS ChangeLog LICENSE MANIFEST.in setup.py INSTALL README.rst
8 |
--------------------------------------------------------------------------------
/sphinx/requirements.txt:
--------------------------------------------------------------------------------
1 | alabaster==0.7.6
2 | argcomplete==0.9.0
3 | argh==0.26.1
4 | argparse==1.3.0
5 | Babel==1.3
6 | docutils==0.12
7 | Jinja2==2.7.3
8 | MarkupSafe==0.23
9 | psycopg2==2.6.1
10 | Pygments==2.0.2
11 | python-dateutil==2.4.0
12 | pytz==2015.4
13 | six==1.9.0
14 | snowballstemmer==1.2.0
15 | Sphinx==1.3.1
16 | sphinx-bootstrap-theme==0.4.6
17 | sphinx-rtd-theme==0.1.8
18 | wheel==0.24.0
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # compiled python sources
2 | *.pyc
3 | *.pyo
4 |
5 | # python modules
6 | *.egg
7 | .eggs
8 |
9 | # editor backups
10 | *~
11 | \#*\#
12 | .*.swp
13 |
14 | # eclipse project files
15 | /.project
16 | /.pydevproject
17 | /.settings
18 |
19 | # PyCharm
20 | /.idea
21 |
22 | # tox testing
23 | .tox/
24 | .cache/
25 |
26 | # setuptools
27 | /MANIFEST
28 | /dist
29 | /build
30 | /barman.egg-info
31 |
32 | # OSX
33 | .DS_Store
34 |
--------------------------------------------------------------------------------
/doc/manual/20-server_setup.en.md:
--------------------------------------------------------------------------------
1 | \newpage
2 |
3 | # Setup of a new server in Barman
4 |
5 | As mentioned in the _"Design and architecture"_ section, we will use the
6 | following conventions:
7 |
8 | - `pg` as server ID and host name where PostgreSQL is installed
9 | - `backup` as host name where Barman is located
10 | - `barman` as the user running Barman on the `backup` server (identified by
11 | the parameter `barman_user` in the configuration)
12 | - `postgres` as the user running PostgreSQL on the `pg` server
13 |
--------------------------------------------------------------------------------
/doc/Makefile:
--------------------------------------------------------------------------------
1 | MANPAGES=barman.1 barman.5
2 | DOCS=
3 | SUBDIRS=manual
4 |
5 | .PHONY: all clean help subdirs $(SUBDIRS)
6 |
7 | all: $(MANPAGES) $(DOCS) $(SUBDIRS)
8 |
9 | barman.1: barman.1.md
10 | pandoc -s -t man -o $@ $<
11 |
12 | barman.5: barman.5.md
13 | pandoc -s -t man -o $@ $<
14 |
15 | clean:
16 | rm -f $(MANPAGES) $(DOCS)
17 | for dir in $(SUBDIRS); do \
18 | $(MAKE) -C $$dir clean; \
19 | done
20 |
21 | help:
22 | @echo "Usage:"
23 | @echo " $$ make"
24 |
25 | subdirs: $(SUBDIRS)
26 |
27 | $(SUBDIRS):
28 | $(MAKE) -C $@
29 |
30 |
--------------------------------------------------------------------------------
/rpm/rhel5/setup.cfg.patch:
--------------------------------------------------------------------------------
1 | --- setup.cfg.old 2011-08-22 12:16:18.703486005 +0300
2 | +++ setup.cfg 2011-08-22 12:16:31.596486005 +0300
3 | @@ -26,7 +26,7 @@
4 | # libraries needed to build psycopg2. If pg_config is not in the path or
5 | # is installed under a different name uncomment the following option and
6 | # set it to the pg_config full path.
7 | -#pg_config=
8 | +pg_config=/usr/pgsql-9.0/bin/pg_config
9 |
10 | # If "pg_config" is not available, "include_dirs" can be used to locate
11 | # postgresql headers and libraries. Some extra checks on sys.platform will
12 |
--------------------------------------------------------------------------------
/doc/manual/Makefile:
--------------------------------------------------------------------------------
1 | DOCS= \
2 | barman-manual.en.pdf barman-manual.en.html
3 |
4 | MDS = \
5 | ??-*.en.md
6 | #00-head.en.md \
7 | #01-intro.en.md \
8 | #02-before_you_start.en.md \
9 | #10-design.en.md
10 |
11 | all: $(DOCS)
12 |
13 | barman-manual.en.pdf: $(MDS) ../images/*.png
14 | pandoc -o $@ -s -f markdown --toc $(MDS)
15 |
16 | barman-manual.en.html: $(MDS) ../images/*.png
17 | pandoc -o $@ -t html5 -f markdown -s -S --toc $(MDS)
18 |
19 | clean:
20 | rm -f $(DOCS)
21 |
22 | help:
23 | @echo "Usage:"
24 | @echo " $$ make"
25 |
26 | .PHONY: all clean help
27 |
--------------------------------------------------------------------------------
/TODO:
--------------------------------------------------------------------------------
1 | Barman TODO - Backlog of features for Barman
2 | Copyright (C) 2011-2016 2ndQuadrant Italia Srl
3 |
4 | * TAR storage strategy for backups
5 | * SSH only connections
6 | * Centralised WAL hub capability (streaming server)
7 | * Barman passive nodes (for asynchronous geographical redundancy)
8 | * Hook scripts for backup delete, WAL archiving, etc.
9 | * Export/Import of backups
10 | * External backup sources (e.g. S3)
11 | * Improve recovery support
12 | * Sandbox recovery
13 | * Logical backup integration (pg_dump on sandbox instances)
14 | * JSON output for full automation
15 | * Backup validation
16 | * Windows support
17 | * ...
18 |
--------------------------------------------------------------------------------
/doc/manual/00-head.en.md:
--------------------------------------------------------------------------------
1 | % Barman Manual
2 | % 2ndQuadrant Italia
3 | % January 20, 2017 (v2.2a1)
4 |
5 | **Barman** (Backup and Recovery Manager) is an open-source administration tool for disaster recovery of PostgreSQL servers written in Python. It allows your organisation to perform remote backups of multiple servers in business critical environments to reduce risk and help DBAs during the recovery phase.
6 |
7 | [Barman] [11] is distributed under GNU GPL 3 and maintained by [2ndQuadrant] [13], a platinum sponsor of the [PostgreSQL project] [31].
8 |
9 | > **IMPORTANT:** \newline
10 | > This manual assumes that you are familiar with theoretical disaster
11 | > recovery concepts, and that you have a grasp of PostgreSQL fundamentals in
12 | > terms of physical backup and disaster recovery. See section _"Before you start"_ below for details.
13 |
--------------------------------------------------------------------------------
/barman/version.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2011-2016 2ndQuadrant Italia Srl
2 | #
3 | # This file is part of Barman.
4 | #
5 | # Barman is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Barman is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Barman. If not, see .
17 |
18 | '''
19 | This module contains the current Barman version.
20 | '''
21 |
22 | __version__ = '2.2a1'
23 |
--------------------------------------------------------------------------------
/bin/barman:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # Copyright (C) 2011-2016 2ndQuadrant Italia Srl
4 | #
5 | # This file is part of Barman.
6 | #
7 | # Barman is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # Barman is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with Barman. If not, see .
19 | #
20 | # PYTHON_ARGCOMPLETE_OK
21 |
22 | from barman.cli import main
23 |
24 | if __name__ == '__main__':
25 | main()
26 | else:
27 | raise NotImplementedError
28 |
--------------------------------------------------------------------------------
/barman/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2011-2016 2ndQuadrant Italia Srl
2 | #
3 | # This file is part of Barman.
4 | #
5 | # Barman is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Barman is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Barman. If not, see .
17 |
18 | """
19 | The main Barman module
20 | """
21 |
22 | from __future__ import absolute_import
23 | from .version import __version__
24 |
25 | __config__ = None
26 |
27 | __all__ = ['__version__', '__config__']
28 |
--------------------------------------------------------------------------------
/doc/manual/22-config_file.en.md:
--------------------------------------------------------------------------------
1 | ## The server configuration file
2 |
3 | Create a new file, called `pg.conf`, in `/etc/barman.d` directory, with the following content:
4 |
5 | ``` ini
6 | [pg]
7 | description = "Our main PostgreSQL server"
8 | conninfo = host=pg user=barman dbname=postgres
9 | backup_method = postgres
10 | # backup_method = rsync
11 | ```
12 |
13 | The `conninfo` option is set accordingly to the section _"Preliminary
14 | steps: PostgreSQL connection"_.
15 |
16 | The meaning of the `backup_method` option will be covered in the
17 | backup section of this guide.
18 |
19 | If you plan to use the streaming connection for WAL archiving or to
20 | create a backup of your server, you also need a `streaming_conninfo`
21 | parameter in your server configuration file:
22 |
23 | ``` ini
24 | streaming_conninfo = host=pg user=streaming_barman dbname=postgres
25 | ```
26 |
27 | This value must be choosen accordingly as described in the section
28 | _"Preliminary steps: PostgreSQL connection"_.
29 |
--------------------------------------------------------------------------------
/tox.ini:
--------------------------------------------------------------------------------
1 | [tox]
2 | envlist = py26, py27, py33, py34, py35, flake8, minimal
3 |
4 | [testenv]
5 | deps = pytest
6 | mock
7 | pytest-catchlog>=1.2.1
8 | pytest-timeout
9 | python-dateutil
10 | commands = py.test {posargs:tests}
11 |
12 | [testenv:minimal]
13 | basepython = python2.6
14 | deps = pytest
15 | mock
16 | pytest-catchlog>=1.2.1
17 | pytest-timeout
18 | psycopg2==2.4.2
19 | argh==0.21.2
20 | python-dateutil==1.5
21 | commands = py.test {posargs:tests}
22 | passenv = USER
23 |
24 | [testenv:flake8]
25 | basepython = python2.7
26 | commands = flake8 {posargs}
27 | deps = flake8
28 | flake8-mock
29 | flake8-string-format
30 | flake8-copyright
31 | flake8-isort
32 | # Workaround for https://github.com/gforcada/flake8-isort/issues/9
33 | pep8
34 |
35 | [flake8]
36 | copyright-check = True
37 | copyright-regexp = Copyright\s+(\(C\)\s+)?(\d{4}-)?2016\s+%(author)s
38 | copyright-author = 2ndQuadrant Italia Srl
39 |
--------------------------------------------------------------------------------
/doc/manual/26-rsync_backup.en.md:
--------------------------------------------------------------------------------
1 | ## Backup with `rsync`/SSH
2 |
3 | The backup over `rsync` was the only available method before 2.0, and
4 | is currently the only backup method that supports the incremental
5 | backup feature. Please consult the _"Features in detail"_ section for
6 | more information.
7 |
8 | To take a backup using `rsync` you need to put these parameters inside
9 | the Barman server configuration file:
10 |
11 | ``` ini
12 | backup_method = rsync
13 | ssh_command = ssh postgres@pg
14 | ```
15 |
16 | The `backup_method` option activates the `rsync` backup method, and
17 | the `ssh_command` option is needed to correctly create an SSH
18 | connection from the Barman server to the PostgreSQL server.
19 |
20 | > **IMPORTANT:** Keep in mind that if the WAL archiving is not
21 | > currently configured, you will not be able to start a backup.
22 |
23 | To check if the server configuration is valid you can use the `barman
24 | check` command:
25 |
26 | ``` bash
27 | barman@backup$ barman check pg
28 | ```
29 |
30 | To take a backup use the `barman backup` command:
31 |
32 | ``` bash
33 | barman@backup$ barman backup pg
34 | ```
35 |
36 |
--------------------------------------------------------------------------------
/doc/manual/02-before_you_start.en.md:
--------------------------------------------------------------------------------
1 | \newpage
2 |
3 | # Before you start
4 |
5 | Before you start using Barman, it is fundamental that you get familiar
6 | with PostgreSQL and the concepts around physical backups, Point-In-Time-Recovery and replication, such as base backups, WAL archiving, etc.
7 |
8 | Below you can find a non exhaustive list of resources that we recommend for you to read:
9 |
10 | - _PostgreSQL documentation_:
11 | - [SQL Dump] [sqldump] [^pgdump]
12 | - [File System Level Backup] [physicalbackup]
13 | - [Continuous Archiving and Point-in-Time Recovery (PITR)] [pitr]
14 | - [Recovery Configuration] [recoveryconfig]
15 | - [Reliability and the Write-Ahead Log] [wal]
16 | - _Book_: [PostgreSQL 9 Administration Cookbook - 2nd edition] [adminbook]
17 |
18 | [^pgdump]: It is important that you know the difference between logical and physical backup, therefore between `pg_dump` and a tool like Barman.
19 |
20 | Professional training on these topics is another effective way of
21 | learning these concepts. At any time of the year you can find many
22 | courses available all over the world, delivered by PostgreSQL
23 | companies such as 2ndQuadrant.
24 |
--------------------------------------------------------------------------------
/scripts/release.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Copyright (C) 2011-2016 2ndQuadrant Italia Srl
4 | #
5 | # This file is part of Barman.
6 | #
7 | # Barman is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # Barman is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with Barman. If not, see .
19 |
20 | set -e
21 |
22 | BASE="$(dirname $(cd $(dirname "$0"); pwd))"
23 | cd "$BASE"
24 |
25 | VERSION="$(python -c 'd={}; exec(open("barman/version.py").read(), d); print(d["__version__"])')"
26 | scripts/gitlog-to-changelog > ChangeLog
27 | git add ChangeLog
28 | git commit -m "Update the ChangeLog file"
29 | scripts/gitlog-to-changelog > ChangeLog
30 | git add ChangeLog
31 | git commit -m "Update the ChangeLog file" --amend
32 | ./setup.py sdist
33 | if ! git tag -s -m "Release ${VERSION}" release/${VERSION}
34 | then
35 | echo "Cannot tag the release as the private key is missing"
36 | fi
37 |
--------------------------------------------------------------------------------
/doc/manual/27-windows-support.en.md:
--------------------------------------------------------------------------------
1 | ## How to setup a Windows based server
2 |
3 | You can backup a PostgreSQL server running on Windows using the
4 | streaming connection for both WAL archiving and for backups.
5 |
6 | > **IMPORTANT:** This feature is still experimental because it is not
7 | > yet part of our continuous integration system.
8 |
9 | Follow every step discussed previously for a streaming connection
10 | setup.
11 |
12 | > **WARNING:**: At this moment, `pg_basebackup` interoperability from
13 | > Windows to Linux is still experimental. If you are having issues
14 | > taking a backup from a Windows server and your PostgreSQL locale is
15 | > not in English, a possible workaround for the issue is instructing
16 | > your PostgreSQL to emit messages in English. You can do this by
17 | > putting the following parameter in your `postgresql.conf` file:
18 | >
19 | > ``` ini
20 | > lc_messages = 'English'
21 | > ```
22 | >
23 | > This has been reported to fix the issue.
24 |
25 | You can backup your server as usual.
26 |
27 | Remote recovery is not supported for Windows servers, so you must
28 | recover your cluster locally in the Barman server and then copy all
29 | the files on a Windows server or use a folder shared between the
30 | PostgreSQL server and the Barman server.
31 |
32 | Additionally, make sure that the system user chosen to run PostgreSQL
33 | has the permission needed to access the restored data. Basically, it
34 | must have full control over the PostgreSQL data directory.
35 |
--------------------------------------------------------------------------------
/doc/manual/25-streaming_backup.en.md:
--------------------------------------------------------------------------------
1 | ## Streaming backup
2 |
3 | Barman can backup a PostgreSQL server using the streaming connection,
4 | relying on `pg_basebackup`, a utility that has been available from
5 | PostgreSQL 9.1.
6 |
7 | > **IMPORTANT:** Barman requires that `pg_basebackup` is installed in
8 | > the same server. For PostgreSQL 9.2 servers, you need the
9 | > `pg_basebackup` of version 9.2 installed alongside with Barman. For
10 | > PostgreSQL 9.3 and above, it is recommented to install the last
11 | > available version of `pg_basebackup`, as it is back compatible. You
12 | > can even install multiple versions of `pg_basebackup` on the Barman
13 | > server and properly point to the specific version for a server,
14 | > using the `path_prefix` option in the configuration file.
15 |
16 | To successfully backup your server with the streaming connection, you
17 | need to use `postgres` as your backup method:
18 |
19 | ``` ini
20 | backup_method = postgres
21 | ```
22 |
23 | > **IMPORTANT:** keep in mind that if the WAL archiving is not
24 | > currently configured, you will not be able to start a backup.
25 |
26 | To check if the server configuration is valid you can use the `barman
27 | check` command:
28 |
29 | ``` bash
30 | barman@backup$ barman check pg
31 | ```
32 |
33 | To start a backup you can use the `barman backup` command:
34 |
35 | ``` bash
36 | barman@backup$ barman backup pg
37 | ```
38 |
39 | > **IMPORTANT:** `pg_basebackup` 9.4 or higher is required for
40 | > tablespace support if you use the `postgres` backup method.
41 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | Barman Core Team (in alphabetical order):
2 |
3 | * Gabriele Bartolini (project leader)
4 | * Jonathan Battiato (QA/testing)
5 | * Stefano Bianucci (developer, intern from University of Florence)
6 | * Giuseppe Broccolo (QA/testing)
7 | * Giulio Calacoci (developer)
8 | * Francesco Canovai (QA/testing)
9 | * Leonardo Cecchi (developer)
10 | * Gianni Ciolli (QA/testing)
11 | * Britt Cole (documentation)
12 | * Marco Nenciarini (lead developer)
13 | * Rubens Souza (QA/testing)
14 |
15 | Past contributors:
16 |
17 | * Carlo Ascani
18 |
19 | Many thanks go to our sponsors (in alphabetical order):
20 |
21 | * 4Caast - http://4caast.morfeo-project.org/ (Founding sponsor)
22 | * Adyen - http://www.adyen.com/
23 | * Agile Business Group - http://www.agilebg.com/
24 | * BIJ12 - http://www.bij12.nl/
25 | * CSI Piemonte - http://www.csipiemonte.it/ (Founding sponsor)
26 | * Ecometer - http://www.ecometer.it/
27 | * GestionaleAuto - http://www.gestionaleauto.com/ (Founding sponsor)
28 | * Jobrapido - http://www.jobrapido.com/
29 | * Navionics - http://www.navionics.com/ (Founding sponsor)
30 | * Sovon Vogelonderzoek Nederland - https://www.sovon.nl/
31 | * Subito.it - http://www.subito.it/
32 | * XCon Internet Services - http://www.xcon.it/ (Founding sponsor)
33 |
--------------------------------------------------------------------------------
/doc/barman.d/ssh-server.conf-template:
--------------------------------------------------------------------------------
1 | ; Barman, Backup and Recovery Manager for PostgreSQL
2 | ; http://www.pgbarman.org/ - http://www.2ndQuadrant.com/
3 | ;
4 | ; Template configuration file for a server using
5 | ; SSH connections and rsync for copy.
6 | ;
7 |
8 | [ssh]
9 | ; Human readable description
10 | description = "Example of PostgreSQL Database (via SSH)"
11 |
12 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13 | ; SSH options (mandatory)
14 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15 | ssh_command = ssh postgres@pg
16 |
17 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18 | ; PostgreSQL connection string (mandatory)
19 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
20 | conninfo = host=pg user=barman dbname=postgres
21 |
22 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23 | ; Backup settings (via rsync over SSH)
24 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
25 | backup_method = rsync
26 | ; Incremental backup support: possible values are None (default), link or copy
27 | ;reuse_backup = link
28 | ; Identify the standard behavior for backup operations: possible values are
29 | ; exclusive_backup (default), concurrent_backup
30 | ;backup_options = exclusive_backup
31 |
32 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
33 | ; Continuous WAL archiving (via 'archive_command')
34 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
35 | archiver = on
36 | ;archiver_batch_size = 50
37 |
38 | ; PATH setting for this server
39 | ;path_prefix = "/usr/pgsql-9.6/bin"
40 |
--------------------------------------------------------------------------------
/doc/barman.d/streaming-server.conf-template:
--------------------------------------------------------------------------------
1 | ; Barman, Backup and Recovery Manager for PostgreSQL
2 | ; http://www.pgbarman.org/ - http://www.2ndQuadrant.com/
3 | ;
4 | ; Template configuration file for a server using
5 | ; only streaming replication protocol
6 | ;
7 |
8 | [streaming]
9 | ; Human readable description
10 | description = "Example of PostgreSQL Database (Streaming-Only)"
11 |
12 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13 | ; PostgreSQL connection string (mandatory)
14 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15 | conninfo = host=pg user=barman dbname=postgres
16 |
17 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18 | ; PostgreSQL streaming connection string
19 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
20 | ; To be used by pg_basebackup for backup and pg_receivexlog for WAL streaming
21 | ; NOTE: streaming_barman is a regular user with REPLICATION privilege
22 | streaming_conninfo = host=pg user=streaming_barman
23 |
24 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
25 | ; Backup settings (via pg_basebackup)
26 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
27 | backup_method = postgres
28 | ;streaming_backup_name = barman_streaming_backup
29 |
30 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
31 | ; WAL streaming settings (via pg_receivexlog)
32 | ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
33 | streaming_archiver = on
34 | slot_name = barman
35 | ;streaming_archiver_name = barman_receive_wal
36 | ;streaming_archiver_batch_size = 50
37 |
38 | ; PATH setting for this server
39 | ;path_prefix = "/usr/pgsql-9.6/bin"
40 |
--------------------------------------------------------------------------------
/rpm/rhel6/python-argh.spec:
--------------------------------------------------------------------------------
1 | %{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
2 | %{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
3 |
4 | Summary: A simple argparse wrapper
5 | Name: python-argh
6 | Version: 0.23.0
7 | Release: 1%{?dist}
8 | License: LGPLv3
9 | Group: Development/Libraries
10 | Url: http://bitbucket.org/neithere/argh/
11 | Source0: http://pypi.python.org/packages/source/a/argh/argh-%{version}.tar.gz
12 | BuildRequires: python-devel, python-setuptools
13 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n)
14 | BuildArch: noarch
15 | Requires: python-abi = %(%{__python} -c "import sys ; print sys.version[:3]")
16 | Requires: python-argparse
17 |
18 | %description
19 | Argh, argparse!
20 | ===============
21 |
22 | Did you ever say "argh" trying to remember the details of optparse or argparse
23 | API? If yes, this package may be useful for you. It provides a very simple
24 | wrapper for argparse with support for hierarchical commands that can be bound
25 | to modules or classes. Argparse can do it; argh makes it easy.
26 |
27 | %prep
28 | %setup -n argh-%{version} -q
29 |
30 | %build
31 | %{__python} setup.py build
32 |
33 | %install
34 | %{__python} setup.py install -O1 --skip-build --root $RPM_BUILD_ROOT
35 |
36 | %clean
37 | rm -rf $RPM_BUILD_ROOT
38 |
39 | %files
40 | %defattr(-,root,root)
41 | %doc README
42 | %{python_sitelib}/argh-%{version}-py2.6.egg-info
43 | %{python_sitelib}/argh/
44 |
45 | %changelog
46 | * Thu Jan 31 2013 - Marco Neciarini 0.23.0-1
47 | - Update to version 0.23.0
48 |
49 | * Wed May 9 2012 - Marco Neciarini 0.15.0-1
50 | - Update to version 0.15.0
51 |
52 | * Sat Dec 4 2011 - Marco Neciarini 0.14.2-1
53 | - Initial packaging.
54 |
--------------------------------------------------------------------------------
/doc/manual/65-troubleshooting.en.md:
--------------------------------------------------------------------------------
1 | \newpage
2 |
3 | # Troubleshooting
4 |
5 | ## Diagnose a Barman installation
6 |
7 | You can gather important information about the status of all
8 | the configured servers using:
9 |
10 | ``` bash
11 | barman diagnose
12 | ```
13 |
14 | The `diagnose` command output is a full snapshot of the barman server,
15 | providing useful information, such as global configuration, SSH version,
16 | Python version, `rsync` version, PostgreSQL clients version,
17 | as well as current configuration and status of all servers.
18 |
19 | The `diagnose` command is extremely useful for troubleshooting problems,
20 | as it gives a global view on the status of your Barman installation.
21 |
22 | ## Requesting help
23 |
24 | Although Barman is extensively documented, there are a lot of scenarios that
25 | are not covered.
26 |
27 | For any questions about Barman and disaster recovery scenarios using Barman,
28 | you can reach the dev team using the community mailing list:
29 |
30 | https://groups.google.com/group/pgbarman
31 |
32 | or the IRC channel on freenode:
33 | irc://irc.freenode.net/barman
34 |
35 | In the event you discover a bug, you can open a ticket using Github:
36 | https://github.com/2ndquadrant-it/barman/issues
37 |
38 | 2ndQuadrant provides professional support for Barman, including 24/7 service.
39 |
40 | ### Submitting a bug
41 |
42 | Barman has been extensively tested and is currently being used in
43 | several production environments. However, as any software, Barman is
44 | not bug free.
45 |
46 | If you discover a bug, please follow this procedure:
47 |
48 | - execute the `barman diagnose` command
49 | - file a bug through the Github issue tracker, by attaching the
50 | output obtained by the diagnostics command above (`barman
51 | diagnose`)
52 |
53 | > **WARNING:**
54 | > Be careful when submitting the output of the diagnose command
55 | > as it might disclose information that are potentially dangerous
56 | > from a security point of view.
57 |
--------------------------------------------------------------------------------
/doc/manual/70-feature-matrix.en.md:
--------------------------------------------------------------------------------
1 | \newpage
2 |
3 | \appendix
4 |
5 | # Feature matrix
6 |
7 | Below you will find a matrix of PostgreSQL versions and Barman features for backup and archiving:
8 |
9 | | **Version** | **Backup with rsync/SSH** | **Backup with pg_basebackup** | **Standard WAL archiving** | **WAL Streaming** | **RPO=0** |
10 | |:---------:|:---------------------:|:-------------------------:|:----------------------:|:----------------------:|:-------:|
11 | | **9.6** | Yes | Yes | Yes | Yes | Yes |
12 | | **9.5** | Yes | Yes | Yes | Yes | Yes ~(d)~ |
13 | | **9.4** | Yes | Yes | Yes | Yes | Yes ~(d)~ |
14 | | **9.3** | Yes | Yes ~(c)~ | Yes | Yes ~(b)~ | No |
15 | | **9.2** | Yes | Yes ~(a)~~(c)~ | Yes | Yes ~(a)~~(b)~ | No |
16 | | _9.1_ | Yes | No | Yes | No | No |
17 | | _9.0_ | Yes | No | Yes | No | No |
18 | | _8.4_ | Yes | No | Yes | No | No |
19 | | _8.3_ | Yes | No | Yes | No | No |
20 |
21 |
22 | **NOTE:**
23 |
24 | a) `pg_basebackup` and `pg_receivexlog` 9.2 required
25 | b) WAL streaming-only not supported (standard archiving required)
26 | c) Backup of tablespaces not supported
27 | d) When using `pg_receivexlog` 9.5, minor version 9.5.5 or higher required [^commitsync]
28 |
29 | [^commitsync]: The commit ["Fix pg_receivexlog --synchronous"] [49340627f9821e447f135455d942f7d5e96cae6d] is required (included in version 9.5.5)
30 |
31 | It is required by Barman that `pg_basebackup` and `pg_receivexlog` of the same version of the PostgreSQL server (or higher) are installed on the same server where Barman resides. The only exception is that PostgreSQL 9.2 users are required to install version 9.2 of `pg_basebackup` and `pg_receivexlog` alongside with Barman.
32 |
33 | >> **TIP:** We recommend that the last major, stable version of the PostgreSQL clients (e.g. 9.6) is installed on the Barman server if you plan to use backup and WAL archiving over streaming replication through `pg_basebackup` and `pg_receivexlog`, for PostgreSQL 9.3 or higher servers.
34 |
35 | >> **TIP:** For "RPO=0" architectures, it is recommended to have at least one synchronous standby server.
36 |
37 |
--------------------------------------------------------------------------------
/rpm/rhel7/python-argh.spec:
--------------------------------------------------------------------------------
1 | %{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
2 | %{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
3 |
4 | Summary: A simple argparse wrapper
5 | Name: python-argh
6 | Version: 0.26.1
7 | Release: 1%{?dist}
8 | License: LGPLv3
9 | Group: Development/Libraries
10 | Url: http://bitbucket.org/neithere/argh/
11 | Source0: http://pypi.python.org/packages/source/a/argh/argh-%{version}.tar.gz
12 | BuildRequires: python-devel, python-setuptools
13 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n)
14 | BuildArch: noarch
15 | Requires: python-abi = %(%{__python} -c "import sys ; print sys.version[:3]")
16 | Requires: python-argparse
17 |
18 | %description
19 | Argh, argparse!
20 | ===============
21 |
22 | Did you ever say "argh" trying to remember the details of optparse or argparse
23 | API? If yes, this package may be useful for you. It provides a very simple
24 | wrapper for argparse with support for hierarchical commands that can be bound
25 | to modules or classes. Argparse can do it; argh makes it easy.
26 |
27 | %prep
28 | %setup -n argh-%{version} -q
29 |
30 | %build
31 | %{__python} setup.py build
32 |
33 | %install
34 | %{__python} setup.py install -O1 --skip-build --root $RPM_BUILD_ROOT
35 |
36 | %clean
37 | rm -rf $RPM_BUILD_ROOT
38 |
39 | %files
40 | %defattr(-,root,root)
41 | %doc README.rst
42 | %{python_sitelib}/argh-%{version}-py2.7.egg-info
43 | %{python_sitelib}/argh/
44 |
45 | %changelog
46 |
47 | * Tue Jan 20 2015 - Francesco Canovai 0.26.1-1
48 | - Update to version 0.26.1
49 |
50 | * Thu Jan 31 2013 - Marco Nenciarini 0.23.0-1
51 | - Update to version 0.23.0
52 |
53 | * Wed May 9 2012 - Marco Nenciarini 0.15.0-1
54 | - Update to version 0.15.0
55 |
56 | * Sat Dec 3 2011 - Marco Nenciarini 0.14.2-1
57 | - Initial packaging.
58 |
--------------------------------------------------------------------------------
/rpm/rhel6/python-argcomplete.spec:
--------------------------------------------------------------------------------
1 | %{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
2 | %{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
3 |
4 | Summary: Bash tab completion for argparse
5 | Name: python-argcomplete
6 | Version: 0.3.5
7 | Release: 1%{?dist}
8 | License: ASL 2.0
9 | Group: Development/Libraries
10 | Url: https://github.com/kislyuk/argcomplete
11 | Source0: http://pypi.python.org/packages/source/a/argcomplete/argcomplete-%{version}.tar.gz
12 | BuildRequires: python-devel,python-setuptools
13 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n)
14 | BuildArch: noarch
15 | Requires: python-abi = %(%{__python} -c "import sys ; print sys.version[:3]")
16 | Requires: python-argparse
17 |
18 | %description
19 | Argcomplete provides easy, extensible command line tab completion of
20 | arguments for your Python script.
21 |
22 | It makes two assumptions:
23 |
24 | * You're using bash as your shell
25 | * You're using argparse to manage your command line arguments/options
26 |
27 | Argcomplete is particularly useful if your program has lots of
28 | options or subparsers, and if your program can dynamically suggest
29 | completions for your argument/option values (for example, if the user
30 | is browsing resources over the network).
31 |
32 | %prep
33 | %setup -n argcomplete-%{version} -q
34 |
35 | %build
36 | %{__python} setup.py build
37 |
38 | %install
39 | %{__python} setup.py install -O1 --skip-build --root $RPM_BUILD_ROOT
40 |
41 | %clean
42 | rm -rf $RPM_BUILD_ROOT
43 |
44 | %files
45 | %defattr(-,root,root)
46 | %doc README.rst
47 | %{python_sitelib}/argcomplete-%{version}-py2.6.egg-info
48 | %{python_sitelib}/argcomplete/
49 | %{_bindir}/activate-global-python-argcomplete
50 | %{_bindir}/python-argcomplete-check-easy-install-script
51 | %{_bindir}/register-python-argcomplete
52 |
53 | %changelog
54 | * Thu Jan 31 2013 - Marco Neciarini 0.3.5-1
55 | - Initial packaging.
56 |
--------------------------------------------------------------------------------
/doc/manual/41-global-commands.en.md:
--------------------------------------------------------------------------------
1 | \newpage
2 |
3 | # General commands
4 |
5 | Barman has many commands and, for the sake of exposition, we can
6 | organize them by scope.
7 |
8 | The scope of the **general commands** is the entire Barman server,
9 | that can backup many PostgreSQL servers. **Server commands**, instead,
10 | act only on a specified server. **Backup commands** work on a backup,
11 | which is taken from a certain server.
12 |
13 | The following list includes the general commands.
14 |
15 |
16 | ## `cron`
17 |
18 | You can perform maintenance operations, on both WAL files and backups,
19 | using the `cron` command:
20 |
21 | ``` bash
22 | barman cron
23 | ```
24 |
25 | > **NOTE:**
26 | > This command should be executed in a _cron script_. Our
27 | > recommendation is to schedule `barman cron` to run every minute. If
28 | > you installed Barman using the rpm or debian package, a cron entry
29 | > running on every minute will be created for you.
30 |
31 | `barman cron` executes WAL archiving operations concurrently on a
32 | server basis, and this also enforces retention policies on those
33 | servers that have:
34 |
35 | - `retention_policy` not empty and valid;
36 | - `retention_policy_mode` set to `auto`.
37 |
38 | The `cron` command ensures that WAL streaming is started for those
39 | servers that have requested it, by transparently executing the
40 | `receive-wal` command.
41 |
42 |
43 | ## `diagnose`
44 |
45 | The `diagnose` command creates a JSON report useful for diagnostic and
46 | support purposes. This report contains information for all configured
47 | servers.
48 |
49 | > **IMPORTANT:**
50 | > Even if the diagnose is written in JSON and that format is thought
51 | > to be machine readable, its structure is not to be considered part
52 | > of the interface. Format can change between different Barman versions.
53 |
54 |
55 | ## `list-server`
56 |
57 | You can display the list of active servers that have been configured
58 | for your backup system with:
59 |
60 | ``` bash
61 | barman list-server
62 | ```
63 |
64 | A machine readble output can be obtained with the `--minimal` option:
65 |
66 | ``` bash
67 | barman list-server --minimal
68 | ```
69 |
--------------------------------------------------------------------------------
/doc/manual/24-wal_archiving.en.md:
--------------------------------------------------------------------------------
1 | ## WAL archiving via `archive_command`
2 |
3 | The `archive_command` is the traditional method to archive WAL files.
4 |
5 | The value of this PostgreSQL configuration parameter must be a shell
6 | command to be executed by the PostgreSQL server to copy the WAL files
7 | to the Barman incoming directory.
8 |
9 | You can retrieve the incoming WALs directory using the `show-server`
10 | Barman command and looking for the `incoming_wals_directory` value:
11 |
12 | ``` bash
13 | barman@backup$ barman show-server pg |grep incoming_wals_directory
14 | incoming_wals_directory: /var/lib/barman/pg/incoming
15 | ```
16 |
17 | > **IMPORTANT:**
18 | > PostgreSQL 9.5 introduced support for WAL file archiving using
19 | > `archive_command` from a standby. This feature is not yet implemented
20 | > in Barman.
21 |
22 | Edit the `postgresql.conf` file of the PostgreSQL instance on the `pg`
23 | database and activate the archive mode:
24 |
25 | ``` ini
26 | archive_mode = on
27 | wal_level = 'replica'
28 | archive_command = 'rsync -a %p barman@backup:INCOMING_WALS_DIRECTORY/%f'
29 | ```
30 |
31 | Make sure you change the `INCOMING_WALS_DIRECTORY` placeholder with
32 | the value returned by the `barman show-server pg` command above.
33 |
34 | Restart the PostgreSQL server.
35 |
36 | In order to test that continuous archiving is on and properly working,
37 | you need to check both the PostgreSQL server and the backup server. In
38 | particular, you need to check that WAL files are correctly collected
39 | in the destination directory.
40 |
41 |
42 | ## Verification of WAL archiving configuration
43 |
44 | In order to improve the verification of the WAL archiving process, the
45 | `switch-xlog` command has been developed:
46 |
47 | ``` bash
48 | barman@backup$ barman switch-xlog --force --archive pg
49 | ```
50 |
51 | The above command will force PostgreSQL to switch WAL file and
52 | trigger the archiving process in Barman. Barman will wait for one
53 | file to arrive within 30 seconds (you can change the timeout through
54 | the `--archive-timeout` option). If no WAL file is received, an error
55 | is returned.
56 |
57 | You can verify if the WAL archiving has been correctly configured using
58 | the `barman check` command.
59 |
--------------------------------------------------------------------------------
/rpm/rhel5/python26-argh.spec:
--------------------------------------------------------------------------------
1 | # Use Python 2.6
2 | %global pybasever 2.6
3 | %global __python_ver 26
4 | %global __python %{_bindir}/python%{pybasever}
5 | %global __os_install_post %{__multiple_python_os_install_post}
6 |
7 | %{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
8 | %{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
9 |
10 | Summary: A simple argparse wrapper
11 | Name: python%{__python_ver}-argh
12 | Version: 0.23.0
13 | Release: 1%{?dist}
14 | License: LGPLv3
15 | Group: Development/Libraries
16 | Url: http://bitbucket.org/neithere/argh/
17 | Source0: http://pypi.python.org/packages/source/a/argh/argh-%{version}.tar.gz
18 | BuildRequires: python%{__python_ver}-devel,python%{__python_ver}-setuptools
19 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n)
20 | BuildArch: noarch
21 | Requires: python-abi = %(%{__python} -c "import sys ; print sys.version[:3]")
22 |
23 | %if "%{__python_ver}" == "26"
24 | Requires: python%{__python_ver}-argparse
25 | %endif
26 |
27 | %description
28 | Agrh, argparse!
29 | ===============
30 |
31 | Did you ever say "argh" trying to remember the details of optparse or argparse
32 | API? If yes, this package may be useful for you. It provides a very simple
33 | wrapper for argparse with support for hierarchical commands that can be bound
34 | to modules or classes. Argparse can do it; argh makes it easy.
35 |
36 | %prep
37 | %setup -n argh-%{version} -q
38 |
39 | %build
40 | %{__python} setup.py build
41 |
42 | %install
43 | %{__python} setup.py install -O1 --skip-build --root $RPM_BUILD_ROOT
44 |
45 | %clean
46 | rm -rf $RPM_BUILD_ROOT
47 |
48 | %files
49 | %defattr(-,root,root)
50 | %doc README
51 | %{python_sitelib}/argh-%{version}-py%{pybasever}.egg-info
52 | %{python_sitelib}/argh/
53 |
54 | %changelog
55 | * Thu Jan 31 2013 - Marco Neciarini 0.23.0-1
56 | - Update to version 0.23.0
57 |
58 | * Wed May 9 2012 - Marco Neciarini 0.15.0-1
59 | - Update to version 0.15.0
60 |
61 | * Sat Dec 4 2011 - Marco Neciarini 0.14.2-1
62 | - Initial packaging.
63 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | Barman, Backup and Recovery Manager for PostgreSQL
2 | ==================================================
3 |
4 | Barman (Backup and Recovery Manager) is an open-source administration
5 | tool for disaster recovery of PostgreSQL servers written in Python. It
6 | allows your organisation to perform remote backups of multiple servers
7 | in business critical environments to reduce risk and help DBAs during
8 | the recovery phase.
9 |
10 | Barman is distributed under GNU GPL 3 and maintained by 2ndQuadrant.
11 |
12 | For further information, look at the "Web resources" section below.
13 |
14 | Source content
15 | --------------
16 |
17 | Here you can find a description of files and directory distributed with
18 | Barman:
19 |
20 | - AUTHORS : development team of Barman
21 | - NEWS : release notes
22 | - ChangeLog : log of changes
23 | - LICENSE : GNU GPL3 details
24 | - TODO : our wishlist for Barman
25 | - barman : sources in Python
26 | - doc : tutorial and man pages
27 | - rpm : SPEC files for RHEL distributions
28 | - scripts : auxiliary scripts
29 | - tests : unit tests
30 |
31 | Web resources
32 | -------------
33 |
34 | - Website : http://www.pgbarman.org/
35 | - Download : http://sourceforge.net/projects/pgbarman/files/
36 | - Documentation : http://www.pgbarman.org/documentation/
37 | - Man page, section 1 : http://docs.pgbarman.org/barman.1.html
38 | - Man page, section 5 : http://docs.pgbarman.org/barman.5.html
39 | - Community support : http://www.pgbarman.org/support/
40 | - Professional support : http://www.2ndquadrant.com/
41 | - Client utilities : https://github.com/2ndquadrant-it/barman-cli
42 | - pgespresso extension : https://github.com/2ndquadrant-it/pgespresso
43 |
44 | Licence
45 | -------
46 |
47 | Copyright (C) 2011-2016 2ndQuadrant Italia Srl
48 |
49 | Barman is free software: you can redistribute it and/or modify it under
50 | the terms of the GNU General Public License as published by the Free
51 | Software Foundation, either version 3 of the License, or (at your
52 | option) any later version.
53 |
54 | Barman is distributed in the hope that it will be useful, but WITHOUT
55 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
56 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
57 | more details.
58 |
59 | You should have received a copy of the GNU General Public License along
60 | with Barman. If not, see http://www.gnu.org/licenses/.
61 |
--------------------------------------------------------------------------------
/rpm/rhel5/python26-argcomplete.spec:
--------------------------------------------------------------------------------
1 | # Use Python 2.6
2 | %global pybasever 2.6
3 | %global __python_ver 26
4 | %global __python %{_bindir}/python%{pybasever}
5 | %global __os_install_post %{__multiple_python_os_install_post}
6 |
7 | %{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
8 | %{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
9 |
10 | Summary: Bash tab completion for argparse
11 | Name: python%{__python_ver}-argcomplete
12 | Version: 0.3.5
13 | Release: 1%{?dist}
14 | License: ASL 2.0
15 | Group: Development/Libraries
16 | Url: https://github.com/kislyuk/argcomplete
17 | Source0: http://pypi.python.org/packages/source/a/argcomplete/argcomplete-%{version}.tar.gz
18 | BuildRequires: python%{__python_ver}-devel,python%{__python_ver}-setuptools
19 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n)
20 | BuildArch: noarch
21 | Requires: python-abi = %(%{__python} -c "import sys ; print sys.version[:3]")
22 |
23 | %if "%{__python_ver}" == "26"
24 | Requires: python%{__python_ver}-argparse
25 | %endif
26 |
27 | %description
28 | Argcomplete provides easy, extensible command line tab completion of
29 | arguments for your Python script.
30 |
31 | It makes two assumptions:
32 |
33 | * You're using bash as your shell
34 | * You're using argparse to manage your command line arguments/options
35 |
36 | Argcomplete is particularly useful if your program has lots of
37 | options or subparsers, and if your program can dynamically suggest
38 | completions for your argument/option values (for example, if the user
39 | is browsing resources over the network).
40 |
41 | %prep
42 | %setup -n argcomplete-%{version} -q
43 |
44 | %build
45 | %{__python} setup.py build
46 |
47 | %install
48 | %{__python} setup.py install -O1 --skip-build --root $RPM_BUILD_ROOT
49 |
50 | %clean
51 | rm -rf $RPM_BUILD_ROOT
52 |
53 | %files
54 | %defattr(-,root,root)
55 | %doc README.rst
56 | %{python_sitelib}/argcomplete-%{version}-py%{pybasever}.egg-info
57 | %{python_sitelib}/argcomplete/
58 | %{_bindir}/activate-global-python-argcomplete
59 | %{_bindir}/python-argcomplete-check-easy-install-script
60 | %{_bindir}/register-python-argcomplete
61 |
62 | %changelog
63 | * Thu Jan 31 2013 - Marco Neciarini 0.3.5-1
64 | - Initial packaging.
65 |
--------------------------------------------------------------------------------
/barman/remote_status.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2011-2016 2ndQuadrant Italia Srl
2 | #
3 | # This file is part of Barman.
4 | #
5 | # Barman is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Barman is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Barman. If not, see .
17 |
18 | """
19 | Remote Status module
20 |
21 | A Remote Status class implements a standard interface for
22 | retrieving and caching the results of a remote component
23 | (such as Postgres server, WAL archiver, etc.). It follows
24 | the Mixin pattern.
25 | """
26 |
27 | from abc import ABCMeta, abstractmethod
28 |
29 | from barman.utils import with_metaclass
30 |
31 |
32 | class RemoteStatusMixin(with_metaclass(ABCMeta, object)):
33 | """
34 | Abstract base class that implements remote status capabilities
35 | following the Mixin pattern.
36 | """
37 |
38 | def __init__(self, *args, **kwargs):
39 | """
40 | Base constructor (Mixin pattern)
41 | """
42 | self._remote_status = None
43 | super(RemoteStatusMixin, self).__init__(*args, **kwargs)
44 |
45 | @abstractmethod
46 | def fetch_remote_status(self):
47 | """
48 | Retrieve status information from the remote component
49 |
50 | The implementation of this method must not raise any exception in case
51 | of errors, but should set the missing values to None in the resulting
52 | dictionary.
53 |
54 | :rtype: dict[str, None|str]
55 | """
56 |
57 | def get_remote_status(self):
58 | """
59 | Get the status of the remote component
60 |
61 | This method does not raise any exception in case of errors,
62 | but set the missing values to None in the resulting dictionary.
63 |
64 | :rtype: dict[str, None|str]
65 | """
66 | if self._remote_status is None:
67 | self._remote_status = self.fetch_remote_status()
68 | return self._remote_status
69 |
70 | def reset_remote_status(self):
71 | """
72 | Reset the cached result
73 | """
74 | self._remote_status = None
75 |
--------------------------------------------------------------------------------
/doc/manual/15-system_requirements.en.md:
--------------------------------------------------------------------------------
1 | \newpage
2 |
3 | # System requirements
4 |
5 | - Linux/Unix
6 | - Python 2.6 or 2.7
7 | - Python modules:
8 | - argcomplete
9 | - argh >= 0.21.2 <= 0.26.2
10 | - argparse (Python 2.6 only)
11 | - psycopg2 >= 2.4.2
12 | - python-dateutil <> 2.0
13 | - setuptools
14 | - PostgreSQL >= 8.3
15 | - rsync >= 3.0.4 (optional for PostgreSQL >= 9.2)
16 |
17 | > **IMPORTANT:**
18 | > Users of RedHat Enterprise Linux, CentOS and Scientific Linux are
19 | > required to install the
20 | > [Extra Packages Enterprise Linux (EPEL) repository] [epel].
21 |
22 | > **NOTE:**
23 | > Python 3 support is experimental. Report any bug through
24 | > the ticketing system on Github or the mailing list.
25 |
26 | ## Requirements for backup
27 |
28 | The most critical requirement for a Barman server is the amount of disk space available.
29 | You are recommended to plan the required disk space based on the size of the cluster, number of WAL files generated per day, frequency of backups, and retention policies.
30 |
31 | Although the only file systems that we officially support are XFS and Ext4, we are aware of users that deploy Barman on different file systems including ZFS and NFS.
32 |
33 | ## Requirements for recovery
34 |
35 | Barman allows you to recover a PostgreSQL instance either
36 | locally (where Barman resides) or remotely (on a separate server).
37 |
38 | Remote recovery is definitely the most common way to restore a PostgreSQL
39 | server with Barman.
40 |
41 | Either way, the same [requirements for PostgreSQL's Log shipping and Point-In-Time-Recovery apply] [requirements_recovery]:
42 |
43 | - identical hardware architecture
44 | - identical major version of PostgreSQL
45 |
46 | In general, it is **highly recommended** to create recovery environments that are as similar as possible, if not identical, to the original server, because they are easier to maintain. For example, we suggest that you use the same operating system, the same PostgreSQL version, the same disk layouts, and so on.
47 |
48 | Additionally, dedicated recovery environments for each PostgreSQL server, even on demand, allows you to nurture the disaster recovery culture in your team. You can be prepared for when something unexpected happens by practising
49 | recovery operations and becoming familiar with them.
50 |
51 | Based on our experience, designated recovery environments reduce the impact of stress in real failure situations, and therefore increase the effectiveness of recovery operations.
52 |
53 | Finally, it is important that time is synchronised between the servers, using NTP for example.
54 |
--------------------------------------------------------------------------------
/sphinx/README.md:
--------------------------------------------------------------------------------
1 | # Generate sphinx documentation
2 |
3 | Generate barman code documentation using Sphinx autodoc
4 |
5 | ## Prerequisites
6 |
7 | Install the python modules required to build the documentation
8 | by executing, from the root directory of Barman:
9 |
10 | ``` bash
11 | pip install -r sphinx/requirements.txt
12 | ```
13 |
14 | ## Documentation generation
15 |
16 | From the root folder of Barman, launch:
17 |
18 | ``` bash
19 | sphinx/generate_docs.sh
20 | ```
21 |
22 |
23 | ### `generate_docs.sh` options
24 |
25 | Is possible to use a different path to the barman source files
26 | directory (default: the current barman source directory) passing it
27 | as argument to the `generate_docs.sh` script.
28 |
29 | ``` bash
30 | sphinx/generate_docs.sh
31 | ```
32 |
33 | It's also possible to pass the target format (default: `html`)
34 | to the generate_docs.sh script using the -t option followed by
35 | one of the available formats:
36 |
37 | * html to make standalone HTML files
38 | * dirhtml to make HTML files named index.html in directories
39 | * singlehtml to make a single large HTML file
40 | * pickle to make pickle files
41 | * json to make JSON files
42 | * htmlhelp to make HTML files and a HTML help project
43 | * qthelp to make HTML files and a qthelp project
44 | * devhelp to make HTML files and a Devhelp project
45 | * epub to make an epub
46 | * latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
47 | * latexpdf to make LaTeX files and run them through pdflatex
48 | * text to make text files
49 | * man to make manual pages
50 | * texinfo to make Texinfo files
51 | * info to make Texinfo files and run them through makeinfo
52 | * gettext to make PO message catalogs
53 | * changes to make an overview of all changed/added/deprecated items
54 | * linkcheck to check all external links for integrity
55 | * doctest to run all doctests embedded in the documentation (if enabled)
56 |
57 | ## Licence
58 |
59 | Copyright (C) 2011-2016 2ndQuadrant Italia Srl
60 |
61 | Barman is free software: you can redistribute it and/or modify
62 | it under the terms of the GNU General Public License as published by
63 | the Free Software Foundation, either version 3 of the License, or
64 | (at your option) any later version.
65 |
66 | Barman is distributed in the hope that it will be useful,
67 | but WITHOUT ANY WARRANTY; without even the implied warranty of
68 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
69 | GNU General Public License for more details.
70 |
71 | You should have received a copy of the GNU General Public License
72 | along with Barman. If not, see .
73 |
--------------------------------------------------------------------------------
/sphinx/docs/index.rst:
--------------------------------------------------------------------------------
1 |
2 | .. Copyright (C) 2011-2016 2ndQuadrant Italia Srl
3 | Barman is free software: you can redistribute it and/or modify
4 | it under the terms of the GNU General Public License as published by
5 | the Free Software Foundation, either version 3 of the License, or
6 | (at your option) any later version.
7 | Barman is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 | You should have received a copy of the GNU General Public License
12 | along with Barman. If not, see .
13 |
14 |
15 | Welcome to barman |version|
16 | ===========================
17 |
18 | Barman (Backup and Recovery Manager) is an open-source administration
19 | tool for disaster recovery of PostgreSQL servers written in Python.
20 | It allows your organisation to perform remote backups of multiple
21 | servers in business critical environments to reduce risk and help DBAs
22 | during the recovery phase.
23 |
24 | Barman is distributed under GNU GPL 3 and maintained by 2ndQuadrant.
25 |
26 | For further information, look at the "Web resources" section below.
27 |
28 | Contents:
29 |
30 | .. toctree::
31 | :maxdepth: 4
32 |
33 | barman
34 |
35 | Web resources
36 | =============
37 |
38 | * Website : http://www.pgbarman.org/
39 | * Download : http://sourceforge.net/projects/pgbarman/files/
40 | * Documentation : http://www.pgbarman.org/documentation/
41 | * Man page, section 1 : http://docs.pgbarman.org/barman.1.html
42 | * Man page, section 5 : http://docs.pgbarman.org/barman.5.html
43 | * Community support : http://www.pgbarman.org/support/
44 | * Professional support : http://www.2ndquadrant.com/
45 | * Client utilities : https://github.com/2ndquadrant-it/barman-cli
46 | * pgespresso extension : https://github.com/2ndquadrant-it/pgespresso
47 |
48 | Licence
49 | =======
50 |
51 | Copyright (C) 2011-2016 2ndQuadrant Italia Srl
52 |
53 | Barman is free software: you can redistribute it and/or modify
54 | it under the terms of the GNU General Public License as published by
55 | the Free Software Foundation, either version 3 of the License, or
56 | (at your option) any later version.
57 |
58 | Barman is distributed in the hope that it will be useful,
59 | but WITHOUT ANY WARRANTY; without even the implied warranty of
60 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
61 | GNU General Public License for more details.
62 |
63 | You should have received a copy of the GNU General Public License
64 | along with Barman. If not, see .
65 |
66 |
67 | Indices and tables
68 | ==================
69 |
70 | * :ref:`genindex`
71 | * :ref:`modindex`
72 | * :ref:`search`
73 |
--------------------------------------------------------------------------------
/doc/manual/99-references.en.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | [rpo]: https://en.wikipedia.org/wiki/Recovery_point_objective
4 | [rto]: https://en.wikipedia.org/wiki/Recovery_time_objective
5 | [repmgr]: http://www.repmgr.org/
6 | [sqldump]: https://www.postgresql.org/docs/current/static/backup-dump.html
7 | [recoveryconfig]: https://www.postgresql.org/docs/current/static/recovery-config.html
8 | [physicalbackup]: https://www.postgresql.org/docs/current/static/backup-file.html
9 | [pitr]: https://www.postgresql.org/docs/current/static/continuous-archiving.html
10 | [adminbook]: http://www.2ndquadrant.com/en/books/postgresql-9-administration-cookbook/
11 | [wal]: https://www.postgresql.org/docs/current/static/wal.html
12 | [49340627f9821e447f135455d942f7d5e96cae6d]: https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=49340627f9821e447f135455d942f7d5e96cae6d
13 | [requirements_recovery]: https://www.postgresql.org/docs/current/static/warm-standby.html#STANDBY-PLANNING
14 | [yumpgdg]: http://yum.postgresql.org/
15 | [aptpgdg]: http://apt.postgresql.org/
16 | [aptpgdgwiki]: https://wiki.postgresql.org/wiki/Apt
17 | [epel]: http://fedoraproject.org/wiki/EPEL
18 | [man5]: http://docs.pgbarman.org/barman.5.html
19 | [setup_user]: https://docs.python.org/3/install/index.html#alternate-installation-the-user-scheme
20 | [pypi]: https://pypi.python.org/pypi/barman/
21 | [pgpass]: https://www.postgresql.org/docs/current/static/libpq-pgpass.html
22 | [pghba]: http://www.postgresql.org/docs/current/static/client-authentication.html
23 | [authpghba]: http://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html
24 | [streamprot]: http://www.postgresql.org/docs/current/static/protocol-replication.html
25 | [roles]: http://www.postgresql.org/docs/current/static/role-attributes.html
26 | [replication-slots]: https://www.postgresql.org/docs/current/static/warm-standby.html#STREAMING-REPLICATION-SLOTS
27 | [synch]: http://www.postgresql.org/docs/current/static/warm-standby.html#SYNCHRONOUS-REPLICATION
28 |
29 |
30 |
31 |
32 | [3]: https://sourceforge.net/projects/pgbarman/files/
33 | [8]: http://en.wikipedia.org/wiki/Hard_link
34 | [9]: https://github.com/2ndquadrant-it/pgespresso
35 | [11]: http://www.pgbarman.org/
36 | [12]: http://www.pgbarman.org/support/
37 | [13]: http://www.2ndquadrant.com/
38 | [14]: http://www.pgbarman.org/faq/
39 | [15]: http://blog.2ndquadrant.com/tag/barman/
40 | [16]: https://github.com/hamann/check-barman
41 | [17]: https://github.com/2ndquadrant-it/puppet-barman
42 | [18]: http://4caast.morfeo-project.org/
43 | [19]: http://www.2ndquadrant.it/
44 | [20]: http://www.postgresql.org/docs/current/static/functions-admin.html
45 | [24]: http://www.postgresql.org/docs/current/static/warm-standby.html#STREAMING-REPLICATION
46 | [25]: http://www.postgresql.org/docs/current/static/app-pgreceivexlog.html
47 | [26]: https://goo.gl/218Ghl
48 | [27]: https://github.com/emin100/barmanapi
49 |
50 | [31]: http://www.postgresql.org/
51 |
--------------------------------------------------------------------------------
/barman/diagnose.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2011-2016 2ndQuadrant Italia Srl
2 | #
3 | # This file is part of Barman.
4 | #
5 | # Barman is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Barman is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Barman. If not, see .
17 |
18 | """
19 | This module represents the barman diagnostic tool.
20 | """
21 |
22 | import json
23 | import logging
24 | import sys
25 |
26 | import barman
27 | from barman import fs, output
28 | from barman.backup import BackupInfo
29 | from barman.exceptions import FsOperationFailed
30 | from barman.utils import BarmanEncoder
31 |
32 | _logger = logging.getLogger(__name__)
33 |
34 |
35 | def exec_diagnose(servers, errors_list):
36 | """
37 | Diagnostic command: gathers information from backup server
38 | and from all the configured servers.
39 |
40 | Gathered information should be used for support and problems detection
41 |
42 | :param dict(str,barman.server.Server) servers: list of configured servers
43 | :param list errors_list: list of global errors
44 | """
45 | # global section. info about barman server
46 | diagnosis = {'global': {}, 'servers': {}}
47 | # barman global config
48 | diagnosis['global']['config'] = dict(barman.__config__._global_config)
49 | diagnosis['global']['config']['errors_list'] = errors_list
50 | command = fs.UnixLocalCommand()
51 | # basic system info
52 | diagnosis['global']['system_info'] = command.get_system_info()
53 | diagnosis['global']['system_info']['barman_ver'] = barman.__version__
54 | # per server section
55 | for name in sorted(servers):
56 | server = servers[name]
57 | if server is None:
58 | output.error("Unknown server '%s'" % name)
59 | continue
60 | # server configuration
61 | diagnosis['servers'][name] = {}
62 | diagnosis['servers'][name]['config'] = vars(server.config)
63 | del diagnosis['servers'][name]['config']['config']
64 | # server system info
65 | if server.config.ssh_command:
66 | try:
67 | command = fs.UnixRemoteCommand(
68 | ssh_command=server.config.ssh_command,
69 | path=server.path
70 | )
71 | diagnosis['servers'][name]['system_info'] = (
72 | command.get_system_info())
73 | except FsOperationFailed:
74 | pass
75 | # barman statuts information for the server
76 | diagnosis['servers'][name]['status'] = server.get_remote_status()
77 | # backup list
78 | backups = server.get_available_backups(BackupInfo.STATUS_ALL)
79 | diagnosis['servers'][name]['backups'] = backups
80 | # wal status
81 | diagnosis['servers'][name]['wals'] = {
82 | 'last_archived_wal_per_timeline':
83 | server.backup_manager.get_latest_archived_wals_info(),
84 | }
85 | # Release any PostgreSQL resource
86 | server.close()
87 | output.info(json.dumps(diagnosis, sys.stdout, cls=BarmanEncoder, indent=4,
88 | sort_keys=True))
89 |
--------------------------------------------------------------------------------
/doc/manual/16-installation.en.md:
--------------------------------------------------------------------------------
1 | \newpage
2 |
3 | # Installation
4 |
5 | > **IMPORTANT:**
6 | > The recommended way to install Barman is by using the available
7 | > packages for your GNU/Linux distribution.
8 |
9 | ## Installation on RedHat/CentOS using RPM packages
10 |
11 | Barman can be installed on RHEL7, RHEL6 and RHEL5 Linux systems using
12 | RPM packages. It is required to install the Extra Packages Enterprise
13 | Linux (EPEL) repository beforehand.
14 |
15 | RPM packages for Barman are available via Yum through the
16 | [PostgreSQL Global Development Group RPM repository] [yumpgdg].
17 | You need to follow the instructions for your distribution (for example RedHat,
18 | CentOS, or Fedora) and architecture as detailed at
19 | [yum.postgresql.org] [yumpgdg].
20 |
21 | Then, as `root` simply type:
22 |
23 | ``` bash
24 | yum install barman
25 | ```
26 |
27 | 2ndQuadrant also maintains RPM packages for Barman and distributes
28 | them through [Sourceforge.net] [3].
29 |
30 | ## Installation on Debian/Ubuntu using packages
31 |
32 | Barman can be installed on Debian and Ubuntu Linux systems using
33 | packages.
34 |
35 | It is directly available in the official repository for Debian and Ubuntu, however, these repositories might not contain the latest available version.
36 | If you want to have the latest version of Barman, the recommended method is to install it through the [PostgreSQL Community APT repository] [aptpgdg].
37 | Instructions can be found in the [APT section of the PostgreSQL Wiki] [aptpgdgwiki].
38 |
39 | > **NOTE:**
40 | > Thanks to the direct involvement of Barman developers in the
41 | > PostgreSQL Community APT repository project, you will always have access
42 | > to the most updated versions of Barman.
43 |
44 | Installing Barman is as easy. As `root` user simply type:
45 |
46 | ``` bash
47 | apt-get install barman
48 | ```
49 |
50 | ## Installation from sources
51 |
52 | > **WARNING:**
53 | > Manual installation of Barman from sources should only be performed
54 | > by expert GNU/Linux users. Installing Barman this way requires
55 | > system administration activities such as dependencies management,
56 | > `barman` user creation, configuration of the `barman.conf` file,
57 | > cron setup for the `barman cron` command, log management, and so on.
58 |
59 | Create a system user called `barman` on the `backup` server.
60 | As `barman` user, download the sources and uncompress them.
61 |
62 | For a system-wide installation, type:
63 |
64 | ``` bash
65 | barman@backup$ ./setup.py build
66 | # run this command with root privileges or through sudo
67 | barman@backup# ./setup.py install
68 | ```
69 |
70 | For a local installation, type:
71 |
72 | ``` bash
73 | barman@backup$ ./setup.py install --user
74 | ```
75 |
76 | The `barman` application will be installed in your user directory ([make sure that your `PATH` environment variable is set properly] [setup_user]).
77 |
78 | [Barman is also available on the Python Package Index (PyPI)] [pypi] and can be installed through `pip`.
79 |
80 | ## Upgrading from Barman 1.X
81 |
82 | Version 2.0 requires that users explicitly configure
83 | their archiving strategy. Before, the file based
84 | archiver, controlled by `archiver`, was enabled by default.
85 |
86 | When you upgrade your Barman installation to 2.0, make sure
87 | you add the following line either globally or for any server
88 | that requires it:
89 |
90 | ``` ini
91 | archiver = on
92 | ```
93 |
94 | Additionally, for a few releases, Barman will transparently set
95 | `archiver = on` with any server that has not explicitly set
96 | an archiving strategy and emit a warning.
97 |
98 | Besides that, version 2.0 is fully compatible with older ones.
99 |
--------------------------------------------------------------------------------
/doc/manual/17-configuration.en.md:
--------------------------------------------------------------------------------
1 | \newpage
2 |
3 | # Configuration
4 |
5 | There are two types of configuration files in Barman:
6 |
7 | - **global/general configuration**
8 | - **server configuration**
9 |
10 | The main configuration file (set to `/etc/barman.conf` by default) contains general options such as main directory, system user, log file, and so on.
11 |
12 | Server configuration files, one for each server to be backed up by Barman, are located in the `/etc/barman.d` directory and must have a `.conf` suffix.
13 |
14 | > **IMPORTANT**: For historical reasons, you can still have one single
15 | > configuration file containing both global and server options. However,
16 | > for maintenance reasons, this approach is deprecated.
17 |
18 | Configuration files in Barman follow the _INI_ format.
19 |
20 | ## Options scope
21 |
22 | Every configuration option has a _scope_:
23 |
24 | - global
25 | - server
26 | - global/server: server options that can be generally set at global level
27 |
28 | Global options are allowed in the _general section_, which is identified in the INI file by the `[barman]` label:
29 |
30 | ``` ini
31 | [barman]
32 | ; ... global and global/server options go here
33 | ```
34 |
35 | Server options can only be specified in a _server section_, which is identified by a line in the configuration file, in square brackets (`[` and `]`). The server section represents the ID of that server in Barman. The following example specifies a section for the server named `pg`:
36 |
37 | ``` ini
38 | [pg]
39 | ; Configuration options for the
40 | ; server named 'pg' go here
41 | ```
42 |
43 | There are two reserved words that cannot be used as server names in Barman:
44 |
45 | - `barman`: identifier of the global section
46 | - `all`: a handy shortcut that allows you to execute some commands on every server managed by Barman in sequence
47 |
48 | Barman implements the **convention over configuration** design paradigm, which attempts to reduce the number of options that you are required to configure without losing flexibility. Therefore, some server options can be defined at global level and overridden at server level, allowing users to specify a generic behavior and refine it for one or more servers. These options have a global/server scope.
49 |
50 | For a list of all the available configurations
51 | and their scope, please refer to [section 5 of the 'man' page] [man5].
52 |
53 | ``` bash
54 | man 5 barman
55 | ```
56 |
57 | ## Examples of configuration
58 |
59 | The following is a basic example of main configuration file:
60 |
61 | ``` ini
62 | [barman]
63 | barman_user = barman
64 | configuration_files_directory = /etc/barman.d
65 | barman_home = /var/lib/barman
66 | log_file = /var/log/barman/barman.log
67 | log_level = INFO
68 | compression = gzip
69 | ```
70 |
71 | The example below, on the other hand, is a server configuration file that uses streaming backup:
72 |
73 | ``` ini
74 | [streaming-pg]
75 | description = "Example of PostgreSQL Database (Streaming-Only)"
76 | conninfo = host=pg user=barman dbname=postgres
77 | streaming_conninfo = host=pg user=streaming_barman
78 | backup_method = postgres
79 | streaming_archiver = on
80 | slot_name = barman
81 | ```
82 |
83 | The following code shows a basic example of traditional backup using `rsync`/SSH:
84 |
85 | ``` ini
86 | [ssh-pg]
87 | description = "Example of PostgreSQL Database (via Ssh)"
88 | ssh_command = ssh postgres@pg
89 | conninfo = host=pg user=barman dbname=postgres
90 | backup_method = rsync
91 | reuse_backup = link
92 | archiver = on
93 | ```
94 |
95 | For more detailed information, please refer to the distributed
96 | `barman.conf` file, as well as the `ssh-server.conf-template` and `streaming-server.conf-template` template files.
97 |
--------------------------------------------------------------------------------
/rpm/rhel5/python-dateutil-1.4.1-remove-embedded-timezone-data.patch:
--------------------------------------------------------------------------------
1 | diff -up python-dateutil-1.4.1/dateutil/tz.py.remove-embedded-timezone-data python-dateutil-1.4.1/dateutil/tz.py
2 | --- python-dateutil-1.4.1/dateutil/tz.py.remove-embedded-timezone-data 2008-02-27 20:45:41.000000000 -0500
3 | +++ python-dateutil-1.4.1/dateutil/tz.py 2010-07-13 14:40:30.228122861 -0400
4 | @@ -930,9 +930,6 @@ def gettz(name=None):
5 | except OSError:
6 | pass
7 | if not tz:
8 | - from dateutil.zoneinfo import gettz
9 | - tz = gettz(name)
10 | - if not tz:
11 | for c in name:
12 | # name must have at least one offset to be a tzstr
13 | if c in "0123456789":
14 | diff -up python-dateutil-1.4.1/dateutil/zoneinfo/__init__.py.remove-embedded-timezone-data python-dateutil-1.4.1/dateutil/zoneinfo/__init__.py
15 | --- python-dateutil-1.4.1/dateutil/zoneinfo/__init__.py.remove-embedded-timezone-data 2005-12-22 13:13:50.000000000 -0500
16 | +++ python-dateutil-1.4.1/dateutil/zoneinfo/__init__.py 2010-07-13 14:40:30.228122861 -0400
17 | @@ -3,6 +3,10 @@ Copyright (c) 2003-2005 Gustavo Niemeye
18 |
19 | This module offers extensions to the standard python 2.3+
20 | datetime module.
21 | +
22 | +This version of the code has been modified to remove the embedded copy
23 | +of zoneinfo-2008e.tar.gz and instead use the system data from the tzdata
24 | +package
25 | """
26 | from dateutil.tz import tzfile
27 | from tarfile import TarFile
28 | @@ -13,49 +17,12 @@ __license__ = "PSF License"
29 |
30 | __all__ = ["setcachesize", "gettz", "rebuild"]
31 |
32 | -CACHE = []
33 | -CACHESIZE = 10
34 | -
35 | -class tzfile(tzfile):
36 | - def __reduce__(self):
37 | - return (gettz, (self._filename,))
38 | -
39 | -def getzoneinfofile():
40 | - filenames = os.listdir(os.path.join(os.path.dirname(__file__)))
41 | - filenames.sort()
42 | - filenames.reverse()
43 | - for entry in filenames:
44 | - if entry.startswith("zoneinfo") and ".tar." in entry:
45 | - return os.path.join(os.path.dirname(__file__), entry)
46 | - return None
47 | -
48 | -ZONEINFOFILE = getzoneinfofile()
49 | -
50 | -del getzoneinfofile
51 | -
52 | def setcachesize(size):
53 | - global CACHESIZE, CACHE
54 | - CACHESIZE = size
55 | - del CACHE[size:]
56 | + pass
57 |
58 | def gettz(name):
59 | - tzinfo = None
60 | - if ZONEINFOFILE:
61 | - for cachedname, tzinfo in CACHE:
62 | - if cachedname == name:
63 | - break
64 | - else:
65 | - tf = TarFile.open(ZONEINFOFILE)
66 | - try:
67 | - zonefile = tf.extractfile(name)
68 | - except KeyError:
69 | - tzinfo = None
70 | - else:
71 | - tzinfo = tzfile(zonefile)
72 | - tf.close()
73 | - CACHE.insert(0, (name, tzinfo))
74 | - del CACHE[CACHESIZE:]
75 | - return tzinfo
76 | + from dateutil.tz import gettz
77 | + return gettz(name)
78 |
79 | def rebuild(filename, tag=None, format="gz"):
80 | import tempfile, shutil
81 | diff -up python-dateutil-1.4.1/MANIFEST.in.remove-embedded-timezone-data python-dateutil-1.4.1/MANIFEST.in
82 | --- python-dateutil-1.4.1/MANIFEST.in.remove-embedded-timezone-data 2010-07-13 14:42:07.974118722 -0400
83 | +++ python-dateutil-1.4.1/MANIFEST.in 2010-07-13 14:42:14.409994960 -0400
84 | @@ -1,4 +1,4 @@
85 | -recursive-include dateutil *.py *.tar.*
86 | +recursive-include dateutil *.py
87 | recursive-include sandbox *.py
88 | include setup.py setup.cfg MANIFEST.in README LICENSE NEWS Makefile
89 | include test.py example.py
90 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # barman - Backup and Recovery Manager for PostgreSQL
4 | #
5 | # Copyright (C) 2011-2016 2ndQuadrant Italia Srl
6 | #
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with this program. If not, see .
19 |
20 | """Backup and Recovery Manager for PostgreSQL
21 |
22 | Barman (Backup and Recovery Manager) is an open-source administration
23 | tool for disaster recovery of PostgreSQL servers written in Python.
24 | It allows your organisation to perform remote backups of multiple
25 | servers in business critical environments to reduce risk and help DBAs
26 | during the recovery phase.
27 |
28 | Barman is distributed under GNU GPL 3 and maintained by 2ndQuadrant.
29 | """
30 |
31 | import sys
32 |
33 | try:
34 | from setuptools import setup
35 | except ImportError:
36 | from distutils.core import setup
37 |
38 | if sys.version_info < (2, 6):
39 | raise SystemExit('ERROR: Barman needs at least python 2.6 to work')
40 |
41 | # Depend on pytest_runner only when the tests are actually invoked
42 | needs_pytest = set(['pytest', 'test']).intersection(sys.argv)
43 | pytest_runner = ['pytest_runner'] if needs_pytest else []
44 |
45 | setup_requires = pytest_runner
46 |
47 | install_requires = [
48 | 'psycopg2 >= 2.4.2',
49 | 'argh >= 0.21.2, <= 0.26.2',
50 | 'python-dateutil',
51 | 'argcomplete',
52 | ]
53 |
54 | if sys.version_info < (2, 7):
55 | install_requires += [
56 | 'argparse',
57 | ]
58 |
59 | if sys.version_info < (3, 3):
60 | install_requires.append('backports.lzma')
61 |
62 | barman = {}
63 | with open('barman/version.py', 'r') as fversion:
64 | exec(fversion.read(), barman)
65 |
66 | setup(
67 | name='barman',
68 | version=barman['__version__'],
69 | author='2ndQuadrant Italia Srl',
70 | author_email='info@2ndquadrant.it',
71 | url='http://www.pgbarman.org/',
72 | packages=['barman', ],
73 | scripts=['bin/barman', 'bin/barman-incr'],
74 | data_files=[
75 | ('share/man/man1', ['doc/barman.1']),
76 | ('share/man/man5', ['doc/barman.5']),
77 | ],
78 | license='GPL-3.0',
79 | description=__doc__.split("\n")[0],
80 | long_description="\n".join(__doc__.split("\n")[2:]),
81 | install_requires=install_requires,
82 | platforms=['Linux', 'Mac OS X'],
83 | classifiers=[
84 | 'Environment :: Console',
85 | 'Development Status :: 5 - Production/Stable',
86 | 'Topic :: System :: Archiving :: Backup',
87 | 'Topic :: Database',
88 | 'Topic :: System :: Recovery Tools',
89 | 'Intended Audience :: System Administrators',
90 | 'License :: OSI Approved :: GNU General Public License v3 or later '
91 | '(GPLv3+)',
92 | 'Programming Language :: Python',
93 | 'Programming Language :: Python :: 2.6',
94 | 'Programming Language :: Python :: 2.7',
95 | 'Programming Language :: Python :: 3.3',
96 | 'Programming Language :: Python :: 3.4',
97 | 'Programming Language :: Python :: 3.5',
98 | ],
99 | setup_requires=setup_requires,
100 | tests_require=[
101 | 'mock',
102 | 'pytest-catchlog>=1.2.1',
103 | 'pytest-timeout',
104 | 'pytest',
105 | ],
106 | )
107 |
--------------------------------------------------------------------------------
/doc/barman.conf:
--------------------------------------------------------------------------------
1 | ; Barman, Backup and Recovery Manager for PostgreSQL
2 | ; http://www.pgbarman.org/ - http://www.2ndQuadrant.com/
3 | ;
4 | ; Main configuration file
5 |
6 | [barman]
7 | ; System user
8 | barman_user = barman
9 |
10 | ; Directory of configuration files. Place your sections in separate files with .conf extension
11 | ; For example place the 'main' server section in /etc/barman.d/main.conf
12 | configuration_files_directory = /etc/barman.d
13 |
14 | ; Main directory
15 | barman_home = /var/lib/barman
16 |
17 | ; Locks directory - default: %(barman_home)s
18 | ;barman_lock_directory = /var/run/barman
19 |
20 | ; Log location
21 | log_file = /var/log/barman/barman.log
22 |
23 | ; Log level (see https://docs.python.org/3/library/logging.html#levels)
24 | log_level = INFO
25 |
26 | ; Default compression level: possible values are None (default), bzip2, gzip, pigz, pygzip or pybzip2
27 | ;compression = gzip
28 |
29 | ; Pre/post backup hook scripts
30 | ;pre_backup_script = env | grep ^BARMAN
31 | ;pre_backup_retry_script = env | grep ^BARMAN
32 | ;post_backup_retry_script = env | grep ^BARMAN
33 | ;post_backup_script = env | grep ^BARMAN
34 |
35 | ; Pre/post archive hook scripts
36 | ;pre_archive_script = env | grep ^BARMAN
37 | ;pre_archive_retry_script = env | grep ^BARMAN
38 | ;post_archive_retry_script = env | grep ^BARMAN
39 | ;post_archive_script = env | grep ^BARMAN
40 |
41 | ; Global retention policy (REDUNDANCY or RECOVERY WINDOW) - default empty
42 | ;retention_policy =
43 |
44 | ; Global bandwidth limit in KBPS - default 0 (meaning no limit)
45 | ;bandwidth_limit = 4000
46 |
47 | ; Immediate checkpoint for backup command - default false
48 | ;immediate_checkpoint = false
49 |
50 | ; Enable network compression for data transfers - default false
51 | ;network_compression = false
52 |
53 | ; Number of retries of data copy during base backup after an error - default 0
54 | ;basebackup_retry_times = 0
55 |
56 | ; Number of seconds of wait after a failed copy, before retrying - default 30
57 | ;basebackup_retry_sleep = 30
58 |
59 | ; Maximum execution time, in seconds, per server
60 | ; for a barman check command - default 30
61 | ;check_timeout = 30
62 |
63 | ; Time frame that must contain the latest backup date.
64 | ; If the latest backup is older than the time frame, barman check
65 | ; command will report an error to the user.
66 | ; If empty, the latest backup is always considered valid.
67 | ; Syntax for this option is: "i (DAYS | WEEKS | MONTHS)" where i is an
68 | ; integer > 0 which identifies the number of days | weeks | months of
69 | ; validity of the latest backup for this check. Also known as 'smelly backup'.
70 | ;last_backup_maximum_age =
71 |
72 | ; Minimum number of required backups (redundancy)
73 | ;minimum_redundancy = 1
74 |
75 | ; Examples of retention policies
76 | ; Retention policy (disabled)
77 | ;retention_policy =
78 | ; Retention policy (based on redundancy)
79 | ;retention_policy = REDUNDANCY 2
80 | ; Retention policy (based on recovery window)
81 | ;retention_policy = RECOVERY WINDOW OF 4 WEEKS
82 | ;;
83 | ;; ; Page-level incremental backups
84 | ;; ; Allow sequences of incremental backups (set to "full" to disable)
85 | ;; incr_allow_root = incr
86 | ;;
87 | ;; ; Compress backups with lzma -9 (gzip, bzip and none are also supported)
88 | ;; ; You could set compression level like this: -
89 | ;; ; Default level is 6
90 | ;; incr_compress = lzma-9
91 | ;;
92 | ;; ; Barman server hostname (socket.getfqdn() call result used by default)
93 | ;; incr_host = barman.example.com
94 | ;;
95 | ;; ; Max number of increments before taking full (6 - take full every week)
96 | ;; incr_max_increments = 6
97 | ;;
98 | ;; ; Number of workers for incr backup
99 | ;; incr_parallel = 1
100 | ;;
101 | ;; ; Pass additional options to rsync
102 | ;; incr_rsync_options = -a
103 | ;;
104 | ;; ; Pass relative path to barman-incr
105 | ;; ; If you announced /var/lib/barman via rsync as barman you need to set:
106 | ;; incr_rsync_relpath = /var/lib
107 | ;;
108 | ;; ; Pass extra args to barman-incr
109 | ;; incr_extra_args = -vvv
110 |
--------------------------------------------------------------------------------
/doc/manual/01-intro.en.md:
--------------------------------------------------------------------------------
1 | \newpage
2 |
3 | # Introduction
4 |
5 | In a perfect world, there would be no need for a backup. However, it is
6 | important, especially in business environments, to be prepared for
7 | when the _"unexpected"_ happens. In a database scenario, the
8 | unexpected could take any of the following forms:
9 |
10 | - data corruption
11 | - system failure (including hardware failure)
12 | - human error
13 | - natural disaster
14 |
15 | In such cases, any ICT manager or DBA should be able to fix the
16 | incident and recover the database in the shortest time possible. We
17 | normally refer to this discipline as **disaster recovery**, and more
18 | broadly *business continuity*.
19 |
20 | Within business continuity, it is important to familiarise with two fundamental metrics, as defined by Wikipedia:
21 |
22 | - [**Recovery Point Objective (RPO)**] [rpo]: _"maximum targeted period in which data might be lost from an IT service due to a major incident"_
23 | - [**Recovery Time Objective (RTO)**] [rto]: _"the targeted duration of time and a service level within which a business process must be restored after a disaster (or disruption) in order to avoid unacceptable consequences associated with a break in business continuity"_
24 |
25 |
26 | In a few words, RPO represents the maximum amount of data you can afford to lose, while RTO represents the maximum down-time you can afford for your service.
27 |
28 | Understandably, we all want **RPO=0** (*"zero data loss"*) and **RTO=0** (*zero down-time*, utopia) - even if it is our grandmothers's recipe website.
29 | In reality, a careful cost analysis phase allows you to determine your business continuity requirements.
30 |
31 | Fortunately, with an open source stack composed of **Barman** and **PostgreSQL**, you can achieve RPO=0 thanks to synchronous streaming replication. RTO is more the focus of a *High Availability* solution, like [**repmgr**] [repmgr]. Therefore, by integrating Barman and repmgr, you can dramatically reduce RTO to nearly zero.
32 |
33 | Based on our experience at 2ndQuadrant, we can confirm that PostgreSQL open source clusters with Barman and repmgr can easily achieve more than 99.99% uptime over a year, if properly configured and monitored.
34 |
35 | In any case, it is important for us to emphasise more on cultural aspects related to disaster recovery, rather than the actual tools. Tools without human beings are useless.
36 |
37 | Our mission with Barman is to promote a culture of disaster recovery that:
38 |
39 | - focuses on backup procedures
40 | - focuses even more on recovery procedures
41 | - relies on education and training on strong theoretical and practical concepts of PostgreSQL's crash recovery, backup, Point-In-Time-Recovery, and replication for your team members
42 | - promotes testing your backups (only a backup that is tested can be considered to be valid), either manually or automatically (be creative with Barman's hook scripts!)
43 | - fosters regular practice of recovery procedures, by all members of your devops team (yes, developers too, not just system administrators and DBAs)
44 | - solicites to regularly scheduled drills and disaster recovery simulations with the team every 3-6 months
45 | - relies on continuous monitoring of PostgreSQL and Barman, and that is able to promptly identify any anomalies
46 |
47 | Moreover, do everything you can to prepare yourself and your team for when the disaster happens (yes, *when*), because when it happens:
48 |
49 | - It is going to be a Friday evening, most likely right when you are about to leave the office.
50 | - It is going to be when you are on holiday (right in the middle of your cruise around the world) and somebody else has to deal with it.
51 | - It is certainly going to be stressful.
52 | - You will regret not being sure that the last available backup is valid.
53 | - Unless you know how long it approximately takes to recover, every second will seems like forever.
54 |
55 | Be prepared, don't be scared.
56 |
57 | In 2011, with these goals in mind, 2ndQuadrant started the development of
58 | Barman, now one of the most used backup tools for PostgreSQL. Barman is an acronym for "Backup and Recovery Manager".
59 |
60 | Currently, Barman works only on Linux and Unix operating systems.
61 |
--------------------------------------------------------------------------------
/doc/manual/66-about.en.md:
--------------------------------------------------------------------------------
1 | \newpage
2 |
3 | # The Barman project
4 |
5 | ## Support and sponsor opportunities
6 |
7 | Barman is free software, written and maintained by 2ndQuadrant. If you
8 | require support on using Barman, or if you need new features, please
9 | get in touch with 2ndQuadrant. You can sponsor the development of new
10 | features of Barman and PostgreSQL which will be made publicly
11 | available as open source.
12 |
13 | For further information, please visit:
14 |
15 | - [Barman website] [11]
16 | - [Support section] [12]
17 | - [2ndQuadrant website] [13]
18 | - [Barman FAQs] [14]
19 | - [2ndQuadrant blog: Barman] [15]
20 |
21 | ## Contributing to Barman
22 |
23 | 2ndQuadrant has a team of software engineers, architects, database
24 | administrators, system administrators, QA engineers, developers and
25 | managers that dedicate their time and expertise to improve Barman's code.
26 | We adopt lean and agile methodologies for software development, and
27 | we believe in the _devops_ culture that allowed us to implement rigorous
28 | testing procedures through cross-functional collaboration.
29 | Every Barman commit is the contribution of multiple individuals, at different
30 | stages of the production pipeline.
31 |
32 | Even though this is our preferred way of developing Barman, we gladly
33 | accept patches from external developers, as long as:
34 |
35 | - user documentation (tutorial and man pages) is provided.
36 | - source code is properly documented and contains relevant comments.
37 | - code supplied is covered by unit tests.
38 | - no unrelated feature is compromised or broken.
39 | - source code is rebased on the current master branch.
40 | - commits and pull requests are limited to a single feature (multi-feature
41 | patches are hard to test and review).
42 | - changes to the user interface are discussed beforehand with 2ndQuadrant.
43 |
44 | We also require that any contributions provide a copyright assignment
45 | and a disclaimer of any work-for-hire ownership claims from the employer
46 | of the developer.
47 |
48 | You can use Github's pull requests system for this purpose.
49 |
50 | ## Authors
51 |
52 | In alphabetical order:
53 |
54 | - Gabriele Bartolini, (project leader)
55 | - Jonathan Battiato, (QA/testing)
56 | - Stefano Bianucci, (developer, intern from University of Florence)
57 | - Giuseppe Broccolo, (QA/testing)
58 | - Giulio Calacoci, (developer)
59 | - Francesco Canovai, (QA/testing)
60 | - Leonardo Cecchi, (developer)
61 | - Gianni Ciolli, (QA/testing)
62 | - Britt Cole, (documentation)
63 | - Marco Nenciarini, (lead developer)
64 | - Rubens Souza, (QA/testing)
65 |
66 | Past contributors:
67 |
68 | - Carlo Ascani
69 |
70 | ## Links
71 |
72 | - [check-barman] [16]: a Nagios plugin for Barman, written by Holger
73 | Hamann (MIT license)
74 | - [puppet-barman] [17]: Barman module for Puppet (GPL)
75 | - [Tutorial on "How To Back Up, Restore, and Migrate PostgreSQL Databases with Barman on CentOS 7"] [26], by Sadequl Hussain (available on DigitalOcean Community)
76 | - [BarmanAPI] [27]: RESTFul API for Barman, written by Mehmet Emin Karakaş (GPL)
77 |
78 | ## License and Contributions
79 |
80 | Barman is the property of 2ndQuadrant Italia and its code is
81 | distributed under GNU General Public License 3.
82 |
83 | Copyright (C) 2011-2016 [2ndQuadrant.it S.r.l.] [19].
84 |
85 | Barman has been partially funded through [4CaaSt] [18], a research
86 | project funded by the European Commission's Seventh Framework
87 | programme.
88 |
89 | Contributions to Barman are welcome, and will be listed in the
90 | `AUTHORS` file. 2ndQuadrant Italia requires that any contributions
91 | provide a copyright assignment and a disclaimer of any work-for-hire
92 | ownership claims from the employer of the developer. This lets us make
93 | sure that all of the Barman distribution remains free code. Please
94 | contact info@2ndQuadrant.it for a copy of the relevant Copyright
95 | Assignment Form.
96 |
--------------------------------------------------------------------------------
/doc/manual/23-wal_streaming.en.md:
--------------------------------------------------------------------------------
1 | ## WAL streaming
2 |
3 | Barman can reduce the Recovery Point Objective (RPO) by allowing users
4 | to add continuous WAL streaming from a PostgreSQL server, on top of
5 | the standard `archive_command` strategy
6 |
7 | Barman relies on [`pg_receivexlog`] [25], a utility that has been
8 | available from PostgreSQL 9.2 which exploits the native streaming
9 | replication protocol and continuously receives transaction logs from a
10 | PostgreSQL server (master or standby).
11 |
12 | > **IMPORTANT:**
13 | > Barman requires that `pg_receivexlog` is installed on the same
14 | > server. For PostgreSQL 9.2 servers, you need `pg_receivexlog` of
15 | > version 9.2 installed alongside Barman. For PostgreSQL 9.3 and
16 | > above, it is recommended to install the latest available version of
17 | > `pg_receivexlog`, as it is back compatible. Otherwise, users can
18 | > install multiple versions of `pg_receivexlog` on the Barman server
19 | > and properly point to the specific version for a server, using the
20 | > `path_prefix` option in the configuration file.
21 |
22 | In order to enable streaming of transaction logs, you need to:
23 |
24 | 1. setup a streaming connection as previously described
25 | 2. set the `streaming_archiver` option to `on`
26 |
27 | The `cron` command, if the aforementioned requirements are met,
28 | transparently manages log streaming through the execution of the
29 | `receive-wal` command. This is the recommended scenario.
30 |
31 | However, users can manually execute the `receive-wal` command:
32 |
33 | ``` bash
34 | barman receive-wal
35 | ```
36 |
37 | > **NOTE:**
38 | > The `receive-wal` command is a foreground process.
39 |
40 | Transaction logs are streamed directly in the directory specified by the
41 | `streaming_wals_directory` configuration option and are then archived
42 | by the `archive-wal` command.
43 |
44 | Unless otherwise specified in the `streaming_archiver_name` parameter,
45 | and only for PostgreSQL 9.3 or above, Barman will set `application_name`
46 | of the WAL streamer process to `barman_receive_wal`, allowing you to
47 | monitor its status in the `pg_stat_replication` system view of the
48 | PostgreSQL server.
49 |
50 |
51 | ### Replication slots
52 |
53 | > **IMPORTANT:** replication slots are available since PostgreSQL 9.4
54 |
55 | Replication slots are an automated way to ensure that the PostgreSQL
56 | server will not remove WAL files until they were received by all
57 | archivers. Barman uses this mechanism to receive the transaction logs
58 | from PostgreSQL.
59 |
60 | You can find more information about replication slots in the
61 | [PostgreSQL manual][replication-slots].
62 |
63 | You can even base your backup architecture on streaming connection
64 | only. This scenario is useful to configure Docker-based PostgreSQL
65 | servers and even to work with PostgreSQL servers running on Windows.
66 |
67 | > **IMPORTANT:**
68 | > In this moment, the Windows support is still experimental, as it is
69 | > not yet part of our continuous integration system.
70 |
71 |
72 | ### How to configure the WAL streaming
73 |
74 | First, the PostgreSQL server must be configured to stream the
75 | transaction log files to the Barman server.
76 |
77 | To configure the streaming connection from Barman to the PostgreSQL
78 | server you need to enable the `streaming_archiver`, as already said,
79 | including this line in the server configuration file:
80 |
81 | ``` ini
82 | streaming_archiver = on
83 | ```
84 |
85 | If you plan to use replication slots (recommended),
86 | another essential option for the setup of the streaming-based
87 | transaction log archiving is the `slot_name` option:
88 |
89 | ``` ini
90 | slot_name = barman
91 | ```
92 |
93 | This option defines the name of the replication slot that will be
94 | used by Barman. It is mandatory if you want to use replication slots.
95 |
96 | When you configure the replication slot name, you can create a
97 | replication slot for Barman with this command:
98 |
99 | ``` bash
100 | barman@backup$ barman receive-wal --create-slot pg
101 | Creating physical replication slot 'barman' on server 'pg'
102 | Replication slot 'barman' created
103 | ```
104 |
105 |
--------------------------------------------------------------------------------
/sphinx/generate_docs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright (C) 2011-2016 2ndQuadrant Italia Srl
4 | #
5 | # This file is part of Barman.
6 | #
7 | # Barman is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # Barman is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with Barman. If not, see .
19 |
20 | BASEDIR=$(cd ${0%/*}; pwd )
21 |
22 | # modify GEN_MODE. It must be passed like parameter value
23 | GEN_MODE='html'
24 |
25 | function die()
26 | {
27 | echo $@
28 | exit 1
29 | }
30 |
31 | function usage()
32 | {
33 | echo "Usage: $0 [-h] [-t TARGET] DIR"
34 | echo
35 | echo "use -h for extended help"
36 | echo
37 | exit 1
38 | }
39 |
40 | function showhelp()
41 | {
42 | echo "$0 [-h] [-t TARGET] DIR"
43 | echo
44 | echo "DIR is the source directory of the barman files"
45 | echo
46 | echo " -h Show this help message"
47 | echo " -t TARGET Generate documentation using a specific "
48 | echo " target format (default: HTML)"
49 | echo
50 | echo "List of available target formats:"
51 | echo " html to make standalone HTML files"
52 | echo " dirhtml to make HTML files named index.html in directories"
53 | echo " singlehtml to make a single large HTML file"
54 | echo " pickle to make pickle files"
55 | echo " json to make JSON files"
56 | echo " htmlhelp to make HTML files and a HTML help project"
57 | echo " qthelp to make HTML files and a qthelp project"
58 | echo " devhelp to make HTML files and a Devhelp project"
59 | echo " epub to make an epub"
60 | echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
61 | echo " latexpdf to make LaTeX files and run them through pdflatex"
62 | echo " text to make text files"
63 | echo " man to make manual pages"
64 | echo " texinfo to make Texinfo files"
65 | echo " info to make Texinfo files and run them through makeinfo"
66 | echo " gettext to make PO message catalogs"
67 | echo " changes to make an overview of all changed/added/deprecated items"
68 | echo " linkcheck to check all external links for integrity"
69 | echo " doctest to run all doctests embedded in the documentation (if enabled)"
70 | echo
71 | }
72 |
73 | RED='\033[1;31m'
74 | RSET='\033[0m'
75 |
76 | function red()
77 | {
78 | printf "${RED}${1}${RSET}\n"
79 | }
80 |
81 |
82 | # if -h is the parameter it shows help
83 | # if -t expect for a target
84 | while getopts ht: OPT;
85 | do
86 | case "$OPT" in
87 | t)
88 | GEN_MODE=${OPTARG}; shift 2;;
89 | --)
90 | shift; break;;
91 | h|*)
92 | showhelp; exit 1;;
93 | esac
94 | shift;
95 | done
96 |
97 | if [[ $# -gt 2 ]]
98 | then
99 | showhelp
100 | exit 1
101 | fi
102 |
103 | if [[ $# -eq 0 ]] ; then
104 | BARMAN_DIR=$(cd "$BASEDIR/.."; pwd)
105 | else
106 | BARMAN_DIR=$(cd "$1"; pwd)
107 | fi
108 |
109 | [[ "${BARMAN_DIR}" = "." ]] && die 'Input directory . is not supported!'
110 | [[ ! -d "${BARMAN_DIR}" ]] && die 'Input directory does not exists!'
111 |
112 | export BARMAN_DIR
113 | cd "${BASEDIR}"
114 |
115 | # Cleans the build directory
116 | red "Cleaning the Build directory..."
117 | make clean
118 |
119 | red "Removing all generated files..."
120 | ls "${BASEDIR}"/docs/*.rst | grep -v 'index.rst$' | xargs -trI X rm -f X
121 |
122 | # Generates automatically modules doc
123 | red "Generating documentation from modules..."
124 | sphinx-apidoc -P -e -T -M -o docs "${BARMAN_DIR}"
125 | # Invokes html generation
126 | red "Generating ${GEN_MODE}"
127 | make ${GEN_MODE}
128 |
129 | red "DONE!!"
130 |
--------------------------------------------------------------------------------
/rpm/rhel5/python26-dateutil.spec:
--------------------------------------------------------------------------------
1 | # Use Python 2.6
2 | %global pybasever 2.6
3 | %global __python_ver 26
4 | %global __python %{_bindir}/python%{pybasever}
5 | %global __os_install_post %{__multiple_python_os_install_post}
6 |
7 | %{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
8 | %{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
9 |
10 | Name: python%{__python_ver}-dateutil
11 | Version: 1.4.1
12 | Release: 6%{?dist}
13 | Summary: Powerful extensions to the standard datetime module
14 |
15 | Group: Development/Languages
16 | License: Python
17 | URL: http://labix.org/python-dateutil
18 | Source0: http://labix.org/download/python-dateutil/python-dateutil-%{version}.tar.gz
19 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
20 |
21 | # Redirect the exposed parts of the dateutil.zoneinfo API to remove references
22 | # to the embedded copy of zoneinfo-2008e.tar.gz and instead use the system
23 | # data from the "tzdata" package (rhbz#559309):
24 | Patch0: python-dateutil-1.4.1-remove-embedded-timezone-data.patch
25 |
26 | BuildArch: noarch
27 | BuildRequires: python%{__python_ver}-devel,python%{__python_ver}-setuptools
28 |
29 | Requires: tzdata
30 |
31 | %description
32 | The dateutil module provides powerful extensions to the standard datetime
33 | module available in Python 2.3+.
34 |
35 | %prep
36 | %setup -n python-dateutil-%{version} -q
37 |
38 | # Remove embedded copy of timezone data:
39 | %patch0 -p1
40 | rm dateutil/zoneinfo/zoneinfo-2008e.tar.gz
41 |
42 | # Change encoding of NEWS file to UTF-8, preserving timestamp:
43 | iconv -f ISO-8859-1 -t utf8 NEWS > NEWS.utf8 && \
44 | touch -r NEWS NEWS.utf8 && \
45 | mv NEWS.utf8 NEWS
46 |
47 | %build
48 | %{__python} setup.py build
49 |
50 |
51 | %install
52 | rm -rf $RPM_BUILD_ROOT
53 | %{__python} setup.py install -O1 --skip-build --root $RPM_BUILD_ROOT
54 |
55 |
56 | %clean
57 | rm -rf $RPM_BUILD_ROOT
58 |
59 | %check
60 | %{__python} test.py
61 |
62 | %files
63 | %defattr(-,root,root,-)
64 | %doc example.py LICENSE NEWS README
65 | %{python_sitelib}/dateutil/
66 | %{python_sitelib}/*.egg-info
67 |
68 | %changelog
69 | * Tue Jul 13 2010 David Malcolm - 1.4.1-6
70 | - remove embedded copy of timezone data, and redirect the dateutil.zoneinfo
71 | API accordingly
72 | Resolves: rhbz#559309
73 | - add a %%check, running the upstream selftest suite
74 |
75 | * Tue Jul 13 2010 David Malcolm - 1.4.1-5
76 | - add requirement on tzdata
77 | Resolves: rhbz#559309
78 | - fix encoding of the NEWS file
79 |
80 | * Mon Nov 30 2009 Dennis Gregorovic - 1.4.1-4.1
81 | - Rebuilt for RHEL 6
82 |
83 | * Sun Jul 26 2009 Fedora Release Engineering - 1.4.1-4
84 | - Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
85 |
86 | * Thu Feb 26 2009 Fedora Release Engineering - 1.4.1-3
87 | - Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
88 |
89 | * Fri Feb 20 2009 Jef Spaleta - 1.4.1-2
90 | - small specfile fix
91 |
92 | * Fri Feb 20 2009 Jef Spaleta - 1.4.1-2
93 | - New upstream version
94 |
95 | * Sat Nov 29 2008 Ignacio Vazquez-Abrams - 1.4-3
96 | - Rebuild for Python 2.6
97 |
98 | * Fri Aug 29 2008 Tom "spot" Callaway - 1.4-2
99 | - fix license tag
100 |
101 | * Tue Jul 01 2008 Jef Spaleta 1.4-1
102 | - Latest upstream release
103 |
104 | * Fri Jan 04 2008 Jef Spaleta 1.2-2
105 | - Fix for egg-info file creation
106 |
107 | * Thu Jun 28 2007 Orion Poplawski 1.2-1
108 | - Update to 1.2
109 |
110 | * Mon Dec 11 2006 Jef Spaleta 1.1-5
111 | - Fix python-devel BR, as per discussion in maintainers-list
112 |
113 | * Mon Dec 11 2006 Jef Spaleta 1.1-4
114 | - Release bump for rebuild against python 2.5 in devel tree
115 |
116 | * Wed Jul 26 2006 Orion Poplawski 1.1-3
117 | - Add patch to fix building on x86_64
118 |
119 | * Wed Feb 15 2006 Orion Poplawski 1.1-2
120 | - Rebuild for gcc/glibc changes
121 |
122 | * Thu Dec 22 2005 Orion Poplawski 1.1-1
123 | - Update to 1.1
124 |
125 | * Thu Jul 28 2005 Orion Poplawski 1.0-1
126 | - Update to 1.0
127 |
128 | * Tue Jul 05 2005 Orion Poplawski 0.9-1
129 | - Initial Fedora Extras package
130 |
--------------------------------------------------------------------------------
/scripts/gitlog-to-changelog:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 | # Convert git log output to ChangeLog format.
3 |
4 | my $VERSION = '2010-10-28 09:48'; # UTC
5 | # The definition above must lie within the first 8 lines in order
6 | # for the Emacs time-stamp write hook (at end) to update it.
7 | # If you change this file with Emacs, please let the write hook
8 | # do its job. Otherwise, update this string manually.
9 |
10 | # Copyright (C) 2008 Free Software Foundation, Inc.
11 |
12 | # This program is free software: you can redistribute it and/or modify
13 | # it under the terms of the GNU General Public License as published by
14 | # the Free Software Foundation, either version 3 of the License, or
15 | # (at your option) any later version.
16 |
17 | # This program is distributed in the hope that it will be useful,
18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | # GNU General Public License for more details.
21 |
22 | # You should have received a copy of the GNU General Public License
23 | # along with this program. If not, see .
24 |
25 | # Written by Jim Meyering
26 |
27 | use strict;
28 | use warnings;
29 | use Getopt::Long;
30 | use POSIX qw(strftime);
31 |
32 | (my $ME = $0) =~ s|.*/||;
33 |
34 | # use File::Coda; # http://meyering.net/code/Coda/
35 | END {
36 | defined fileno STDOUT or return;
37 | close STDOUT and return;
38 | warn "$ME: failed to close standard output: $!\n";
39 | $? ||= 1;
40 | }
41 |
42 | sub usage ($)
43 | {
44 | my ($exit_code) = @_;
45 | my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
46 | if ($exit_code != 0)
47 | {
48 | print $STREAM "Try `$ME --help' for more information.\n";
49 | }
50 | else
51 | {
52 | print $STREAM < ChangeLog
68 |
69 | EOF
70 | }
71 | exit $exit_code;
72 | }
73 |
74 | # If the string $S is a well-behaved file name, simply return it.
75 | # If it contains white space, quotes, etc., quote it, and return the new tring.
76 | sub shell_quote($)
77 | {
78 | my ($s) = @_;
79 | if ($s =~ m![^\w+/.,-]!)
80 | {
81 | # Convert each single quote to '\''
82 | $s =~ s/\'/\'\\\'\'/g;
83 | # Then single quote the string.
84 | $s = "'$s'";
85 | }
86 | return $s;
87 | }
88 |
89 | sub quoted_cmd(@)
90 | {
91 | return join (' ', map {shell_quote $_} @_);
92 | }
93 |
94 | {
95 | my $since_date = '1970-01-01 UTC';
96 | GetOptions
97 | (
98 | help => sub { usage 0 },
99 | version => sub { print "$ME version $VERSION\n"; exit },
100 | 'since=s' => \$since_date,
101 | ) or usage 1;
102 |
103 | @ARGV
104 | and (warn "$ME: too many arguments\n"), usage 1;
105 |
106 | my @cmd = (qw (git log --log-size), "--since=$since_date",
107 | '--pretty=format:%at %an <%ae>%n%n%s%n%b%n');
108 | open PIPE, '-|', @cmd
109 | or die "$ME: failed to run `". quoted_cmd (@cmd) ."': $!\n";
110 |
111 | my $prev_date_line = '';
112 | while (1)
113 | {
114 | defined (my $in = )
115 | or last;
116 | $in =~ /^log size (\d+)$/
117 | or die "$ME:$.: Invalid line (expected log size):\n$in";
118 | my $log_nbytes = $1;
119 |
120 | my $log;
121 | my $n_read = read PIPE, $log, $log_nbytes;
122 | $n_read == $log_nbytes
123 | or die "$ME:$.: unexpected EOF\n";
124 |
125 | my @line = split "\n", $log;
126 | my $author_line = shift @line;
127 | defined $author_line
128 | or die "$ME:$.: unexpected EOF\n";
129 | $author_line =~ /^(\d+) (.*>)$/
130 | or die "$ME:$.: Invalid line "
131 | . "(expected date/author/email):\n$author_line\n";
132 |
133 | my $date_line = sprintf "%s $2\n", strftime ("%F", localtime ($1));
134 | # If this line would be the same as the previous date/name/email
135 | # line, then arrange not to print it.
136 | if ($date_line ne $prev_date_line)
137 | {
138 | $prev_date_line eq ''
139 | or print "\n";
140 | print $date_line;
141 | }
142 | $prev_date_line = $date_line;
143 |
144 | # Omit "Signed-off-by..." lines.
145 | @line = grep !/^Signed-off-by: .*>$/, @line;
146 |
147 | # Remove leading and trailing blank lines.
148 | while ($line[0] =~ /^\s*$/) { shift @line; }
149 | while ($line[$#line] =~ /^\s*$/) { pop @line; }
150 |
151 | # Prefix each non-empty line with a TAB.
152 | @line = map { length $_ ? "\t$_" : '' } @line;
153 |
154 | print "\n", join ("\n", @line), "\n";
155 |
156 | defined ($in = )
157 | or last;
158 | $in ne "\n"
159 | and die "$ME:$.: unexpected line:\n$in";
160 | }
161 |
162 | close PIPE
163 | or die "$ME: error closing pipe from " . quoted_cmd (@cmd) . "\n";
164 | # FIXME-someday: include $PROCESS_STATUS in the diagnostic
165 | }
166 |
167 | # Local Variables:
168 | # indent-tabs-mode: nil
169 | # eval: (add-hook 'write-file-hooks 'time-stamp)
170 | # time-stamp-start: "my $VERSION = '"
171 | # time-stamp-format: "%:y-%02m-%02d %02H:%02M"
172 | # time-stamp-time-zone: "UTC"
173 | # time-stamp-end: "'; # UTC"
174 | # End:
175 |
176 |
--------------------------------------------------------------------------------
/rpm/barman.spec:
--------------------------------------------------------------------------------
1 | %if 0%{?rhel} == 7
2 | %global pybasever 2.7
3 | %else
4 | %if 0%{?fedora}>=21
5 | %global pybasever 2.7
6 | %else
7 | %global pybasever 2.6
8 | %endif
9 | %endif
10 |
11 | %if 0%{?rhel} == 5
12 | %global with_python26 1
13 | %endif
14 |
15 | %if 0%{?with_python26}
16 | %global __python_ver python26
17 | %global __python %{_bindir}/python%{pybasever}
18 | %global __os_install_post %{__multiple_python_os_install_post}
19 | %else
20 | %global __python_ver python
21 | %endif
22 |
23 | %global main_version 2.2
24 | # comment out the next line if not a pre-release (use '#%%global ...')
25 | %global extra_version a1
26 | # Usually 1 - unique sequence for all pre-release version
27 | %global package_release 1
28 |
29 | %{!?pybasever: %define pybasever %(%{__python} -c "import sys;print(sys.version[0:3])")}
30 | %{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
31 | %{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
32 |
33 | Summary: Backup and Recovery Manager for PostgreSQL
34 | Name: barman
35 | Version: %{main_version}
36 | Release: %{?extra_version:0.}%{package_release}%{?extra_version:.%{extra_version}}%{?dist}
37 | License: GPLv3
38 | Group: Applications/Databases
39 | Url: http://www.pgbarman.org/
40 | Source0: %{name}-%{version}%{?extra_version:%{extra_version}}.tar.gz
41 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n)
42 | BuildArch: noarch
43 | Vendor: 2ndQuadrant Italia Srl
44 | Requires: python-abi = %{pybasever}, %{__python_ver}-psycopg2 >= 2.4.2, %{__python_ver}-argh >= 0.21.2, %{__python_ver}-argcomplete, %{__python_ver}-dateutil
45 | Requires: /usr/sbin/useradd
46 | Requires: rsync >= 3.0.4
47 | Requires: barman-incr >= %{main_version}
48 |
49 | %package incr
50 | Summary: Helper for incremental backup with barman
51 | Requires: python-abi = %{pybasever}, %{__python_ver}-backports-lzma, %{__python_ver}-msgpack >= 0.4.6
52 | %if 0%{?rhel} == 5
53 | Requires: %{__python_ver}-argparse
54 | %endif
55 | Requires: rsync >= 3.0.4
56 |
57 | %description
58 | Barman (Backup and Recovery Manager) is an open-source
59 | administration tool for disaster recovery of PostgreSQL
60 | servers written in Python.
61 | It allows your organisation to perform remote backups of
62 | multiple servers in business critical environments to
63 | reduce risk and help DBAs during the recovery phase.
64 |
65 | Barman is distributed under GNU GPL 3 and maintained
66 | by 2ndQuadrant.
67 |
68 | %description incr
69 | Barman-incr is simple python tool for incremental backup of PostgreSQL (>= 9.3).
70 |
71 |
72 | %prep
73 | %setup -n barman-%{version}%{?extra_version:%{extra_version}} -q
74 |
75 | %build
76 | %{__python} setup.py build
77 | cat > barman.cron << EOF
78 | # m h dom mon dow user command
79 | * * * * * barman [ -x %{_bindir}/barman ] && %{_bindir}/barman -q cron
80 | EOF
81 | cat > barman.logrotate << EOF
82 | /var/log/barman/barman.log {
83 | missingok
84 | notifempty
85 | create 0600 barman barman
86 | }
87 | EOF
88 |
89 | %install
90 | %{__python} setup.py install -O1 --skip-build --root %{buildroot}
91 | mkdir -p %{buildroot}%{_sysconfdir}/bash_completion.d
92 | mkdir -p %{buildroot}%{_sysconfdir}/cron.d/
93 | mkdir -p %{buildroot}%{_sysconfdir}/logrotate.d/
94 | mkdir -p %{buildroot}%{_sysconfdir}/barman.d/
95 | mkdir -p %{buildroot}/var/lib/barman
96 | mkdir -p %{buildroot}/var/log/barman
97 | install -pm 644 doc/barman.conf %{buildroot}%{_sysconfdir}/barman.conf
98 | install -pm 644 doc/barman.d/* %{buildroot}%{_sysconfdir}/barman.d/
99 | install -pm 644 scripts/barman.bash_completion %{buildroot}%{_sysconfdir}/bash_completion.d/barman
100 | install -pm 644 barman.cron %{buildroot}%{_sysconfdir}/cron.d/barman
101 | install -pm 644 barman.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/barman
102 | touch %{buildroot}/var/log/barman/barman.log
103 | mkdir -p %{buildroot}/usr/bin
104 | install -pm 755 bin/barman-incr %{buildroot}/usr/bin/barman-incr
105 |
106 | %clean
107 | rm -rf %{buildroot}
108 |
109 | %files
110 | %defattr(-,root,root)
111 | %doc INSTALL NEWS README.rst
112 | %{python_sitelib}/%{name}-%{version}%{?extra_version:%{extra_version}}-py%{pybasever}.egg-info
113 | %{python_sitelib}/%{name}/
114 | %{_bindir}/%{name}
115 | %doc %{_mandir}/man1/%{name}.1.gz
116 | %doc %{_mandir}/man5/%{name}.5.gz
117 | %config(noreplace) %{_sysconfdir}/bash_completion.d/
118 | %config(noreplace) %{_sysconfdir}/%{name}.conf
119 | %config(noreplace) %{_sysconfdir}/cron.d/%{name}
120 | %config(noreplace) %{_sysconfdir}/logrotate.d/%{name}
121 | %config(noreplace) %{_sysconfdir}/barman.d/
122 | %attr(700,barman,barman) %dir /var/lib/%{name}
123 | %attr(755,barman,barman) %dir /var/log/%{name}
124 | %attr(600,barman,barman) %ghost /var/log/%{name}/%{name}.log
125 |
126 | %files incr
127 | %attr(755,root,root) /usr/bin/barman-incr
128 |
129 | %pre
130 | groupadd -f -r barman >/dev/null 2>&1 || :
131 | useradd -M -n -g barman -r -d /var/lib/barman -s /bin/bash \
132 | -c "Backup and Recovery Manager for PostgreSQL" barman >/dev/null 2>&1 || :
133 |
134 | %changelog
135 | * Thu Jan 5 2017 - Giulio Calacoci 2.1-1
136 | - New release 2.1-1
137 |
138 | * Tue Dec 27 2016 - Gabriele Bartolini 2.1-0.1.alpha.1
139 | - New release 2.1-0.1.alpha.1
140 |
141 | * Tue Sep 27 2016 - Gabriele Bartolini 2.0-1
142 | - New release 2.0-1
143 | - Trim changelog for releases 1.X
144 |
--------------------------------------------------------------------------------
/tests/test_process.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2011-2016 2ndQuadrant Italia Srl
2 | #
3 | # This file is part of Barman.
4 | #
5 | # Barman is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Barman is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Barman. If not, see .
17 |
18 | import errno
19 | import os
20 |
21 | import mock
22 |
23 | from barman.lockfile import ServerWalReceiveLock
24 | from barman.process import ProcessInfo, ProcessManager
25 | from testing_helpers import build_config_from_dicts
26 |
27 |
28 | # noinspection PyMethodMayBeStatic
29 | class TestProcessInfo(object):
30 | """
31 | ProcessInfo obj tests
32 | """
33 |
34 | def test_init(self):
35 | """
36 | Test the init method
37 | """
38 | pi = ProcessInfo(pid=12345,
39 | server_name='test_server',
40 | task='test_task')
41 |
42 | assert pi.pid == 12345
43 | assert pi.server_name == 'test_server'
44 | assert pi.task == 'test_task'
45 |
46 |
47 | class TestProcessManager(object):
48 | """
49 | Simple class for testing the ProcessManager obj
50 | """
51 |
52 | def test_init(self, tmpdir):
53 | """
54 | Test the init method
55 | """
56 | # Build a basic configuration
57 | config = build_config_from_dicts({
58 | 'barman_lock_directory': tmpdir.strpath})
59 | config.name = 'main'
60 | # Acquire a lock and initialise the ProjectManager.
61 | # Expect the ProjectManager to Retrieve the
62 | # "Running process" identified by the lock
63 | lock = ServerWalReceiveLock(tmpdir.strpath, 'main')
64 | with lock:
65 | pm = ProcessManager(config)
66 |
67 | # Test for the length of the process list
68 | assert len(pm.process_list) == 1
69 | # Test for the server identifier of the process
70 | assert pm.process_list[0].server_name == 'main'
71 | # Test for the task type
72 | assert pm.process_list[0].task == 'receive-wal'
73 | # Read the pid from the lockfile and test id against the ProcessInfo
74 | # contained in the process_list
75 | with open(lock.filename, 'r') as lockfile:
76 | pid = lockfile.read().strip()
77 | assert int(pid) == pm.process_list[0].pid
78 |
79 | # Test lock file parse error.
80 | # Skip the lock and don't raise any exception.
81 | with lock:
82 | with open(lock.filename, 'w') as lockfile:
83 | lockfile.write("invalid")
84 | pm = ProcessManager(config)
85 | assert len(pm.process_list) == 0
86 |
87 | def test_list(self, tmpdir):
88 | """
89 | Test the list method from the ProjectManager class
90 | """
91 | config = build_config_from_dicts({
92 | 'barman_lock_directory': tmpdir.strpath})
93 | config.name = 'main'
94 | with ServerWalReceiveLock(tmpdir.strpath, 'main'):
95 | pm = ProcessManager(config)
96 | process = pm.list('receive-wal')[0]
97 |
98 | assert process.server_name == 'main'
99 | assert process.task == 'receive-wal'
100 | with open(os.path.join(
101 | tmpdir.strpath,
102 | '.%s-receive-wal.lock' % config.name)) as lockfile:
103 | pid = lockfile.read().strip()
104 | assert int(pid) == process.pid
105 |
106 | @mock.patch('os.kill')
107 | def test_kill(self, kill_mock, tmpdir):
108 | """
109 | Test the Kill method from the ProjectManager class.
110 | Mocks the os.kill used inside the the kill method
111 | """
112 | config = build_config_from_dicts({
113 | 'barman_lock_directory': tmpdir.strpath})
114 | config.name = 'main'
115 | # Acquire a lock, simulating a running process
116 | with ServerWalReceiveLock(tmpdir.strpath, 'main'):
117 | # Build a ProcessManager and retrieve the receive-wal process
118 | pm = ProcessManager(config)
119 | pi = pm.list('receive-wal')[0]
120 | # Exit at the first invocation of kill (this is a failed kill)
121 | kill_mock.side_effect = OSError(errno.EPERM, '', '')
122 | kill = pm.kill(pi)
123 | # Expect the kill result to be false
124 | assert kill is False
125 | assert kill_mock.call_count == 1
126 | kill_mock.assert_called_with(pi.pid, 2)
127 |
128 | kill_mock.reset_mock()
129 | # Exit at the second invocation of kill (this is a successful kill)
130 | kill_mock.side_effect = [None, OSError(errno.ESRCH, '', '')]
131 | # Expect the kill result to be true
132 | kill = pm.kill(pi)
133 | assert kill
134 | assert kill_mock.call_count == 2
135 | kill_mock.assert_has_calls([mock.call(pi.pid, 2),
136 | mock.call(pi.pid, 0)])
137 |
138 | kill_mock.reset_mock()
139 | # Check for the retry feature. exit at the second iteration of the
140 | # kill cycle
141 | kill_mock.side_effect = [None, None, OSError(errno.ESRCH, '', '')]
142 | kill = pm.kill(pi)
143 | assert kill
144 | assert kill_mock.call_count == 3
145 | kill_mock.assert_has_calls([mock.call(pi.pid, 2),
146 | mock.call(pi.pid, 0),
147 | mock.call(pi.pid, 0)])
148 |
--------------------------------------------------------------------------------
/doc/manual/43-backup-commands.en.md:
--------------------------------------------------------------------------------
1 | \newpage
2 |
3 | # Backup commands
4 |
5 | Backup commands are those that works directly on backups already existing in
6 | Barman's backup catalog.
7 |
8 | > **NOTE:**
9 | > Remember a backup ID can be retrieved with `barman list-backup
10 | > `
11 |
12 | ## Backup ID shortcuts
13 |
14 | Barman allows you to use special keywords to identify a specific backup:
15 |
16 | * `last/latest`: identifies the newest backup in the catalog
17 | * `first/oldest`: identifies the oldest backup in the catalog
18 |
19 | Using those keywords with Barman commands allows you to execute actions
20 | without knowing the exact ID of a backup for a server.
21 | For example we can issue:
22 |
23 | ``` bash
24 | barman delete oldest
25 | ```
26 |
27 | to remove the oldest backup available in the catalog and reclaim disk space.
28 |
29 | ## `delete`
30 |
31 | You can delete a given backup with:
32 |
33 | ``` bash
34 | barman delete
35 | ```
36 |
37 | The `delete` command accepts any [shortcut](#shortcuts) to identify backups.
38 |
39 | ## `list-files`
40 |
41 | You can list the files (base backup and required WAL files) for a
42 | given backup with:
43 |
44 | ``` bash
45 | barman list-files [--target TARGET_TYPE]
46 | ```
47 |
48 | With the `--target TARGET_TYPE` option, it is possible to choose the
49 | content of the list for a given backup.
50 |
51 | Possible values for `TARGET_TYPE` are:
52 |
53 | - `data`: lists the data files
54 | - `standalone`: lists the base backup files, including required WAL
55 | files
56 | - `wal`: lists all WAL files from the beginning of the base backup to
57 | the start of the following one (or until the end of the log)
58 | - `full`: same as `data` + `wal`
59 |
60 | The default value for `TARGET_TYPE` is `standalone`.
61 |
62 | > **IMPORTANT:**
63 | > The `list-files` command facilitates interaction with external
64 | > tools, and can therefore be extremely useful to integrate
65 | > Barman into your archiving procedures.
66 |
67 | ## `recover`
68 |
69 | The `recover` command is used to recover a whole server after
70 | a backup is executed using the `backup` command.
71 |
72 | This is achieved issuing a command like the following:
73 |
74 | ```bash
75 | barman@backup$ barman recover /path/to/recover/dir
76 | ```
77 |
78 | At the end of the execution of the recovery, the selected backup is recovered
79 | locally and the destination path contains a data directory ready to be used
80 | to start a PostgreSQL instance.
81 |
82 | > **IMPORTANT:**
83 | > Running this command as user `barman`, it will become the database superuser.
84 |
85 | The specific ID of a backup can be retrieved using the [list-backup](#list-backup)
86 | command.
87 |
88 | > **IMPORTANT:**
89 | > Barman does not currently keep track of symbolic links inside PGDATA
90 | > (except for tablespaces inside pg_tblspc). We encourage
91 | > system administrators to keep track of symbolic links and to add them
92 | > to the disaster recovery plans/procedures in case they need to be restored
93 | > in their original location.
94 |
95 | The recovery command has several options that modify the command behavior.
96 |
97 | ### Remote recovery
98 |
99 | Add the `--remote-ssh-command ` option to the invocation
100 | of the recovery command. Doing this will allow Barman to execute
101 | the copy on a remote server, using the provided command to connect
102 | to the remote host.
103 |
104 | > **NOTE:**
105 | > It is advisable to use the `postgres` user to perform
106 | > the recovery on the remote host.
107 |
108 | Known limitations of the remote recovery are:
109 |
110 | * Barman requires at least 4GB of free space in the system temporary directory
111 | unless the [`get-wal`](#get-wal) command is specified
112 | in the `recovery_option` parameter in the Barman configuration.
113 | * The SSH connection between Barman and the remote host **must** use the
114 | public key exchange authentication method
115 | * The remote user **must** be able to create the directory structure
116 | of the backup in the destination directory.
117 | * There must be enough free space on the remote server
118 | to contain the base backup and the WAL files needed for recovery.
119 |
120 | ### Tablespace remapping
121 |
122 | Barman is able to automatically remap one or more tablespaces using
123 | the recover command with the --tablespace option.
124 | The option accepts a pair of values as arguments using the
125 | `NAME:DIRECTORY` format:
126 |
127 | * `NAME` is the identifier of the tablespace
128 | * `DIRECTORY` is the new destination path for the tablespace
129 |
130 | If the destination directory does not exists,
131 | Barman will try to create it (assuming you have the required permissions).
132 |
133 | ### Point in time recovery
134 |
135 | Barman wraps PostgreSQL's Point-in-Time Recovery (PITR),
136 | allowing you to specify a recovery target, either as a timestamp,
137 | as a restore label, or as a transaction ID.
138 |
139 | The recovery target can be specified using one of
140 | three mutually exclusive options:
141 |
142 | * --target-time TARGET_TIME: to specify a timestamp
143 | * --target-xid TARGET_XID: to specify a transaction ID
144 | * --target-name TARGET_NAME: to specify a named restore point
145 | previously created with the pg_create_restore_point(name)
146 | function[^TARGET_NAME]
147 |
148 | [^TARGET_NAME]:
149 | Only available on PostgreSQL 9.1 and above
150 |
151 | You can use the --exclusive option to specify whether to stop immediately
152 | before or immediately after the recovery target.
153 |
154 | Barman allows you to specify a target timeline for recovery,
155 | using the `target-tli` option. The notion of timeline goes beyond the scope of
156 | this document; you can find more details in the PostgreSQL documentation,
157 | as mentioned in the _"Before you start"_ section.
158 |
159 | ## `show-backup`
160 |
161 | You can retrieve all the available information for a particular backup of
162 | a given server with:
163 |
164 | ``` bash
165 | barman show-backup
166 | ```
167 |
168 | The `show-backup` command accepts any [shortcut](#shortcuts) to identify backups.
169 |
--------------------------------------------------------------------------------
/sphinx/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | PAPER =
8 | BUILDDIR = _build
9 |
10 | # Internal variables.
11 | PAPEROPT_a4 = -D latex_paper_size=a4
12 | PAPEROPT_letter = -D latex_paper_size=letter
13 | ALLSPHINXOPTS = -c . -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ./docs
14 | # the i18n builder cannot share the environment and doctrees with the others
15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
16 |
17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
18 |
19 | help:
20 | @echo "Please use \`make ' where is one of"
21 | @echo " html to make standalone HTML files"
22 | @echo " dirhtml to make HTML files named index.html in directories"
23 | @echo " singlehtml to make a single large HTML file"
24 | @echo " pickle to make pickle files"
25 | @echo " json to make JSON files"
26 | @echo " htmlhelp to make HTML files and a HTML help project"
27 | @echo " qthelp to make HTML files and a qthelp project"
28 | @echo " devhelp to make HTML files and a Devhelp project"
29 | @echo " epub to make an epub"
30 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
31 | @echo " latexpdf to make LaTeX files and run them through pdflatex"
32 | @echo " text to make text files"
33 | @echo " man to make manual pages"
34 | @echo " texinfo to make Texinfo files"
35 | @echo " info to make Texinfo files and run them through makeinfo"
36 | @echo " gettext to make PO message catalogs"
37 | @echo " changes to make an overview of all changed/added/deprecated items"
38 | @echo " linkcheck to check all external links for integrity"
39 | @echo " doctest to run all doctests embedded in the documentation (if enabled)"
40 |
41 | clean:
42 | -rm -rf $(BUILDDIR)/*
43 |
44 | html:
45 | $(SPHINXBUILD) -a -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
46 | @echo
47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
48 |
49 | dirhtml:
50 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
51 | @echo
52 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
53 |
54 | singlehtml:
55 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
56 | @echo
57 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
58 |
59 | pickle:
60 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
61 | @echo
62 | @echo "Build finished; now you can process the pickle files."
63 |
64 | json:
65 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
66 | @echo
67 | @echo "Build finished; now you can process the JSON files."
68 |
69 | htmlhelp:
70 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
71 | @echo
72 | @echo "Build finished; now you can run HTML Help Workshop with the" \
73 | ".hhp project file in $(BUILDDIR)/htmlhelp."
74 |
75 | qthelp:
76 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
77 | @echo
78 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \
79 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
80 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Barman.qhcp"
81 | @echo "To view the help file:"
82 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Barman.qhc"
83 |
84 | devhelp:
85 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
86 | @echo
87 | @echo "Build finished."
88 | @echo "To view the help file:"
89 | @echo "# mkdir -p $$HOME/.local/share/devhelp/Barman"
90 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Barman"
91 | @echo "# devhelp"
92 |
93 | epub:
94 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
95 | @echo
96 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
97 |
98 | latex:
99 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
100 | @echo
101 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
102 | @echo "Run \`make' in that directory to run these through (pdf)latex" \
103 | "(use \`make latexpdf' here to do that automatically)."
104 |
105 | latexpdf:
106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
107 | @echo "Running LaTeX files through pdflatex..."
108 | $(MAKE) -C $(BUILDDIR)/latex all-pdf
109 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
110 |
111 | text:
112 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
113 | @echo
114 | @echo "Build finished. The text files are in $(BUILDDIR)/text."
115 |
116 | man:
117 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
118 | @echo
119 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
120 |
121 | texinfo:
122 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
123 | @echo
124 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
125 | @echo "Run \`make' in that directory to run these through makeinfo" \
126 | "(use \`make info' here to do that automatically)."
127 |
128 | info:
129 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
130 | @echo "Running Texinfo files through makeinfo..."
131 | make -C $(BUILDDIR)/texinfo info
132 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
133 |
134 | gettext:
135 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
136 | @echo
137 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
138 |
139 | changes:
140 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
141 | @echo
142 | @echo "The overview file is in $(BUILDDIR)/changes."
143 |
144 | linkcheck:
145 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
146 | @echo
147 | @echo "Link check complete; look for any errors in the above output " \
148 | "or in $(BUILDDIR)/linkcheck/output.txt."
149 |
150 | doctest:
151 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
152 | @echo "Testing of doctests in the sources finished, look at the " \
153 | "results in $(BUILDDIR)/doctest/output.txt."
154 |
--------------------------------------------------------------------------------
/barman/process.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2011-2016 2ndQuadrant Italia Srl
2 | #
3 | # This file is part of Barman.
4 | #
5 | # Barman is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Barman is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Barman. If not, see
17 |
18 | import errno
19 | import logging
20 | import os
21 | import signal
22 | import time
23 | from glob import glob
24 |
25 | from barman import output
26 | from barman.exceptions import LockFileParsingError
27 | from barman.lockfile import ServerWalReceiveLock
28 |
29 | _logger = logging.getLogger(__name__)
30 |
31 |
32 | class ProcessInfo(object):
33 | """
34 | Barman process representation
35 | """
36 |
37 | def __init__(self, pid, server_name, task):
38 | """
39 | This object contains all the information required to identify a
40 | barman process
41 |
42 | :param int pid: Process ID
43 | :param string server_name: Name of the server owning the process
44 | :param string task: Task name (receive-wal, archive-wal...)
45 | """
46 |
47 | self.pid = pid
48 | self.server_name = server_name
49 | self.task = task
50 |
51 |
52 | class ProcessManager(object):
53 | """
54 | Class for the management of barman processes owned by a server
55 | """
56 |
57 | # Map containing the tasks we want to retrieve (and eventually manage)
58 | TASKS = {
59 | 'receive-wal': ServerWalReceiveLock
60 | }
61 |
62 | def __init__(self, config):
63 | """
64 | Build a ProcessManager for the provided server
65 |
66 | :param config: configuration of the server owning the process manager
67 | """
68 | self.config = config
69 | self.process_list = []
70 | # Cycle over the lock files in the lock directory for this server
71 | for path in glob(os.path.join(self.config.barman_lock_directory,
72 | '.%s-*.lock' % self.config.name)):
73 | for task, lock_class in self.TASKS.items():
74 | # Check the lock_name against the lock class
75 | lock = lock_class.build_if_matches(path)
76 | if lock:
77 | try:
78 | # Use the lock to get the owner pid
79 | pid = lock.get_owner_pid()
80 | except LockFileParsingError:
81 | _logger.warning(
82 | "Skipping the %s process for server %s: "
83 | "Error reading the PID from lock file '%s'",
84 | task, self.config.name, path)
85 | break
86 | # If there is a pid save it in the process list
87 | if pid:
88 | self.process_list.append(
89 | ProcessInfo(pid, config.name, task))
90 | # In any case, we found a match, so we must stop iterating
91 | # over the task types and handle the the next path
92 | break
93 |
94 | def list(self, task_filter=None):
95 | """
96 | Returns a list of processes owned by this server
97 |
98 | If no filter is provided, all the processes are returned.
99 |
100 | :param str task_filter: Type of process we want to retrieve
101 | :return list[ProcessInfo]: List of processes for the server
102 | """
103 | server_tasks = []
104 | for process in self.process_list:
105 | # Filter the processes if necessary
106 | if task_filter and process.task != task_filter:
107 | continue
108 | server_tasks.append(process)
109 | return server_tasks
110 |
111 | def kill(self, process_info, retries=10):
112 | """
113 | Kill a process
114 |
115 | Returns True if killed successfully False otherwise
116 |
117 | :param ProcessInfo process_info: representation of the process
118 | we want to kill
119 | :param int retries: number of times the method will check
120 | if the process is still alive
121 | :rtype: bool
122 | """
123 | # Try to kill the process
124 | try:
125 | _logger.debug("Sending SIGINT to PID %s", process_info.pid)
126 | os.kill(process_info.pid, signal.SIGINT)
127 | _logger.debug("os.kill call succeeded")
128 | except OSError as e:
129 | _logger.debug("os.kill call failed: %s", e)
130 | # The process doesn't exists. It has probably just terminated.
131 | if e.errno == errno.ESRCH:
132 | return True
133 | # Something unexpected has happened
134 | output.error("%s", e)
135 | return False
136 | # Check if the process have been killed. the fastest (and maybe safest)
137 | # way is to send a kill with 0 as signal.
138 | # If the method returns an OSError exceptions, the process have been
139 | # killed successfully, otherwise is still alive.
140 | for counter in range(retries):
141 | try:
142 | _logger.debug("Checking with SIG_DFL if PID %s is still alive",
143 | process_info.pid)
144 | os.kill(process_info.pid, signal.SIG_DFL)
145 | _logger.debug("os.kill call succeeded")
146 | except OSError as e:
147 | _logger.debug("os.kill call failed: %s", e)
148 | # If the process doesn't exists, we are done.
149 | if e.errno == errno.ESRCH:
150 | return True
151 | # Something unexpected has happened
152 | output.error("%s", e)
153 | return False
154 | time.sleep(1)
155 | _logger.debug("The PID %s has not been terminated after %s retries",
156 | process_info.pid, retries)
157 | return False
158 |
--------------------------------------------------------------------------------
/rpm/rhel5/python26-psycopg2.spec:
--------------------------------------------------------------------------------
1 | # Use Python 2.6
2 | %global pybasever 2.6
3 | %global __python_ver 26
4 | %global __python %{_bindir}/python%{pybasever}
5 | %global __os_install_post %{__multiple_python_os_install_post}
6 |
7 | %{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
8 | %{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
9 |
10 | %define ZPsycopgDAdir %{_localstatedir}/lib/zope/Products/ZPsycopgDA
11 |
12 | %global pgmajorversion 90
13 | %global pginstdir /usr/pgsql-9.0
14 | %global sname psycopg2
15 |
16 | Summary: A PostgreSQL database adapter for Python
17 | Name: python26-%{sname}
18 | Version: 2.4.5
19 | Release: 1%{?dist}
20 | License: LGPLv3 with exceptions
21 | Group: Applications/Databases
22 | Url: http://www.psycopg.org/psycopg/
23 | Source0: http://initd.org/psycopg/tarballs/PSYCOPG-2-4/%{sname}-%{version}.tar.gz
24 | Patch0: setup.cfg.patch
25 | BuildRequires: python%{__python_ver}-devel postgresql%{pgmajorversion}-devel
26 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n)
27 | Requires: python-abi = %(%{__python} -c "import sys ; print sys.version[:3]")
28 |
29 | %description
30 | psycopg is a PostgreSQL database adapter for the Python programming
31 | language (just like pygresql and popy.) It was written from scratch
32 | with the aim of being very small and fast, and stable as a rock. The
33 | main advantages of psycopg are that it supports the full Python
34 | DBAPI-2.0 and being thread safe at level 2.
35 |
36 | %package doc
37 | Summary: Documentation for psycopg python PostgreSQL database adapter
38 | Group: Documentation
39 | Requires: %{name} = %{version}-%{release}
40 |
41 | %description doc
42 | Documentation and example files for the psycopg python PostgreSQL
43 | database adapter.
44 |
45 | %package test
46 | Summary: Tests for psycopg2
47 | Group: Development/Libraries
48 | Requires: %{name} = %{version}-%{release}
49 |
50 | %description test
51 | Tests for psycopg2.
52 |
53 | %package zope
54 | Summary: Zope Database Adapter ZPsycopgDA
55 | Group: Applications/Databases
56 | Requires: %{name} = %{version}-%{release} zope
57 |
58 | %description zope
59 | Zope Database Adapter for PostgreSQL, called ZPsycopgDA
60 |
61 | %prep
62 | %setup -q -n psycopg2-%{version}
63 | %patch0 -p0
64 |
65 | %build
66 | %{__python} setup.py build
67 | # Fix for wrong-file-end-of-line-encoding problem; upstream also must fix this.
68 | for i in `find doc -iname "*.html"`; do sed -i 's/\r//' $i; done
69 | for i in `find doc -iname "*.css"`; do sed -i 's/\r//' $i; done
70 |
71 | %install
72 | rm -Rf %{buildroot}
73 | mkdir -p %{buildroot}%{python_sitearch}/psycopg2
74 | %{__python} setup.py install --no-compile --root %{buildroot}
75 |
76 | install -d %{buildroot}%{ZPsycopgDAdir}
77 | cp -pr ZPsycopgDA/* %{buildroot}%{ZPsycopgDAdir}
78 |
79 | %clean
80 | rm -rf %{buildroot}
81 |
82 | %files
83 | %defattr(-,root,root)
84 | %doc AUTHORS ChangeLog INSTALL LICENSE README
85 | %dir %{python_sitearch}/psycopg2
86 | %{python_sitearch}/psycopg2/*.py
87 | %{python_sitearch}/psycopg2/*.pyc
88 | %{python_sitearch}/psycopg2/*.so
89 | %{python_sitearch}/psycopg2/*.pyo
90 | %{python_sitearch}/psycopg2-*.egg-info
91 |
92 | %files doc
93 | %defattr(-,root,root)
94 | %doc doc examples/
95 |
96 | %files test
97 | %defattr(-,root,root)
98 | %{python_sitearch}/%{sname}/tests/*
99 |
100 | %files zope
101 | %defattr(-,root,root)
102 | %dir %{ZPsycopgDAdir}
103 | %{ZPsycopgDAdir}/*.py
104 | %{ZPsycopgDAdir}/*.pyo
105 | %{ZPsycopgDAdir}/*.pyc
106 | %{ZPsycopgDAdir}/dtml/*
107 | %{ZPsycopgDAdir}/icons/*
108 |
109 | %changelog
110 | * Wed May 9 2012 - Marco Neciarini 2.4.5-1
111 | - Update to version 2.4.5
112 |
113 | * Mon Aug 22 2011 Devrim GUNDUZ 2.4.2-1
114 | - Update to 2.4.2
115 | - Add a patch for pg_config path.
116 | - Add new subpackage: test
117 |
118 | * Tue Mar 16 2010 Devrim GUNDUZ 2.0.14-1
119 | - Update to 2.0.14
120 |
121 | * Mon Oct 19 2009 Devrim GUNDUZ 2.0.13-1
122 | - Update to 2.0.13
123 |
124 | * Mon Sep 7 2009 Devrim GUNDUZ 2.0.12-1
125 | - Update to 2.0.12
126 |
127 | * Tue May 26 2009 Devrim GUNDUZ 2.0.11-1
128 | - Update to 2.0.11
129 |
130 | * Fri Apr 24 2009 Devrim GUNDUZ 2.0.10-1
131 | - Update to 2.0.10
132 |
133 | * Thu Mar 2 2009 Devrim GUNDUZ 2.0.9-1
134 | - Update to 2.0.9
135 |
136 | * Wed Apr 30 2008 - Devrim GUNDUZ 2.0.7-1
137 | - Update to 2.0.7
138 |
139 | * Fri Jun 15 2007 - Devrim GUNDUZ 2.0.6-1
140 | - Update to 2.0.6
141 |
142 | * Sun May 06 2007 Thorsten Leemhuis
143 | - rebuilt for RHEL5 final
144 |
145 | * Wed Dec 6 2006 - Devrim GUNDUZ 2.0.5.1-4
146 | - Rebuilt for PostgreSQL 8.2.0
147 |
148 | * Mon Sep 11 2006 - Devrim GUNDUZ 2.0.5.1-3
149 | - Rebuilt
150 |
151 | * Wed Sep 6 2006 - Devrim GUNDUZ 2.0.5.1-2
152 | - Remove ghost'ing, per Python Packaging Guidelines
153 |
154 | * Mon Sep 4 2006 - Devrim GUNDUZ 2.0.5.1-1
155 | - Update to 2.0.5.1
156 |
157 | * Sun Aug 6 2006 - Devrim GUNDUZ 2.0.3-3
158 | - Fixed zope package dependencies and macro definition, per bugzilla review (#199784)
159 | - Fixed zope package directory ownership, per bugzilla review (#199784)
160 | - Fixed cp usage for zope subpackage, per bugzilla review (#199784)
161 |
162 | * Mon Jul 31 2006 - Devrim GUNDUZ 2.0.3-2
163 | - Fixed 64 bit builds
164 | - Fixed license
165 | - Added Zope subpackage
166 | - Fixed typo in doc description
167 | - Added macro for zope subpackage dir
168 |
169 | * Mon Jul 31 2006 - Devrim GUNDUZ 2.0.3-1
170 | - Update to 2.0.3
171 | - Fixed spec file, per bugzilla review (#199784)
172 |
173 | * Sat Jul 22 2006 - Devrim GUNDUZ 2.0.2-3
174 | - Removed python dependency, per bugzilla review. (#199784)
175 | - Changed doc package group, per bugzilla review. (#199784)
176 | - Replaced dos2unix with sed, per guidelines and bugzilla review (#199784)
177 | - Fix changelog dates
178 |
179 | * Sat Jul 21 2006 - Devrim GUNDUZ 2.0.2-2
180 | - Added dos2unix to buildrequires
181 | - removed python related part from package name
182 |
183 | * Fri Jul 20 2006 - Devrim GUNDUZ 2.0.2-1
184 | - Fix rpmlint errors, including dos2unix solution
185 | - Re-engineered spec file
186 |
187 | * Fri Jan 23 2006 - Devrim GUNDUZ
188 | - First 2.0.X build
189 |
190 | * Fri Jan 23 2006 - Devrim GUNDUZ
191 | - Update to 1.2.21
192 |
193 | * Tue Dec 06 2005 - Devrim GUNDUZ
194 | - Initial release for 1.1.20
195 |
--------------------------------------------------------------------------------
/barman/exceptions.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2011-2016 2ndQuadrant Italia Srl
2 | #
3 | # This file is part of Barman.
4 | #
5 | # Barman is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Barman is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Barman. If not, see .
17 |
18 |
19 | class BarmanException(Exception):
20 | """
21 | The base class of all other barman exceptions
22 | """
23 |
24 |
25 | class ConfigurationException(BarmanException):
26 | """
27 | Base exception for all the Configuration errors
28 | """
29 |
30 |
31 | class CommandException(BarmanException):
32 | """
33 | Base exception for all the errors related to
34 | the execution of a Command.
35 | """
36 |
37 |
38 | class CompressionException(BarmanException):
39 | """
40 | Base exception for all the errors related to
41 | the execution of a compression action.
42 | """
43 |
44 |
45 | class PostgresException(BarmanException):
46 | """
47 | Base exception for all the errors related to PostgreSQL.
48 | """
49 |
50 |
51 | class BackupException(BarmanException):
52 | """
53 | Base exception for all the errors related to the execution of a backup.
54 | """
55 |
56 |
57 | class WALFileException(BarmanException):
58 | """
59 | Base exception for all the errors related to WAL files.
60 | """
61 |
62 |
63 | class HookScriptException(BarmanException):
64 | """
65 | Base exception for all the errors related to Hook Script execution.
66 | """
67 |
68 |
69 | class LockFileException(BarmanException):
70 | """
71 | Base exception for lock related errors
72 | """
73 |
74 |
75 | class DuplicateWalFile(WALFileException):
76 | """
77 | A duplicate WAL file has been found
78 | """
79 |
80 |
81 | class MatchingDuplicateWalFile(DuplicateWalFile):
82 | """
83 | A duplicate WAL file has been found, but it's identical to the one we
84 | already have.
85 | """
86 |
87 |
88 | class SshCommandException(CommandException):
89 | """
90 | Error parsing ssh_command parameter
91 | """
92 |
93 |
94 | class UnknownBackupIdException(BackupException):
95 | """
96 | The searched backup_id doesn't exists
97 | """
98 |
99 |
100 | class BackupInfoBadInitialisation(BackupException):
101 | """
102 | Exception for a bad initialization error
103 | """
104 |
105 |
106 | class CommandFailedException(CommandException):
107 | """
108 | Exception representing a failed command
109 | """
110 |
111 |
112 | class CommandMaxRetryExceeded(CommandFailedException):
113 | """
114 | A command with retry_times > 0 has exceeded the number of available retry
115 | """
116 | def __init__(self, exc):
117 | """
118 | :param Exception exc: the last exception raised by the command
119 | """
120 | self.exc = exc
121 | super(CommandMaxRetryExceeded, self).__init__(*exc.args)
122 |
123 |
124 | class RsyncListFilesFailure(CommandException):
125 | """
126 | Failure parsing the output of a "rsync --list-only" command
127 | """
128 |
129 |
130 | class DataTransferFailure(CommandException):
131 | """
132 | Used to pass failure details from a data transfer Command
133 | """
134 |
135 | @classmethod
136 | def from_command_error(cls, cmd, e, msg):
137 | """
138 | This method build a DataTransferFailure exception and report the
139 | provided message to the user (both console and log file) along with
140 | the output of the failed command.
141 |
142 | :param str cmd: The command that failed the transfer
143 | :param CommandFailedException e: The exception we are handling
144 | :param str msg: a descriptive message on what we are trying to do
145 | :return DataTransferFailure: will contain the message provided in msg
146 | """
147 | details = msg
148 | details += "\n%s error:\n" % cmd
149 | details += e.args[0]['out']
150 | details += e.args[0]['err']
151 | return cls(details)
152 |
153 |
154 | class CompressionIncompatibility(CompressionException):
155 | """
156 | Exception for compression incompatibility
157 | """
158 |
159 |
160 | class FsOperationFailed(CommandException):
161 | """
162 | Exception which represents a failed execution of a command on FS
163 | """
164 |
165 |
166 | class LockFileBusy(LockFileException):
167 | """
168 | Raised when a lock file is not free
169 | """
170 |
171 |
172 | class LockFilePermissionDenied(LockFileException):
173 | """
174 | Raised when a lock file is not accessible
175 | """
176 |
177 |
178 | class LockFileParsingError(LockFileException):
179 | """
180 | Raised when the content of the lockfile is unexpected
181 | """
182 |
183 |
184 | class ConninfoException(ConfigurationException):
185 | """
186 | Error for missing or failed parsing of the conninfo parameter (DSN)
187 | """
188 |
189 |
190 | class PostgresConnectionError(PostgresException):
191 | """
192 | Error connecting to the PostgreSQL server
193 | """
194 | def __str__(self):
195 | # Returns the first line
196 | if self.args and self.args[0]:
197 | return str(self.args[0]).splitlines()[0].strip()
198 | else:
199 | return ''
200 |
201 |
202 | class PostgresAppNameError(PostgresConnectionError):
203 | """
204 | Error setting application name with PostgreSQL server
205 | """
206 |
207 |
208 | class PostgresSuperuserRequired(PostgresException):
209 | """
210 | Superuser access is required
211 | """
212 |
213 |
214 | class PostgresIsInRecovery(PostgresException):
215 | """
216 | PostgreSQL is in recovery, so no write operations are allowed
217 | """
218 |
219 |
220 | class PostgresUnsupportedFeature(PostgresException):
221 | """
222 | Unsupported feature
223 | """
224 |
225 |
226 | class PostgresDuplicateReplicationSlot(PostgresException):
227 | """
228 | The creation of a physical replication slot failed because
229 | the slot already exists
230 | """
231 |
232 |
233 | class PostgresReplicationSlotsFull(PostgresException):
234 | """
235 | The creation of a physical replication slot failed because
236 | the all the replication slots have been taken
237 | """
238 |
239 |
240 | class PostgresReplicationSlotInUse(PostgresException):
241 | """
242 | The drop of a physical replication slot failed because
243 | the replication slots is in use
244 | """
245 |
246 |
247 | class PostgresInvalidReplicationSlot(PostgresException):
248 | """
249 | Exception representing a failure during the deletion of a non
250 | existent replication slot
251 | """
252 |
253 |
254 | class TimeoutError(CommandException):
255 | """
256 | A timeout occurred.
257 | """
258 |
259 |
260 | class ArchiverFailure(WALFileException):
261 | """
262 | Exception representing a failure during the execution
263 | of the archive process
264 | """
265 |
266 |
267 | class BadXlogSegmentName(WALFileException):
268 | """
269 | Exception for a bad xlog name
270 | """
271 |
272 |
273 | class BadHistoryFileContents(WALFileException):
274 | """
275 | Exception for a corrupted history file
276 | """
277 |
278 |
279 | class AbortedRetryHookScript(HookScriptException):
280 | """
281 | Exception for handling abort of retry hook scripts
282 | """
283 | def __init__(self, hook):
284 | """
285 | Initialise the exception with hook script info
286 | """
287 | self.hook = hook
288 |
289 | def __str__(self):
290 | """
291 | String representation
292 | """
293 | return ("Abort '%s_%s' retry hook script (%s, exit code: %d)" % (
294 | self.hook.phase, self.hook.name,
295 | self.hook.script, self.hook.exit_status))
296 |
--------------------------------------------------------------------------------
/doc/manual/21-preliminary_steps.en.md:
--------------------------------------------------------------------------------
1 | ## Preliminary steps
2 |
3 | This section contains some preliminary steps that you need to
4 | undertake before setting up your PostgreSQL server in Barman.
5 |
6 | > **IMPORTANT:**
7 | > Before you proceed, it is important that you have made your decision
8 | > in terms of WAL archiving and backup strategies, as outlined in the
9 | > _"Design and architecture"_ section. In particular, you should
10 | > decide which WAL archiving methods to use, as well as the backup
11 | > method.
12 |
13 | ### PostgreSQL connection
14 |
15 | You need to make sure that the `backup` server can connect to
16 | the PostgreSQL server on `pg` as superuser. This operation is mandatory.
17 |
18 | We recommend creating a specific user in PostgreSQL, named `barman`,
19 | as follows:
20 |
21 | ``` bash
22 | postgres@pg$ createuser -s -W barman
23 | ```
24 |
25 | > **IMPORTANT:** The above command will prompt for a password,
26 | > which you are then advised to add to the `~barman/.pgpass` file
27 | > on the `backup` server. For further information, please refer to
28 | > ["The Password File" section in the PostgreSQL Documentation] [pgpass].
29 |
30 | This connection is required by Barman in order to coordinate its
31 | activities with the server, as well as for monitoring purposes.
32 |
33 | You can choose your favourite client authentication method among those
34 | offered by PostgreSQL. More information can be found in the
35 | ["Client Authentication" section of the PostgreSQL Documentation] [pghba].
36 |
37 | Make sure you test the following command before proceeding:
38 |
39 | ``` bash
40 | barman@backup$ psql -c 'SELECT version()' -U barman -h pg postgres
41 | ```
42 |
43 | Write down the above information (user name, host name and database
44 | name) and keep it for later. You will need it with in the `conninfo`
45 | option for your server configuration, like in this example:
46 |
47 | ``` ini
48 | [pg]
49 | ; ...
50 | conninfo = host=pg user=barman dbname=postgres
51 | ```
52 |
53 | > **NOTE:** Barman honours the `application_name` connection option
54 | > for PostgreSQL servers 9.0 or higher.
55 |
56 |
57 | ### PostgreSQL WAL archiving and replication
58 |
59 | Before you proceed, you need to properly configure PostgreSQL on `pg`
60 | to accept streaming replication connections from the Barman
61 | server. Please read the following sections in the PostgreSQL
62 | documentation:
63 |
64 | - [Role attributes] [roles]
65 | - [The pg_hba.conf file] [authpghba]
66 | - [Setting up standby servers using streaming replication] [streamprot]
67 |
68 |
69 | One configuration parameter that is crucially important is the
70 | `wal_level` parameter. This parameter must be configured to ensure
71 | that all the useful information necessary for a backup to be coherent
72 | are included in the transaction log file.
73 |
74 | ``` ini
75 | wal_level = 'replica'
76 | ```
77 |
78 | For PostgreSQL versions older than 9.6, `wal_level` must be set to
79 | `hot_standby`.
80 |
81 | Restart the PostgreSQL server for the configuration to be refreshed.
82 |
83 |
84 | ### PostgreSQL streaming connection
85 |
86 | If you plan to use WAL streaming or streaming backup, you need to
87 | setup a streaming connection. We recommend creating a specific user in
88 | PostgreSQL, named `streaming_barman`, as follows:
89 |
90 | ``` bash
91 | postgres@pg$ createuser -W --replication streaming_barman
92 | ```
93 |
94 | > **IMPORTANT:** The above command will prompt for a password,
95 | > which you are then advised to add to the `~barman/.pgpass` file
96 | > on the `backup` server. For further information, please refer to
97 | > ["The Password File" section in the PostgreSQL Documentation] [pgpass].
98 |
99 | You can manually verify that the streaming connection works through
100 | the following command:
101 |
102 | ``` bash
103 | barman@backup$ psql -U streaming_barman -h pg \
104 | -c "IDENTIFY_SYSTEM" \
105 | replication=1
106 | ```
107 |
108 | > **IMPORTANT:**
109 | > Please make sure you are able to connect via streaming replication
110 | > before going any further.
111 |
112 | You also need to configure the `max_wal_senders` parameter in the
113 | PostgreSQL configuration file:
114 |
115 | ``` ini
116 | max_wal_senders = 2
117 | ```
118 |
119 | This option represents the maximum number of concurrent streaming
120 | connections that the server will be allowed to manage.
121 |
122 | Another important parameter is `max_replication_slots`, which
123 | represents the maximum number of replication slots [^replslot94]
124 | that the server will be allowed to manage.
125 | This parameter is needed if you are planning to
126 | use the streaming connection to receive WAL files over the streaming
127 | connection:
128 |
129 | ``` ini
130 | max_replication_slots = 2
131 | ```
132 |
133 | [^replslot94]: Replication slots have been introduced in PostgreSQL 9.4.
134 | See section _"WAL Streaming / Replication slots"_ for
135 | details.
136 |
137 | The values proposed for `max_replication_slots` and `max_wal_senders`
138 | must be considered as examples, and the values you will use in your
139 | actual setup must be choosen after a careful evaluation of the
140 | architecture. Please consult the PostgreSQL documentation for
141 | guidelines and clarifications.
142 |
143 |
144 | ### SSH connections
145 |
146 | SSH is a protocol and a set of tools that allows you to open a remote
147 | shell to a remote server and copy files between the server and the local
148 | system. You can find more documentation about SSH usage in the article
149 | ["SSH Essentials"][ssh_essentials] by Digital Ocean.
150 |
151 | SSH key exchange is a very common practice that is used to implement
152 | secure passwordless connections between users on different machines,
153 | and it's needed to use `rsync` for WAL archiving and for backups.
154 |
155 | > **NOTE:**
156 | > This procedure is not needed if you plan to use the streaming
157 | > connection only to archive transaction logs and backup your PostgreSQL
158 | > server.
159 |
160 | [ssh_essentials]: https://www.digitalocean.com/community/tutorials/ssh-essentials-working-with-ssh-servers-clients-and-keys
161 |
162 | #### SSH configuration of postgres user
163 |
164 | Unless you have done it before, you need to create an SSH key for the
165 | PostgreSQL user. Log in as `postgres`, in the `pg` host and type:
166 |
167 | ``` bash
168 | postgres@pg$ ssh-keygen -t rsa
169 | ```
170 |
171 | As this key must be used to connect from hosts without providing a
172 | password, no passphrase should be entered during the key pair
173 | creation.
174 |
175 |
176 | #### SSH configuration of barman user
177 |
178 | As in the previous paragraph, you need to create an SSH key for the
179 | Barman user. Log in as `barman` in the `backup` host and type:
180 |
181 | ``` bash
182 | barman@backup$ ssh-keygen -t rsa
183 | ```
184 |
185 | For the same reason, no passphrase should be entered.
186 |
187 | #### From PostgreSQL to Barman
188 |
189 | The SSH connection from the PostgreSQL server to the backup server is
190 | needed to correctly archive WAL files using the `archive_command`
191 | setting.
192 |
193 | To successfully connect from the PostgreSQL server to the backup
194 | server, the PostgreSQL public key has to be configured into the
195 | authorized keys of the backup server for the `barman` user.
196 |
197 | The public key to be authorized is stored inside the `postgres` user
198 | home directory in a file named `.ssh/id_rsa.pub`, and its content
199 | should be included in a file named `.ssh/authorized_keys` inside the
200 | home directory of the `barman` user in the backup server. If the
201 | `authorized_keys` file doesn't exist, create it using `600` as
202 | permissions.
203 |
204 | The following command should succeed without any output if the SSH key
205 | pair exchange has been completed successfully:
206 |
207 | ``` bash
208 | postgres@pg$ ssh barman@backup -C true
209 | ```
210 |
211 | The value of the `archive_command` configuration parameter will be
212 | discussed in the _"WAL archiving via archive_command section"_.
213 |
214 |
215 | #### From Barman to PostgreSQL
216 |
217 | The SSH connection between the backup server and the PostgreSQL server
218 | is used for the traditional backup over rsync. Just as with the
219 | connection from the PostgreSQL server to the backup server, we should
220 | authorize the public key of the backup server in the PostgreSQL server
221 | for the `postgres` user.
222 |
223 | The content of the file `.ssh/id_rsa.pub` in the `barman` server should
224 | be put in the file named `.ssh/authorized_keys` in the PostgreSQL
225 | server. The permissions of that file should be `600`.
226 |
227 | The following command should succeed without any output if the key
228 | pair exchange has been completed successfully.
229 |
230 | ``` bash
231 | barman@backup$ ssh postgres@pg -C true
232 | ```
233 |
--------------------------------------------------------------------------------
/doc/manual/42-server-commands.en.md:
--------------------------------------------------------------------------------
1 | \newpage
2 |
3 | # Server commands
4 |
5 | As we said in the previous section, server commands work directly on
6 | a PostgreSQL server or on its area in Barman, and are useful to check
7 | its status, perform maintainance operations, take backups, and
8 | manage the WAL archive.
9 |
10 | ## `archive_wal`
11 |
12 | The `archive_wal` command execute maintainance operations on WAL files
13 | for a given server. This operations include processing of the WAL
14 | files received from the streaming connection or from the
15 | `archive_command` or both.
16 |
17 | > **IMPORTANT:**
18 | > The `archive_wal` command, even if it can be directly invoked, is
19 | > designed to be started from the `cron` general command.
20 |
21 | ## `backup`
22 |
23 | The `backup` command takes a full backup (_base backup_) of a given
24 | server. It has several options that let you override the corresponding
25 | configuration parameter for the new backup. For more information,
26 | consult the manual page.
27 |
28 | You can perform a full backup for a given server with:
29 |
30 | ``` bash
31 | barman backup
32 | ```
33 |
34 | > **TIP:**
35 | > You can use `barman backup all` to sequentially backup all your
36 | > configured servers.
37 |
38 |
39 | ## `check`
40 |
41 | You can check the connection to a given server and the
42 | configuration coherence with the `check` command:
43 |
44 | ``` bash
45 | barman check
46 | ```
47 |
48 | > **TIP:**
49 | > You can use `barman check all` to check all your configured servers.
50 |
51 | > **IMPORTANT:**
52 | > The `check` command is probably the most critical feature that
53 | > Barman implements. We recommend to integrate it with your alerting
54 | > and monitoring infrastructure. The `--nagios` option allows you
55 | > to easily create a plugin for Nagios/Icinga.
56 |
57 | ## `get-wal`
58 |
59 | Barman allows users to request any _xlog_ file from its WAL archive
60 | through the `get-wal` command:
61 |
62 | ``` bash
63 | barman get-wal [-o OUTPUT_DIRECTORY] [-j|-x]
64 | ```
65 |
66 | If the requested WAL file is found in the server archive, the
67 | uncompressed content will be returned to `STDOUT`, unless otherwise
68 | specified.
69 |
70 | The following options are available for the `get-wal` command:
71 |
72 | - `-o` allows users to specify a destination directory where Barman
73 | will deposit the requested WAL file
74 | - `-j` will compress the output using `bzip2` algorithm
75 | - `-x` will compress the output using `gzip` algorithm
76 | - `-p SIZE` peeks from the archive up to WAL files, starting from
77 | the requested file
78 |
79 | It is possible to use `get-wal` during a recovery operation,
80 | transforming the Barman server into a _WAL hub_ for your servers. This
81 | can be automatically achieved by adding the `get-wal` value to the
82 | `recovery_options` global/server configuration option:
83 |
84 | ``` ini
85 | recovery_options = 'get-wal'
86 | ```
87 |
88 | `recovery_options` is a global/server option that accepts a list of
89 | comma separated values. If the keyword `get-wal` is present during a
90 | recovery operation, Barman will prepare the `recovery.conf` file by
91 | setting the `restore_command` so that `barman get-wal` is used to
92 | fetch the required WAL files.
93 |
94 | This is an example of a `restore_command` for a local recovery:
95 |
96 | ``` ini
97 | restore_command = 'sudo -u barman barman get-wal SERVER %f > %p'
98 | ```
99 |
100 | Please note that the `get-wal` command should always be invoked as
101 | `barman` user, and that it requires the correct permission to
102 | read the WAL files from the catalog. This is the reason why we are
103 | using `sudo -u barman` in the example.
104 |
105 | Setting `recovery_options` to `get-wal` for a remote recovery will instead
106 | generate a `restore_command` using the `barman-wal-restore` script.
107 | `barman-wal-restore` is a more resilient shell script which manages SSH
108 | connection errors.
109 |
110 | This script has many useful options such as the automatic compression and
111 | decompression of the WAL files and the *peek* feature, which allows you
112 | to retrieve the next WAL files while PostgreSQL is applying one of them. It is
113 | an excellent way to optimise the bandwidth usage between PostgreSQL and
114 | Barman.
115 |
116 | `barman-wal-restore` is available in the `barman-cli` project or package.
117 |
118 | This is an example of a `restore_command` for a remote recovery:
119 |
120 | ``` ini
121 | restore_command = 'barman-wal-restore -U barman backup SERVER %f %p'
122 | ```
123 |
124 | Since it uses SSH to communicate with the Barman server, SSH key authentication
125 | is required for the `postgres` user to login as `barman` on the backup server.
126 |
127 | > **IMPORTANT:**
128 | > Even though `recovery_options` aims to automate the process, using
129 | > the `get-wal` facility requires manual intervention and proper
130 | > testing.
131 |
132 | ## `list-backup`
133 |
134 | You can list the catalog of available backups for a given server
135 | with:
136 |
137 | ``` bash
138 | barman list-backup
139 | ```
140 |
141 | > **TIP:** You can request a full list of the backups of all servers
142 | > using `all` as the server name.
143 |
144 | To have a machine-readable output you can use the `--minimal` option.
145 |
146 | ## `rebuild-xlogdb`
147 |
148 | At any time, you can regenerate the content of the WAL archive for a
149 | specific server (or every server, using the `all` shortcut). The WAL
150 | archive is contained in the `xlog.db` file and every server managed by
151 | Barman has its own copy.
152 |
153 | The `xlog.db` file can be rebuilt with the `rebuild-xlogdb`
154 | command. This will scan all the archived WAL files and regenerate the
155 | metadata for the archive.
156 |
157 | For example:
158 |
159 | ``` bash
160 | barman rebuild-xlogdb
161 | ```
162 |
163 | ## `receive-wal`
164 |
165 | This command manages the `receive-wal` process, which uses the
166 | streaming protocol to receive WAL files from the PostgreSQL streaming
167 | connection.
168 |
169 | ### receive-wal process management
170 |
171 | If the command is run without options, a `receive-wal` process will
172 | be started. This command is based on the `pg_receivexlog` PostgreSQL
173 | command.
174 |
175 | ``` bash
176 | barman receive-wal
177 | ```
178 |
179 | If the command is run with the `--stop` option, the currently running
180 | `receive-wal` process will be stopped.
181 |
182 | The `receive-wal` process uses a status file to track last written
183 | record of the transaction log. When the status file needs to be
184 | cleaned, the `--reset` option can be used.
185 |
186 | > **IMPORTANT:** If you are not using replication slots, you rely
187 | > on the value of `wal_keep_segments`. Be aware that under high peeks
188 | > of workload on the database, the `receive-wal` process
189 | > might fall behind and go out of sync. As a precautionary measure,
190 | > Barman currently requires that users manually execute the command with the
191 | > `--reset` option, to avoid making wrong assumptions.
192 |
193 | ### Replication slot management
194 |
195 | The `receive-wal` process is also useful to create or drop the
196 | replication slot needed by Barman for its WAL archiving procedure.
197 |
198 | With the `--create-slot` option, the replication slot named after the
199 | `slot_name` configuration option will be created on the PostgreSQL
200 | server.
201 |
202 | With the `--drop-slot`, the previous replication slot will be deleted.
203 |
204 | ## `replication-status`
205 |
206 | The `replication-status` command reports the status of any streaming
207 | client currently attached to the PostgreSQL server, including the
208 | `receive-wal` process of your Barman server (if configured).
209 |
210 | You can execute the command as follows:
211 |
212 | ``` bash
213 | barman replication-status
214 | ```
215 |
216 | > **TIP:** You can request a full status report of the replica
217 | > for all your servers using `all` as the server name.
218 |
219 | To have a machine-readable output you can use the `--minimal` option.
220 |
221 | ## `show-server`
222 |
223 | You can show the configuration parameters for a given server with:
224 |
225 | ``` bash
226 | barman show-server
227 | ```
228 |
229 | > **TIP:** you can request a full configuration report using `all` as
230 | > the server name.
231 |
232 |
233 | ## `status`
234 |
235 | The `status` command shows live information and status of a PostgreSQL
236 | server or of all servers if you use `all` as server name.
237 |
238 | ``` bash
239 | barman show-server
240 | ```
241 |
242 | ## `switch-xlog`
243 |
244 | This command makes the PostgreSQL server switch to another transaction
245 | log file, allowing the current log file to be closed, received and then
246 | archived.
247 |
248 | ``` bash
249 | barman switch-xlog
250 | ```
251 |
252 | If there has been no transaction activity since the last transaction
253 | log file switch, the switch needs to be forced using the
254 | `--force` option.
255 |
256 | The `--archive` option requests Barman to trigger WAL archiving after
257 | the xlog switch. By default, a 30 seconds timeout is enforced (this
258 | can be changed with `--archive-timeout`). If no WAL file is received,
259 | an error is returned.
260 |
--------------------------------------------------------------------------------
/doc/manual/10-design.en.md:
--------------------------------------------------------------------------------
1 | \newpage
2 |
3 | # Design and architecture
4 |
5 | ## Where to install Barman
6 |
7 | One of the foundations of Barman is the ability to operate remotely from the database server, via the network.
8 |
9 | Theoretically, you could have your Barman server located in a data centre in another part of the world, thousands of miles away from your PostgreSQL server.
10 | Realistically, you do not want your Barman server to be too far from your PostgreSQL server, so that both backup and recovery times are kept under control.
11 |
12 | Even though there is no _"one size fits all"_ way to setup Barman, there are a couple of recommendations that we suggest you abide by, in particular:
13 |
14 | - Install Barman on a dedicated server
15 | - Do not share the same storage with your PostgreSQL server
16 | - Integrate Barman with your monitoring infrastructure [^nagios]
17 | - Test everything before you deploy it to production
18 |
19 | [^nagios]: Integration with Nagios/Icinga is straightforward thanks to the `barman check --nagios` command, one of the most important features of Barman and a true lifesaver.
20 |
21 | A reasonable way to start modelling your disaster recovery architecture is to:
22 |
23 | - design a couple of possibile architectures in respect to PostgreSQL and Barman, such as:
24 | 1. same data centre
25 | 2. different data centre in the same metropolitan area
26 | 3. different data centre
27 | - elaborate the pros and the cons of each hypothesis
28 | - evaluate the single points of failure (SPOF) of your system, with cost-benefit analysis
29 | - make your decision and implement the initial solution
30 |
31 | Having said this, a very common setup for Barman is to be installed in the same data centre where your PostgreSQL servers are. In this case, the single point of failure is the data centre. Fortunately, the impact of such a SPOF can be alleviated thanks to a feature called _hook scripts_. Indeed, backups of Barman can be exported on different media, such as _tape_ via `tar`, or locations, like an _S3 bucket_ in the Amazon cloud.
32 |
33 | Remember that no decision is forever. You can start this way and adapt over time to the solution that suits you best. However, try and keep it simple to start with.
34 |
35 | ## One Barman, many PostgreSQL servers
36 |
37 | Another relevant feature that was first introduced by Barman is support for multiple servers. Barman can store backup data coming from multiple PostgreSQL instances, even with different versions, in a centralised way. [^recver]
38 |
39 | [^recver]: The same [requirements for PostgreSQL's PITR][requirements_recovery] apply for recovery, as detailed in the section _"Requirements for recovery"_.
40 |
41 | As a result, you can model complex disaster recovery architectures, forming a "star schema", where PostgreSQL servers rotate around a central Barman server.
42 |
43 | Every architecture makes sense in its own way. Choose the one that resonates with you, and most importantly, the one you trust, based on real experimentation and testing.
44 |
45 | From this point forward, for the sake of simplicity, this guide will assume a basic architecture:
46 |
47 | - one PostgreSQL instance (with host name `pg`)
48 | - one backup server with Barman (with host name `backup`)
49 |
50 | ## Streaming backup vs rsync/SSH
51 |
52 | Traditionally, Barman has always operated remotely via SSH, taking advantage of `rsync` for physical backup operations. Version 2.0 introduces native support for PostgreSQL's streaming replication protocol for backup operations, via `pg_basebackup`. [^fmatrix]
53 |
54 | [^fmatrix]: Check in the "Feature matrix" which PostgreSQL versions support streaming replication backups with Barman.
55 |
56 | Choosing one of these two methods is a decision you will need to make.
57 |
58 | On a general basis, starting from Barman 2.0, backup over streaming replication is the recommended setup for PostgreSQL 9.4 or higher. Moreover, if you do not make use of tablespaces, backup over streaming can be used starting from PostgreSQL 9.2.
59 |
60 | > **IMPORTANT:** \newline
61 | > Because Barman transparently makes use of `pg_basebackup`, features such as incremental backup, deduplication, and network compression are currently not available. In this case, bandwidth limitation has some restrictions - compared to the traditional method via `rsync`.
62 |
63 | Traditional backup via `rsync`/SSH is available for all versions of PostgreSQL starting from 8.3, and it is recommended in all cases where `pg_basebackup` limitations occur (for example, a very large database that can benefit from incremental backup and deduplication).
64 |
65 | The reason why we recommend streaming backup is that, based on our experience, it is easier to setup than the traditional one. Also, streaming backup allows you to backup a PostgreSQL server on Windows[^windows], and makes life easier when working with Docker.
66 |
67 | [^windows]: Backup of a PostgreSQL server on Windows is possible, but it is still experimental because it is not yet part of our continuous integration system. See section _"How to setup a Windows based server"_ for details.
68 |
69 | ## Standard archiving, WAL streaming ... or both
70 |
71 | PostgreSQL's Point-In-Time-Recovery requires that transactional logs, also known as _xlog_ or WAL files, are stored alongside of base backups.
72 |
73 | Traditionally, Barman has supported standard WAL file shipping through PostgreSQL's `archive_command` (usually via `rsync`/SSH). With this method, WAL files are archived only when PostgreSQL _switches_ to a new WAL file. To keep it simple, this normally happens every 16MB worth of data changes.
74 |
75 | Barman 1.6.0 introduces streaming of WAL files for PostgreSQL servers 9.2 or higher, as an additional method for transactional log archiving, through `pg_receivexlog`. WAL streaming is able to reduce the risk of data loss, bringing RPO down to _near zero_ values.
76 |
77 | Barman 2.0 introduces support for replication slots with PostgreSQL servers 9.4 or above, therefore allowing WAL streaming-only configurations. Moreover, you can now add Barman as a synchronous WAL receiver in your PostgreSQL 9.5 (or higher) cluster, and achieve **zero data loss** (RPO=0).
78 |
79 | In some cases you have no choice and you are forced to use traditional archiving. In others, you can choose whether to use both or just WAL streaming.
80 | Unless you have strong reasons not to do it, we recommend to use both channels, for maximum reliability and robustness.
81 |
82 | ## Two typical scenarios for backups
83 |
84 | In order to make life easier for you, below we summarise the two most typical scenarios for a given PostgreSQL server in Barman.
85 |
86 | Bear in mind that this is a decision that you must make for every single server that you decide to back up with Barman. This means that you can have heterogeneous setups within the same installation.
87 |
88 | As mentioned before, we will only worry about the PostgreSQL server (`pg`) and the Barman server (`backup`). However, in real life, your architecture will most likely contain other technologies such as repmgr, pgBouncer, Nagios/Icinga, and so on.
89 |
90 | ### Scenario 1: Backup via streaming protocol
91 |
92 | If you are using PostgreSQL 9.4 or higher, and your database falls under a general use case scenario, you will likely end up deciding on a streaming backup installation - see figure \ref{scenario1-design} below.
93 |
94 |
95 | { width=80% }
96 |
97 | In this scenario, you will need to configure:
98 |
99 | 1. a standard connection to PostgreSQL, for management, coordination, and monitoring purposes
100 | 2. a streaming replication connection that will be used by both `pg_basebackup` (for base backup operations) and `pg_receivexlog` (for WAL streaming)
101 |
102 | This setup, in Barman's terminology, is known as **streaming-only** setup, as it does not require any SSH connection for backup and archiving operations. This is particularly suitable and extremely practical for Docker environments.
103 |
104 | However, as mentioned before, you can configure standard archiving as well and implement a more robust architecture - see figure \ref{scenario1b-design} below.
105 |
106 | { width=80% }
107 |
108 | This alternate approach requires:
109 |
110 | - an additional SSH connection that allows the `postgres` user on the PostgreSQL server to connect as `barman` user on the Barman server
111 | - the `archive_command` in PostgreSQL be configured to ship WAL files to Barman
112 |
113 | This architecture is available also to PostgreSQL 9.2/9.3 users that do not use tablespaces.
114 |
115 |
116 | ### Scenario 2: Backup via `rsync`/SSH
117 |
118 | The _traditional_ setup of `rsync` over SSH is the only available option for:
119 |
120 | - PostgreSQL servers version 8.3, 8.4, 9.0 or 9.1
121 | - PostgreSQL servers version 9.2 or 9.3 that are using tablespaces
122 | - incremental backup and deduplication
123 | - network compression during backups
124 | - finer control of bandwidth usage, including on a tablespace basis
125 |
126 | { width=80% }
127 |
128 | In this scenario, you will need to configure:
129 |
130 | 1. a standard connection to PostgreSQL for management, coordination, and monitoring purposes
131 | 2. an SSH connection for base backup operations to be used by `rsync` that allows the `barman` user on the Barman server to connect as `postgres` user on the PostgreSQL server
132 | 3. an SSH connection for WAL archiving to be used by the `archive_command` in PostgreSQL and that allows the `postgres` user on the PostgreSQL server to connect as `barman` user on the Barman server
133 |
134 | Starting from PostgreSQL 9.2, you can add a streaming replication connection that is used for WAL streaming and significantly reduce RPO. This more robust implementation is depicted in figure \ref{scenario2b-design}.
135 |
136 | { width=80% }
137 |
138 |
139 |
--------------------------------------------------------------------------------
/barman/hooks.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2011-2016 2ndQuadrant Italia Srl
2 | #
3 | # This file is part of Barman.
4 | #
5 | # Barman is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Barman is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Barman. If not, see .
17 |
18 | """
19 | This module contains the logic to run hook scripts
20 | """
21 |
22 | import logging
23 | import time
24 |
25 | from barman import version
26 | from barman.command_wrappers import Command
27 | from barman.exceptions import AbortedRetryHookScript, UnknownBackupIdException
28 |
29 | _logger = logging.getLogger(__name__)
30 |
31 |
32 | class HookScriptRunner(object):
33 | def __init__(self, backup_manager, name, phase=None, error=None,
34 | retry=False, **extra_env):
35 | """
36 | Execute a hook script managing its environment
37 | """
38 | self.backup_manager = backup_manager
39 | self.name = name
40 | self.extra_env = extra_env
41 | self.phase = phase
42 | self.error = error
43 | self.retry = retry
44 |
45 | self.environment = None
46 | self.exit_status = None
47 | self.exception = None
48 | self.script = None
49 |
50 | self.reset()
51 |
52 | def reset(self):
53 | """
54 | Reset the status of the class.
55 | """
56 | self.environment = dict(self.extra_env)
57 | config_file = self.backup_manager.config.config.config_file
58 | self.environment.update({
59 | 'BARMAN_VERSION': version.__version__,
60 | 'BARMAN_SERVER': self.backup_manager.config.name,
61 | 'BARMAN_CONFIGURATION': config_file,
62 | 'BARMAN_HOOK': self.name,
63 | 'BARMAN_RETRY': str(1 if self.retry else 0),
64 | })
65 | if self.error:
66 | self.environment['BARMAN_ERROR'] = self.error
67 | if self.phase:
68 | self.environment['BARMAN_PHASE'] = self.phase
69 | script_config_name = "%s_%s" % (self.phase, self.name)
70 | else:
71 | script_config_name = self.name
72 | self.script = getattr(self.backup_manager.config, script_config_name,
73 | None)
74 | self.exit_status = None
75 | self.exception = None
76 |
77 | def env_from_backup_info(self, backup_info):
78 | """
79 | Prepare the environment for executing a script
80 |
81 | :param BackupInfo backup_info: the backup metadata
82 | """
83 | try:
84 | previous_backup = self.backup_manager.get_previous_backup(
85 | backup_info.backup_id)
86 | if previous_backup:
87 | previous_backup_id = previous_backup.backup_id
88 | else:
89 | previous_backup_id = ''
90 | except UnknownBackupIdException:
91 | previous_backup_id = ''
92 | self.environment.update({
93 | 'BARMAN_BACKUP_DIR': backup_info.get_basebackup_directory(),
94 | 'BARMAN_BACKUP_ID': backup_info.backup_id,
95 | 'BARMAN_PREVIOUS_ID': previous_backup_id,
96 | 'BARMAN_STATUS': backup_info.status,
97 | 'BARMAN_ERROR': backup_info.error or '',
98 | })
99 |
100 | def env_from_wal_info(self, wal_info, full_path=None, error=None):
101 | """
102 | Prepare the environment for executing a script
103 |
104 | :param WalFileInfo wal_info: the backup metadata
105 | :param str full_path: override wal_info.fullpath() result
106 | :param str|Exception error: An error message in case of failure
107 | """
108 | self.environment.update({
109 | 'BARMAN_SEGMENT': wal_info.name,
110 | 'BARMAN_FILE': str(full_path if full_path is not None else
111 | wal_info.fullpath(self.backup_manager.server)),
112 | 'BARMAN_SIZE': str(wal_info.size),
113 | 'BARMAN_TIMESTAMP': str(wal_info.time),
114 | 'BARMAN_COMPRESSION': wal_info.compression or '',
115 | 'BARMAN_ERROR': str(error or '')
116 | })
117 |
118 | def run(self):
119 | """
120 | Run a a hook script if configured.
121 | This method must never throw any exception
122 | """
123 | # noinspection PyBroadException
124 | try:
125 | if self.script:
126 | _logger.debug("Attempt to run %s: %s", self.name, self.script)
127 | cmd = Command(
128 | self.script,
129 | env_append=self.environment,
130 | path=self.backup_manager.server.path,
131 | shell=True, check=False)
132 | self.exit_status = cmd()
133 | if self.exit_status != 0:
134 | details = "%s returned %d\n" \
135 | "Output details:\n" \
136 | % (self.script, self.exit_status)
137 | details += cmd.out
138 | details += cmd.err
139 | _logger.warning(details)
140 | else:
141 | _logger.debug("%s returned %d",
142 | self.script,
143 | self.exit_status)
144 | return self.exit_status
145 | except Exception as e:
146 | _logger.exception('Exception running %s', self.name)
147 | self.exception = e
148 | return None
149 |
150 |
151 | class RetryHookScriptRunner(HookScriptRunner):
152 |
153 | """
154 | A 'retry' hook script is a special kind of hook script that Barman
155 | tries to run indefinitely until it either returns a SUCCESS or
156 | ABORT exit code.
157 | Retry hook scripts are executed immediately before (pre) and after (post)
158 | the command execution. Standard hook scripts are executed immediately
159 | before (pre) and after (post) the retry hook scripts.
160 | """
161 |
162 | # Failed attempts before sleeping for NAP_TIME seconds
163 | ATTEMPTS_BEFORE_NAP = 5
164 | # Short break after a failure (in seconds)
165 | BREAK_TIME = 3
166 | # Long break (nap, in seconds) after ATTEMPTS_BEFORE_NAP failures
167 | NAP_TIME = 60
168 | # ABORT (and STOP) exit code
169 | EXIT_ABORT_STOP = 63
170 | # ABORT (and CONTINUE) exit code
171 | EXIT_ABORT_CONTINUE = 62
172 | # SUCCESS exit code
173 | EXIT_SUCCESS = 0
174 |
175 | def __init__(self, backup_manager, name, phase=None, error=None,
176 | **extra_env):
177 | super(RetryHookScriptRunner, self).__init__(
178 | backup_manager, name, phase, error, retry=True, **extra_env)
179 |
180 | def run(self):
181 | """
182 | Run a a 'retry' hook script, if required by configuration.
183 |
184 | Barman will retry to run the script indefinitely until it returns
185 | a EXIT_SUCCESS, or an EXIT_ABORT_CONTINUE, or an EXIT_ABORT_STOP code.
186 | There are BREAK_TIME seconds of sleep between every try.
187 | Every ATTEMPTS_BEFORE_NAP failures, Barman will sleep
188 | for NAP_TIME seconds.
189 | """
190 | # If there is no script, exit
191 | if self.script is not None:
192 | # Keep track of the number of attempts
193 | attempts = 1
194 | while True:
195 | # Run the script using the standard hook method (inherited)
196 | super(RetryHookScriptRunner, self).run()
197 |
198 | # Run the script until it returns EXIT_ABORT_CONTINUE,
199 | # or an EXIT_ABORT_STOP, or EXIT_SUCCESS
200 | if self.exit_status in (self.EXIT_ABORT_CONTINUE,
201 | self.EXIT_ABORT_STOP,
202 | self.EXIT_SUCCESS):
203 | break
204 |
205 | # Check for the number of attempts
206 | if attempts <= self.ATTEMPTS_BEFORE_NAP:
207 | attempts += 1
208 | # Take a short break
209 | _logger.debug("Retry again in %d seconds", self.BREAK_TIME)
210 | time.sleep(self.BREAK_TIME)
211 | else:
212 | # Reset the attempt number and take a longer nap
213 | _logger.debug("Reached %d failures. Take a nap "
214 | "then retry again in %d seconds",
215 | self.ATTEMPTS_BEFORE_NAP,
216 | self.NAP_TIME)
217 | attempts = 1
218 | time.sleep(self.NAP_TIME)
219 |
220 | # Outside the loop check for the exit code.
221 | if self.exit_status == self.EXIT_ABORT_CONTINUE:
222 | # Warn the user if the script exited with EXIT_ABORT_CONTINUE
223 | # Notify EXIT_ABORT_CONTINUE exit status because success and
224 | # failures are already managed in the superclass run method
225 | _logger.warning("%s was aborted (got exit status %d, "
226 | "Barman resumes)",
227 | self.script,
228 | self.exit_status)
229 | elif self.exit_status == self.EXIT_ABORT_STOP:
230 | # Log the error and raise AbortedRetryHookScript exception
231 | _logger.error("%s was aborted (got exit status %d, "
232 | "Barman requested to stop)",
233 | self.script,
234 | self.exit_status)
235 | raise AbortedRetryHookScript(self)
236 |
237 | return self.exit_status
238 |
--------------------------------------------------------------------------------
/tests/test_compressor.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013-2016 2ndQuadrant Italia Srl
2 | #
3 | # This file is part of Barman.
4 | #
5 | # Barman is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Barman is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Barman. If not, see .
17 |
18 | import base64
19 | import os
20 |
21 | import mock
22 |
23 | from barman.compression import (BZip2Compressor, CommandCompressor,
24 | CompressionManager, CustomCompressor,
25 | GZipCompressor, PyBZip2Compressor,
26 | PyGZipCompressor, identify_compression)
27 |
28 |
29 | # noinspection PyMethodMayBeStatic
30 | class TestCompressionManager(object):
31 | def test_compression_manager_creation(self):
32 | # prepare mock obj
33 | config_mock = mock.Mock()
34 | comp_manager = CompressionManager(config_mock, None)
35 | assert comp_manager
36 |
37 | def test_check_compression_none(self):
38 | # prepare mock obj
39 | config_mock = mock.Mock()
40 | config_mock.compression = "custom"
41 | comp_manager = CompressionManager(config_mock, None)
42 | assert comp_manager.check() is True
43 |
44 | def test_check_with_compression(self):
45 | # prepare mock obj
46 | config_mock = mock.Mock()
47 | comp_manager = CompressionManager(config_mock, None)
48 | assert comp_manager.check('test_compression') is False
49 |
50 | def test_get_compressor_custom(self):
51 | # prepare mock obj
52 | config_mock = mock.Mock()
53 | config_mock.compression = "custom"
54 | config_mock.custom_compression_filter = (
55 | "test_custom_compression_filter")
56 | config_mock.custom_decompression_filter = (
57 | "test_custom_decompression_filter")
58 |
59 | # check custom compression method creation
60 | comp_manager = CompressionManager(config_mock, None)
61 | assert comp_manager.get_compressor() is not None
62 |
63 | def test_get_compressor_gzip(self):
64 | # prepare mock obj
65 | config_mock = mock.Mock()
66 | config_mock.compression = "gzip"
67 |
68 | # check custom compression method creation
69 | comp_manager = CompressionManager(config_mock, None)
70 | assert comp_manager.get_compressor() is not None
71 |
72 | def test_get_compressor_bzip2(self):
73 | # prepare mock obj
74 | config_mock = mock.Mock()
75 | config_mock.compression = "bzip2"
76 |
77 | # check custom compression method creation
78 | comp_manager = CompressionManager(config_mock, None)
79 | assert comp_manager.get_compressor() is not None
80 |
81 | def test_get_compressor_invalid(self):
82 | # prepare mock obj
83 | config_mock = mock.Mock()
84 |
85 | # check custom compression method creation
86 | comp_manager = CompressionManager(config_mock, None)
87 | assert comp_manager.get_compressor("test_compression") is None
88 |
89 |
90 | # noinspection PyMethodMayBeStatic
91 | class TestIdentifyCompression(object):
92 | def test_identify_compression(self, tmpdir):
93 | bz2_tmp_file = tmpdir.join("test_file")
94 | # "test" in bz2 compression
95 | bz2_tmp_file.write(base64.b64decode(
96 | b"QlpoOTFBWSZTWczDcdQAAAJBgAAQAgAMACAAIZpoM00Zl4u5IpwoSGZhuOoA"),
97 | mode='wb')
98 |
99 | compression_bz2 = identify_compression(bz2_tmp_file.strpath)
100 | assert compression_bz2 == "bzip2"
101 |
102 | zip_tmp_file = tmpdir.join("test_file")
103 | # "test" in bz2 compression
104 | zip_tmp_file.write(base64.b64decode(
105 | b"H4sIAF0ssFIAAytJLS7hAgDGNbk7BQAAAA=="),
106 | mode='wb')
107 |
108 | # check custom compression method creation
109 | compression_zip = identify_compression(zip_tmp_file.strpath)
110 | assert compression_zip == "gzip"
111 |
112 |
113 | # noinspection PyMethodMayBeStatic
114 | class TestCommandCompressors(object):
115 |
116 | def test_creation(self):
117 | # Prepare mock obj
118 | config_mock = mock.Mock()
119 |
120 | compressor = CommandCompressor(config=config_mock,
121 | compression="dummy_compressor")
122 |
123 | assert compressor is not None
124 | assert compressor.config == config_mock
125 | assert compressor.compression == "dummy_compressor"
126 |
127 | def test_build_command(self):
128 | # prepare mock obj
129 | config_mock = mock.Mock()
130 |
131 | compressor = CommandCompressor(config=config_mock,
132 | compression="dummy_compressor")
133 |
134 | command = compressor._build_command("dummy_command")
135 |
136 | assert command.cmd == 'command(){ dummy_command > "$2" < "$1";}; ' \
137 | 'command'
138 |
139 | def test_gzip(self, tmpdir):
140 |
141 | config_mock = mock.Mock()
142 |
143 | compressor = GZipCompressor(config=config_mock, compression='gzip')
144 |
145 | src = tmpdir.join('sourcefile')
146 | src.write('content')
147 |
148 | compressor.compress(src.strpath, '%s/zipfile.zip' % tmpdir.strpath)
149 | assert os.path.exists('%s/zipfile.zip' % tmpdir.strpath)
150 | compression_zip = identify_compression('%s/zipfile.zip' %
151 | tmpdir.strpath)
152 | assert compression_zip == "gzip"
153 |
154 | compressor.decompress('%s/zipfile.zip' % tmpdir.strpath,
155 | '%s/zipfile.uncompressed' % tmpdir.strpath)
156 |
157 | f = open('%s/zipfile.uncompressed' % tmpdir.strpath).read()
158 | assert f == 'content'
159 |
160 | def test_bzip2(self, tmpdir):
161 |
162 | config_mock = mock.Mock()
163 |
164 | compressor = BZip2Compressor(config=config_mock, compression='bzip2')
165 |
166 | src = tmpdir.join('sourcefile')
167 | src.write('content')
168 |
169 | compressor.compress(src.strpath, '%s/bzipfile.bz2' % tmpdir.strpath)
170 | assert os.path.exists('%s/bzipfile.bz2' % tmpdir.strpath)
171 | compression_zip = identify_compression('%s/bzipfile.bz2' %
172 | tmpdir.strpath)
173 | assert compression_zip == "bzip2"
174 |
175 | compressor.decompress('%s/bzipfile.bz2' % tmpdir.strpath,
176 | '%s/bzipfile.uncompressed' % tmpdir.strpath)
177 |
178 | f = open('%s/bzipfile.uncompressed' % tmpdir.strpath).read()
179 | assert f == 'content'
180 |
181 |
182 | # noinspection PyMethodMayBeStatic
183 | class TestInternalCompressors(object):
184 |
185 | def test_gzip(self, tmpdir):
186 |
187 | config_mock = mock.Mock()
188 |
189 | compressor = PyGZipCompressor(config=config_mock, compression='pygzip')
190 |
191 | src = tmpdir.join('sourcefile')
192 | src.write('content')
193 |
194 | compressor.compress(src.strpath, '%s/zipfile.zip' % tmpdir.strpath)
195 | assert os.path.exists('%s/zipfile.zip' % tmpdir.strpath)
196 | compression_zip = identify_compression('%s/zipfile.zip' %
197 | tmpdir.strpath)
198 | assert compression_zip == "gzip"
199 |
200 | compressor.decompress('%s/zipfile.zip' % tmpdir.strpath,
201 | '%s/zipfile.uncompressed' % tmpdir.strpath)
202 |
203 | f = open('%s/zipfile.uncompressed' % tmpdir.strpath).read()
204 | assert f == 'content'
205 |
206 | def test_bzip2(self, tmpdir):
207 |
208 | config_mock = mock.Mock()
209 |
210 | compressor = PyBZip2Compressor(config=config_mock,
211 | compression='pybzip2')
212 |
213 | src = tmpdir.join('sourcefile')
214 | src.write('content')
215 |
216 | compressor.compress(src.strpath, '%s/bzipfile.bz2' % tmpdir.strpath)
217 | assert os.path.exists('%s/bzipfile.bz2' % tmpdir.strpath)
218 | compression_zip = identify_compression('%s/bzipfile.bz2' %
219 | tmpdir.strpath)
220 | assert compression_zip == "bzip2"
221 |
222 | compressor.decompress('%s/bzipfile.bz2' % tmpdir.strpath,
223 | '%s/bzipfile.uncompressed' % tmpdir.strpath)
224 |
225 | f = open('%s/bzipfile.uncompressed' % tmpdir.strpath).read()
226 | assert f == 'content'
227 |
228 |
229 | # noinspection PyMethodMayBeStatic
230 | class TestCustomCompressor(object):
231 | def test_custom_compressor_creation(self):
232 | config_mock = mock.Mock()
233 | config_mock.custom_compression_filter = 'dummy_compression_filter'
234 | config_mock.custom_decompression_filter = 'dummy_decompression_filter'
235 |
236 | compressor = CustomCompressor(config=config_mock,
237 | compression="custom")
238 |
239 | assert compressor is not None
240 | assert compressor._compress.cmd == (
241 | 'command(){ dummy_compression_filter > "$2" < "$1";}; command')
242 | assert compressor._decompress.cmd == (
243 | 'command(){ dummy_decompression_filter > "$2" < "$1";}; command')
244 |
245 | def test_validate(self):
246 | config_mock = mock.Mock()
247 | config_mock.custom_compression_filter = 'dummy_compression_filter'
248 | config_mock.custom_decompression_filter = 'dummy_decompression_filter'
249 |
250 | compressor = CustomCompressor(config=config_mock,
251 | compression="custom")
252 |
253 | validate = compressor.validate('custom')
254 |
255 | assert validate is None
256 |
--------------------------------------------------------------------------------
/tests/test_cli.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014-2016 2ndQuadrant Italia Srl
2 | #
3 | # This file is part of Barman.
4 | #
5 | # Barman is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Barman is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Barman. If not, see .
17 |
18 | import pytest
19 | from mock import Mock
20 |
21 | import barman.config
22 | from barman.cli import get_server, get_server_list, manage_server_command
23 | from barman.server import Server
24 | from testing_helpers import build_config_dictionary, build_config_from_dicts
25 |
26 |
27 | # noinspection PyMethodMayBeStatic
28 | class TestCli(object):
29 |
30 | def test_get_server(self, monkeypatch):
31 | """
32 | Test the get_server method, providing a basic configuration
33 |
34 | :param monkeypatch monkeypatch: pytest patcher
35 | """
36 | # Mock the args from argparse
37 | args = Mock()
38 | args.server_name = 'main'
39 | monkeypatch.setattr(barman, '__config__', build_config_from_dicts(
40 | main_conf={
41 | 'archiver': 'on',
42 | }))
43 | server_main = get_server(args)
44 | # Expect the server to exists
45 | assert server_main
46 | # Expect the name to be the right one
47 | assert server_main.config.name == 'main'
48 |
49 | def test_get_server_with_conflicts(self, monkeypatch, capsys):
50 | """
51 | Test get_server method using a configuration containing errors
52 |
53 | :param monkeypatch monkeypatch: pytest patcher
54 | """
55 | # Mock the args from argparse
56 | args = Mock()
57 | # conflicting directories
58 | monkeypatch.setattr(barman, '__config__', build_config_from_dicts(
59 | main_conf={
60 | 'wals_directory': '/some/barman/home/main/wals',
61 | 'basebackups_directory': '/some/barman/home/main/wals',
62 | 'archiver': 'on',
63 | }))
64 | args.server_name = 'main'
65 | with pytest.raises(SystemExit):
66 | get_server(args, True)
67 | out, err = capsys.readouterr()
68 | assert err
69 | assert "ERROR: Conflicting path:" in err
70 |
71 | # conflicting directories with on_error_stop=False
72 | monkeypatch.setattr(barman, '__config__', build_config_from_dicts(
73 | main_conf={
74 | 'wals_directory': '/some/barman/home/main/wals',
75 | 'basebackups_directory': '/some/barman/home/main/wals',
76 | 'archiver': 'on',
77 | }))
78 | args.server_name = 'main'
79 | get_server(args, on_error_stop=False)
80 | # In this case the server is returned and a warning message is emitted
81 | out, err = capsys.readouterr()
82 | assert err
83 | assert "ERROR: Conflicting path:" in err
84 |
85 | def test_manage_server_command(self, monkeypatch, capsys):
86 | """
87 | Test manage_server_command method checking
88 | the various types of error output
89 |
90 | :param monkeypatch monkeypatch: pytest patcher
91 | """
92 | # Build a server with a config with path conflicts
93 | monkeypatch.setattr(barman, '__config__', build_config_from_dicts(
94 | main_conf=build_config_dictionary({
95 | 'wals_directory': '/some/barman/home/main/wals',
96 | 'basebackups_directory': '/some/barman/home/main/wals',
97 | 'archiver': 'on',
98 | })))
99 | server = Server(barman.__config__.get_server('main'))
100 | # Test a not blocking WARNING message
101 | manage_server_command(server)
102 | out, err = capsys.readouterr()
103 | # Expect an ERROR message because of conflicting paths
104 | assert 'ERROR: Conflicting path' in err
105 |
106 | # Build a server with a config without path conflicts
107 | monkeypatch.setattr(barman, '__config__', build_config_from_dicts())
108 | server = Server(barman.__config__.get_server('main'))
109 | # Set the server as not active
110 | server.config.active = False
111 | # Request to treat inactive as errors
112 | to_be_executed = manage_server_command(server, inactive_is_error=True)
113 | out, err = capsys.readouterr()
114 | # Expect a ERROR message because of a not active server
115 | assert 'ERROR: Inactive server' in err
116 | assert not to_be_executed
117 |
118 | # Request to treat inactive as warning
119 | to_be_executed = manage_server_command(server, inactive_is_error=False)
120 | out, err = capsys.readouterr()
121 | # Expect no error whatsoever
122 | assert err == ''
123 | assert not to_be_executed
124 |
125 | def test_get_server_global_error_list(self, monkeypatch, capsys):
126 | """
127 | Test the management of multiple servers and the
128 | presence of global errors
129 |
130 | :param monkeypatch monkeypatch: pytest patcher
131 | """
132 | args = Mock()
133 | args.server_name = 'main'
134 | # Build 2 servers with shared path.
135 | monkeypatch.setattr(barman, '__config__', build_config_from_dicts(
136 | global_conf=None,
137 | main_conf={
138 | 'basebackups_directory': '/some/barman/home/main/base',
139 | 'incoming_wals_directory': '/some/barman/home/main/incoming',
140 | 'wals_directory': '/some/barman/home/main/wals',
141 | 'backup_directory': '/some/barman/home/main',
142 | 'archiver': 'on',
143 | },
144 | test_conf={
145 | 'basebackups_directory': '/some/barman/home/test/wals',
146 | 'incoming_wals_directory': '/some/barman/home/main/incoming',
147 | 'wals_directory': '/some/barman/home/main/wals',
148 | 'backup_directory': '/some/barman/home/main',
149 | 'archiver': 'on',
150 | }))
151 | # Expect a conflict because of the shared paths
152 | with pytest.raises(SystemExit):
153 | get_server(args)
154 | out, err = capsys.readouterr()
155 | # Check for the presence of error messages
156 | assert err
157 | # Check paths in error messages
158 | assert 'Conflicting path: ' \
159 | 'basebackups_directory=/some/barman/home/main/base' in err
160 | assert 'Conflicting path: ' \
161 | 'incoming_wals_directory=/some/barman/home/main/incoming' in err
162 | assert 'Conflicting path: ' \
163 | 'wals_directory=/some/barman/home/main/wals' in err
164 | assert 'Conflicting path: ' \
165 | 'backup_directory=/some/barman/home/main' in err
166 |
167 | def test_get_server_list(self, monkeypatch, capsys):
168 | """
169 | Test the get_server_list method
170 |
171 | :param monkeypatch monkeypatch: pytest patcher
172 | """
173 | monkeypatch.setattr(barman, '__config__', build_config_from_dicts())
174 | server_dict = get_server_list()
175 | assert server_dict
176 | # Expect 2 test servers Main and Test
177 | assert len(server_dict) == 2
178 | # Test the method with global errors
179 | monkeypatch.setattr(barman, '__config__', build_config_from_dicts(
180 | global_conf=None,
181 | main_conf={
182 | 'basebackups_directory': '/some/barman/home/main/base',
183 | 'incoming_wals_directory': '/some/barman/home/main/incoming',
184 | 'wals_directory': '/some/barman/home/main/wals',
185 | 'backup_directory': '/some/barman/home/main',
186 | 'archiver': 'on',
187 | },
188 | test_conf={
189 | 'basebackups_directory': '/some/barman/home/test/wals',
190 | 'incoming_wals_directory': '/some/barman/home/main/incoming',
191 | 'wals_directory': '/some/barman/home/main/wals',
192 | 'backup_directory': '/some/barman/home/main',
193 | 'archiver': 'on',
194 | }))
195 | # Expect the method to fail and exit
196 | with pytest.raises(SystemExit):
197 | get_server_list()
198 | out, err = capsys.readouterr()
199 | # Check for the presence of error messages
200 | assert err
201 | # Check paths in error messages
202 | assert 'Conflicting path: ' \
203 | 'basebackups_directory=/some/barman/home/main/base' in err
204 | assert 'Conflicting path: ' \
205 | 'incoming_wals_directory=/some/barman/home/main/incoming' in err
206 | assert 'Conflicting path: ' \
207 | 'wals_directory=/some/barman/home/main/wals' in err
208 | assert 'Conflicting path: ' \
209 | 'backup_directory=/some/barman/home/main' in err
210 |
211 | def test_get_server_list_global_error_continue(self, monkeypatch):
212 | """
213 | Test the population of the list of global errors for diagnostic
214 | purposes (diagnose invocation)
215 |
216 | :param monkeypatch monkeypatch: pytest patcher
217 | """
218 | monkeypatch.setattr(barman, '__config__', build_config_from_dicts(
219 | global_conf=None,
220 | main_conf={
221 | 'backup_directory': '/some/barman/home/main',
222 | 'archiver': 'on',
223 | },
224 | test_conf={
225 | 'backup_directory': '/some/barman/home/main',
226 | 'archiver': 'on',
227 | }))
228 | server_dict = get_server_list(on_error_stop=False)
229 | global_error_list = barman.__config__.servers_msg_list
230 | # Check for the presence of servers
231 | assert server_dict
232 | # Check for the presence of global errors
233 | assert global_error_list
234 | assert len(global_error_list) == 6
235 |
--------------------------------------------------------------------------------
/barman/lockfile.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2011-2016 2ndQuadrant Italia Srl
2 | #
3 | # This file is part of Barman.
4 | #
5 | # Barman is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # Barman is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Barman. If not, see .
17 |
18 | """
19 | This module is the lock manager for Barman
20 | """
21 |
22 | import errno
23 | import fcntl
24 | import os
25 | import re
26 |
27 | from barman.exceptions import (LockFileBusy, LockFileParsingError,
28 | LockFilePermissionDenied)
29 |
30 |
31 | class LockFile(object):
32 | """
33 | Ensures that there is only one process which is running against a
34 | specified LockFile.
35 | It supports the Context Manager interface, allowing the use in with
36 | statements.
37 |
38 | with LockFile('file.lock') as locked:
39 | if not locked:
40 | print "failed"
41 | else:
42 |
43 |
44 | You can also use exceptions on failures
45 |
46 | try:
47 | with LockFile('file.lock', True):
48 |
49 | except LockFileBusy, e, file:
50 | print "failed to lock %s" % file
51 |
52 | """
53 |
54 | LOCK_PATTERN = None
55 | """
56 | If defined in a subclass, it must be a compiled regular expression
57 | which matches the lock filename.
58 |
59 | It must provide named groups for the constructor parameters which produce
60 | the same lock name. I.e.:
61 |
62 | >>> ServerWalReceiveLock('/tmp', 'server-name').filename
63 | '/tmp/.server-name-receive-wal.lock'
64 | >>> ServerWalReceiveLock.LOCK_PATTERN = re.compile(
65 | r'\.(?P.+)-receive-wal\.lock')
66 | >>> m = ServerWalReceiveLock.LOCK_PATTERN.match(
67 | '.server-name-receive-wal.lock')
68 | >>> ServerWalReceiveLock('/tmp', **(m.groupdict())).filename
69 | '/tmp/.server-name-receive-wal.lock'
70 |
71 | """
72 |
73 | @classmethod
74 | def build_if_matches(cls, path):
75 | """
76 | Factory method that creates a lock instance if the path matches
77 | the lock filename created by the actual class
78 |
79 | :param path: the full path of a LockFile
80 | :return:
81 | """
82 | # If LOCK_PATTERN is not defined always return None
83 | if not cls.LOCK_PATTERN:
84 | return None
85 | # Matches the provided path against LOCK_PATTERN
86 | lock_directory = os.path.abspath(os.path.dirname(path))
87 | lock_name = os.path.basename(path)
88 | match = cls.LOCK_PATTERN.match(lock_name)
89 | if match:
90 | # Build the lock object for the provided path
91 | return cls(lock_directory, **(match.groupdict()))
92 | return None
93 |
94 | def __init__(self, filename, raise_if_fail=True, wait=False):
95 | self.filename = os.path.abspath(filename)
96 | self.fd = None
97 | self.raise_if_fail = raise_if_fail
98 | self.wait = wait
99 |
100 | def acquire(self, raise_if_fail=None, wait=None):
101 | """
102 | Creates and holds on to the lock file.
103 |
104 | When raise_if_fail, a LockFileBusy is raised if
105 | the lock is held by someone else and a LockFilePermissionDenied is
106 | raised when the user executing barman have insufficient rights for
107 | the creation of a LockFile.
108 |
109 | Returns True if lock has been successfully acquired, False otherwise.
110 |
111 | :param bool raise_if_fail: If True raise an exception on failure
112 | :param bool wait: If True issue a blocking request
113 | :returns bool: whether the lock has been acquired
114 | """
115 | if self.fd:
116 | return True
117 | fd = None
118 | # method arguments take precedence on class parameters
119 | raise_if_fail = raise_if_fail \
120 | if raise_if_fail is not None else self.raise_if_fail
121 | wait = wait if wait is not None else self.wait
122 | try:
123 | # 384 is 0600 in octal, 'rw-------'
124 | fd = os.open(self.filename, os.O_CREAT | os.O_RDWR, 384)
125 | flags = fcntl.LOCK_EX
126 | if not wait:
127 | flags |= fcntl.LOCK_NB
128 | fcntl.flock(fd, flags)
129 | # Once locked, replace the content of the file
130 | os.lseek(fd, 0, os.SEEK_SET)
131 | os.write(fd, ("%s\n" % os.getpid()).encode('ascii'))
132 | # Truncate the file at the current position
133 | os.ftruncate(fd, os.lseek(fd, 0, os.SEEK_CUR))
134 | self.fd = fd
135 | return True
136 | except (OSError, IOError) as e:
137 | if fd:
138 | os.close(fd) # let's not leak file descriptors
139 | if raise_if_fail:
140 | if e.errno in (errno.EAGAIN, errno.EWOULDBLOCK):
141 | raise LockFileBusy(self.filename)
142 | elif e.errno == errno.EACCES:
143 | raise LockFilePermissionDenied(self.filename)
144 | else:
145 | raise
146 | else:
147 | return False
148 |
149 | def release(self):
150 | """
151 | Releases the lock.
152 |
153 | If the lock is not held by the current process it does nothing.
154 | """
155 | if not self.fd:
156 | return
157 | try:
158 | fcntl.flock(self.fd, fcntl.LOCK_UN)
159 | os.close(self.fd)
160 | except (OSError, IOError):
161 | pass
162 | self.fd = None
163 |
164 | def __del__(self):
165 | """
166 | Avoid stale lock files.
167 | """
168 | self.release()
169 |
170 | # Contextmanager interface
171 |
172 | def __enter__(self):
173 | return self.acquire()
174 |
175 | def __exit__(self, exception_type, value, traceback):
176 | self.release()
177 |
178 | def get_owner_pid(self):
179 | """
180 | Test whether a lock is already held by a process.
181 |
182 | Returns the PID of the owner process or None if the lock is available.
183 |
184 | :rtype: int|None
185 | :raises LockFileParsingError: when the lock content is garbled
186 | :raises LockFilePermissionDenied: when the lockfile is not accessible
187 | """
188 | try:
189 | self.acquire(raise_if_fail=True, wait=False)
190 | except LockFileBusy:
191 | try:
192 | # Read the lock content and parse the PID
193 | # NOTE: We cannot read it in the self.acquire method to avoid
194 | # reading the previous locker PID
195 | with open(self.filename, 'r') as file_object:
196 | return int(file_object.readline().strip())
197 | except ValueError as e:
198 | # This should not happen
199 | raise LockFileParsingError(e)
200 | # release the lock and return None
201 | self.release()
202 | return None
203 |
204 |
205 | class GlobalCronLock(LockFile):
206 | """
207 | This lock protects cron from multiple executions.
208 |
209 | Creates a global '.cron.lock' lock file under the given lock_directory.
210 | """
211 |
212 | def __init__(self, lock_directory):
213 | super(GlobalCronLock, self).__init__(
214 | os.path.join(lock_directory, '.cron.lock'),
215 | raise_if_fail=True)
216 |
217 |
218 | class ServerBackupLock(LockFile):
219 | """
220 | This lock protects a server from multiple executions of backup command
221 |
222 | Creates a '.-backup.lock' lock file under the given lock_directory
223 | for the named SERVER.
224 | """
225 |
226 | def __init__(self, lock_directory, server_name):
227 | super(ServerBackupLock, self).__init__(
228 | os.path.join(lock_directory, '.%s-backup.lock' % server_name),
229 | raise_if_fail=True)
230 |
231 |
232 | class ServerCronLock(LockFile):
233 | """
234 | This lock protects a server from multiple executions of cron command
235 |
236 | Creates a '.-cron.lock' lock file under the given lock_directory
237 | for the named SERVER.
238 | """
239 |
240 | def __init__(self, lock_directory, server_name):
241 | super(ServerCronLock, self).__init__(
242 | os.path.join(lock_directory, '.%s-cron.lock' % server_name),
243 | raise_if_fail=True, wait=False)
244 |
245 |
246 | class ServerXLOGDBLock(LockFile):
247 | """
248 | This lock protects a server's xlogdb access
249 |
250 | Creates a '.-xlogdb.lock' lock file under the given lock_directory
251 | for the named SERVER.
252 | """
253 |
254 | def __init__(self, lock_directory, server_name):
255 | super(ServerXLOGDBLock, self).__init__(
256 | os.path.join(lock_directory, '.%s-xlogdb.lock' % server_name),
257 | raise_if_fail=True, wait=True)
258 |
259 |
260 | class ServerWalArchiveLock(LockFile):
261 | """
262 | This lock protects a server from multiple executions of wal-archive command
263 |
264 | Creates a '.-archive-wal.lock' lock file under
265 | the given lock_directory for the named SERVER.
266 | """
267 |
268 | def __init__(self, lock_directory, server_name):
269 | super(ServerWalArchiveLock, self).__init__(
270 | os.path.join(lock_directory, '.%s-archive-wal.lock' % server_name),
271 | raise_if_fail=True, wait=False)
272 |
273 |
274 | class ServerWalReceiveLock(LockFile):
275 | """
276 | This lock protects a server from multiple executions of receive-wal command
277 |
278 | Creates a '.-receive-wal.lock' lock file under
279 | the given lock_directory for the named SERVER.
280 | """
281 | # TODO: Implement on the other LockFile subclasses
282 | LOCK_PATTERN = re.compile(r'\.(?P.+)-receive-wal\.lock')
283 |
284 | def __init__(self, lock_directory, server_name):
285 | super(ServerWalReceiveLock, self).__init__(
286 | os.path.join(lock_directory, '.%s-receive-wal.lock' % server_name),
287 | raise_if_fail=True, wait=False)
288 |
--------------------------------------------------------------------------------