Merge pull request #23 from pgexperts/93compat

93compat
This commit is contained in:
Alexander Kukushkin
2015-09-04 08:14:13 +02:00
5 changed files with 30 additions and 23 deletions
+3 -2
View File
@@ -67,6 +67,7 @@ For an example file, see `postgres0.yml`. Below is an explanation of settings:
* *connect_address*: ip address + port through which Postgres is accessible from other nodes and applications.
* *data_dir*: file path to initialize and store Postgres data files
* *maximum_lag_on_failover*: the maximum bytes a follower may lag before it is not eligible become leader
* *use_slots*: whether or not to use replication_slots. Must be False for PostgreSQL 9.3, and you should comment out max_replication_slots.
* *pg_hba*: list of lines which should be added to pg_hba.conf
* *- host all all 0.0.0.0/0 md5*
* *replication*
@@ -84,8 +85,8 @@ For an example file, see `postgres0.yml`. Below is an explanation of settings:
* *admin*:
* *username*: admin username, user will be created during initialization. It would have CREATEDB and CREATEROLE privileges
* *password*: admin password, user will be created during initialization.
* *recovery_conf*: configuration settings written to recovery.conf when configuring follower
* *parameters*: list of configuration settings for Postgres
* *recovery_conf*: additional configuration settings written to recovery.conf when configuring follower
* *parameters*: list of configuration settings for Postgres. Many of these are required for replication to work.
## Replication choices
+24 -21
View File
@@ -50,6 +50,7 @@ class Postgresql:
self.superuser = config['superuser']
self.admin = config['admin']
self.callback = config.get('callbacks', {})
self.use_slots = config.get('use_slots',True)
self.recovery_conf = os.path.join(self.data_dir, 'recovery.conf')
self.configuration_to_save = (os.path.join(self.data_dir, 'pg_hba.conf'),
os.path.join(self.data_dir, 'postgresql.conf'))
@@ -255,9 +256,9 @@ class Postgresql:
member_conn = psycopg2.connect(**r)
member_conn.autocommit = True
member_cursor = member_conn.cursor()
member_cursor.execute(
"SELECT pg_is_in_recovery(), %s - (pg_last_xlog_replay_location() - '0/0000000'::pg_lsn)",
(self.xlog_position(), ))
member_cursor.execute("""SELECT pg_is_in_recovery(),
%s - pg_xlog_location_diff(pg_last_xlog_replay_location(),'0/00000')""",
(self.xlog_position(), ))
row = member_cursor.fetchone()
member_cursor.close()
member_conn.close()
@@ -305,10 +306,9 @@ class Postgresql:
recovery_target_timeline = 'latest'
""")
if leader and leader.conn_url:
f.write("""
primary_slot_name = '{}'
primary_conninfo = '{}'
""".format(self.name, self.primary_conninfo(leader.conn_url)))
f.write("""primary_conninfo = '{}'\n""".format(self.primary_conninfo(leader.conn_url)))
if self.use_slots:
f.write("""primary_slot_name = '{}'\n""".format(self.name))
for name, value in self.config.get('recovery_conf', {}).items():
f.write("{} = '{}'\n".format(name, value))
@@ -362,25 +362,28 @@ primary_conninfo = '{}'
def xlog_position(self):
return self.query("""SELECT CASE WHEN pg_is_in_recovery()
THEN pg_last_xlog_replay_location() - '0/0000000'::pg_lsn
ELSE pg_current_xlog_location() - '0/00000'::pg_lsn END""").fetchone()[0]
THEN pg_xlog_location_diff(pg_last_xlog_replay_location(),'0/0000000')
ELSE pg_xlog_location_diff(pg_current_xlog_location(),'0/00000') END""").fetchone()[0]
def load_replication_slots(self):
cursor = self.query("SELECT slot_name FROM pg_replication_slots WHERE slot_type='physical'")
self.members = [r[0] for r in cursor]
if self.use_slots:
cursor = self.query("SELECT slot_name FROM pg_replication_slots WHERE slot_type='physical'")
self.members = [r[0] for r in cursor]
def sync_replication_slots(self, members):
# drop unused slots
for slot in set(self.members) - set(members):
self.query("""SELECT pg_drop_replication_slot(%s)
WHERE EXISTS(SELECT 1 FROM pg_replication_slots
WHERE slot_name = %s)""", slot, slot)
if self.use_slots:
# drop unused slots
for slot in set(self.members) - set(members):
self.query("""SELECT pg_drop_replication_slot(%s)
WHERE EXISTS(SELECT 1 FROM pg_replication_slots
WHERE slot_name = %s)""", slot, slot)
# create new slots
for slot in set(members) - set(self.members):
self.query("""SELECT pg_create_physical_replication_slot(%s)
WHERE NOT EXISTS (SELECT 1 FROM pg_replication_slots
WHERE slot_name = %s)""", slot, slot)
# create new slots
for slot in set(members) - set(self.members):
self.query("""SELECT pg_create_physical_replication_slot(%s)
WHERE NOT EXISTS (SELECT 1 FROM pg_replication_slots
WHERE slot_name = %s)""", slot, slot)
self.members = members
def create_replication_slots(self, cluster):
+1
View File
@@ -30,6 +30,7 @@ postgresql:
connect_address: 127.0.0.1:5432
data_dir: data/postgresql0
maximum_lag_on_failover: 1048576 # 1 megabyte in bytes
use_slots: True
pg_hba:
- host all all 0.0.0.0/0 md5
- hostssl all all 0.0.0.0/0 md5
+1
View File
@@ -30,6 +30,7 @@ postgresql:
connect_address: 127.0.0.1:5433
data_dir: data/postgresql1
maximum_lag_on_failover: 1048576 # 1 megabyte in bytes
use_slots: True
pg_hba:
- host all all 0.0.0.0/0 md5
- hostssl all all 0.0.0.0/0 md5
+1
View File
@@ -111,6 +111,7 @@ class TestPostgresql(unittest.TestCase):
'pg_hba': ['hostssl all all 0.0.0.0/0 md5', 'host all all 0.0.0.0/0 md5'],
'superuser': {'password': ''},
'admin': {'username': 'admin', 'password': 'admin'},
'use_slots' : True,
'replication': {'username': 'replicator',
'password': 'rep-pass',
'network': '127.0.0.1/32'},