mirror of
https://github.com/outbackdingo/patroni.git
synced 2026-08-25 14:53:37 +00:00
Enable configuration of PostgreSQL binary locations. (#263)
Adds a bin_dir parameter to PostgreSQL settings that will be prefixed to all command invocations.
This commit is contained in:
committed by
Alexander Kukushkin
parent
fa7aa71092
commit
494887f47e
@@ -38,6 +38,7 @@ PostgreSQL
|
||||
- **PATRONI\_POSTGRESQL\_LISTEN**: IP address + port that Postgres listens to. Multiple comma-separated addresses are permitted, as long as the port component is appended after to the last one with a colon, i.e. ``listen: 127.0.0.1,127.0.0.2:5432``. Patroni will use the first address from this list to establish local connections to the PostgreSQL node.
|
||||
- **PATRONI\_POSTGRESQL\_CONNECT\_ADDRESS**: IP address + port through which Postgres is accessible from other nodes and applications.
|
||||
- **PATRONI\_POSTGRESQL\_DATA\_DIR**: The location of the Postgres data directory, either existing or to be initialized by Patroni.
|
||||
- **PATRONI\_POSTGRESQL\_BIN_DIR**: Path to PostgreSQL binaries. (pg_ctl, pg_rewind, pg_basebackup, postgres) The default value is an empty string meaning that PATH environment variable will be used to find the executables.
|
||||
- **PATRONI\_POSTGRESQL\_PGPASS**: path to the `.pgpass <https://www.postgresql.org/docs/current/static/libpq-pgpass.html>`__ password file. Patroni creates this file before executing pg\_basebackup and under some other circumstances. The location must be writable by Patroni.
|
||||
- **PATRONI\_REPLICATION\_USERNAME**: replication username; the user will be created during initialization. Replicas will use this user to access master via streaming replication
|
||||
- **PATRONI\_REPLICATION\_PASSWORD**: replication password; the user will be created during initialization.
|
||||
|
||||
@@ -65,6 +65,7 @@ PostgreSQL
|
||||
- **connect\_address**: IP address + port through which Postgres is accessible from other nodes and applications.
|
||||
- **create\_replica\_methods**: an ordered list of the create methods for turning a Patroni node into a new replica. "basebackup" is the default method; other methods are assumed to refer to scripts, each of which is configured as its own config item.
|
||||
- **data\_dir**: The location of the Postgres data directory, either existing or to be initialized by Patroni.
|
||||
- **bin\_dir**: Path to PostgreSQL binaries. (pg_ctl, pg_rewind, pg_basebackup, postgres) The default value is an empty string meaning that PATH environment variable will be used to find the executables.
|
||||
- **listen**: IP address + port that Postgres listens to; must be accessible from other nodes in the cluster, if you're using streaming replication. Multiple comma-separated addresses are permitted, as long as the port component is appended after to the last one with a colon, i.e. ``listen: 127.0.0.1,127.0.0.2:5432``. Patroni will use the first address from this list to establish local connections to the PostgreSQL node.
|
||||
- **pgpass**: path to the `.pgpass <https://www.postgresql.org/docs/current/static/libpq-pgpass.html>`__ password file. Patroni creates this file before executing pg\_basebackup and under some other circumstances. The location must be writable by Patroni.
|
||||
- **recovery\_conf**: additional configuration settings written to recovery.conf when configuring follower.
|
||||
|
||||
+2
-1
@@ -42,6 +42,7 @@ class Config(object):
|
||||
'ttl': 30, 'loop_wait': 10, 'retry_timeout': 10,
|
||||
'maximum_lag_on_failover': 1048576,
|
||||
'postgresql': {
|
||||
'bin_dir': '',
|
||||
'use_slots': True,
|
||||
'parameters': {p: v[0] for p, v in Postgresql.CMDLINE_OPTIONS.items()}
|
||||
}
|
||||
@@ -193,7 +194,7 @@ class Config(object):
|
||||
ret[section][param] = value
|
||||
|
||||
_set_section_values('restapi', ['listen', 'connect_address', 'certfile', 'keyfile'])
|
||||
_set_section_values('postgresql', ['listen', 'connect_address', 'data_dir', 'pgpass'])
|
||||
_set_section_values('postgresql', ['listen', 'connect_address', 'data_dir', 'pgpass', 'bin_dir'])
|
||||
|
||||
def _get_auth(name):
|
||||
ret = {}
|
||||
|
||||
+14
-6
@@ -58,6 +58,7 @@ class Postgresql(object):
|
||||
self.config = config
|
||||
self.name = config['name']
|
||||
self.scope = config['scope']
|
||||
self._bin_dir = config.get('bin_dir') or ''
|
||||
self._database = config.get('database', 'postgres')
|
||||
self._data_dir = config['data_dir']
|
||||
self._pending_restart = False
|
||||
@@ -132,12 +133,16 @@ class Postgresql(object):
|
||||
self.connection_string = 'postgres://{0}/{1}'.format(
|
||||
self._connect_address or self._local_address['host'] + ':' + self._local_address['port'], self._database)
|
||||
|
||||
def _pgcommand(self, cmd):
|
||||
"""Returns path to the specified PostgreSQL command"""
|
||||
return os.path.join(self._bin_dir, cmd)
|
||||
|
||||
def pg_ctl(self, cmd, *args, **kwargs):
|
||||
"""Builds and executes pg_ctl command
|
||||
|
||||
:returns: `!True` when return_code == 0, otherwise `!False`"""
|
||||
|
||||
pg_ctl = ['pg_ctl', cmd]
|
||||
pg_ctl = [self._pgcommand('pg_ctl'), cmd]
|
||||
if cmd in ('start', 'stop', 'restart'):
|
||||
pg_ctl += ['-w']
|
||||
timeout = self.config.get('pg_ctl_timeout')
|
||||
@@ -222,7 +227,7 @@ class Postgresql(object):
|
||||
if not (self.config.get('use_pg_rewind') and all(self._superuser.get(n) for n in ('username', 'password'))):
|
||||
return False
|
||||
|
||||
cmd = ['pg_rewind', '--help']
|
||||
cmd = [self._pgcommand('pg_rewind'), '--help']
|
||||
try:
|
||||
ret = subprocess.call(cmd, stdout=open(os.devnull, 'w'), stderr=subprocess.STDOUT)
|
||||
if ret != 0: # pg_rewind is not there, close up the shop and go home
|
||||
@@ -657,7 +662,10 @@ class Postgresql(object):
|
||||
dsn = 'user={user} host={host} port={port} dbname={database} sslmode=prefer sslcompression=1'.format(**r)
|
||||
logger.info('running pg_rewind from %s', dsn)
|
||||
try:
|
||||
return subprocess.call(['pg_rewind', '-D', self._data_dir, '--source-server', dsn], env=env) == 0
|
||||
return subprocess.call([self._pgcommand('pg_rewind'),
|
||||
'-D', self._data_dir,
|
||||
'--source-server', dsn,
|
||||
], env=env) == 0
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
@@ -667,7 +675,7 @@ class Postgresql(object):
|
||||
# Don't try to call pg_controldata during backup restore
|
||||
if self._version_file_exists() and self.state != 'creating replica':
|
||||
try:
|
||||
data = subprocess.check_output(['pg_controldata', self._data_dir])
|
||||
data = subprocess.check_output([self._pgcommand('pg_controldata'), self._data_dir])
|
||||
if data:
|
||||
data = data.decode('utf-8').splitlines()
|
||||
result = {l.split(':')[0].replace('Current ', '', 1): l.split(':')[1].strip() for l in data if l}
|
||||
@@ -693,7 +701,7 @@ class Postgresql(object):
|
||||
|
||||
def single_user_mode(self, command=None, options=None):
|
||||
""" run a given command in a single-user mode. If the command is empty - then just start and stop """
|
||||
cmd = ['postgres', '--single', '-D', self._data_dir]
|
||||
cmd = [self._pgcommand('postgres'), '--single', '-D', self._data_dir]
|
||||
for opt, val in sorted((options or {}).items()):
|
||||
cmd.extend(['-c', '{0}={1}'.format(opt, val)])
|
||||
# need a database name to connect
|
||||
@@ -965,7 +973,7 @@ $$""".format(name, ' '.join(options)), name, password, password)
|
||||
ret = 1
|
||||
for bbfailures in range(0, maxfailures):
|
||||
try:
|
||||
ret = subprocess.call(['pg_basebackup', '--pgdata=' + self._data_dir,
|
||||
ret = subprocess.call([self._pgcommand('pg_basebackup'), '--pgdata=' + self._data_dir,
|
||||
'--xlog-method=stream', "--dbname=" + conn_url], env=env)
|
||||
if ret == 0:
|
||||
break
|
||||
|
||||
@@ -58,6 +58,7 @@ postgresql:
|
||||
listen: 127.0.0.1:5432
|
||||
connect_address: 127.0.0.1:5432
|
||||
data_dir: data/postgresql0
|
||||
# bin_dir:
|
||||
pgpass: /tmp/pgpass0
|
||||
authentication:
|
||||
replication:
|
||||
|
||||
Reference in New Issue
Block a user