no need to change node id when doing failover for pgpool
[pgpool-online-recovery] / streaming-replication.sh
1 #!/bin/bash -e
2
3 ##This is meanst to be run on the slave, with the masters ip as the passed variable. ($1)
4 sourcehost="$1"
5 datadir=/var/lib/pgsql/9.6/data
6 archivedir=/var/lib/pgsql/9.6/archive
7 archivedirdest=/var/lib/pgsql/9.6/archive
8
9 cd # if used as root with sudo -u postgres home dir won't be readable and we will get errors
10
11 #Usage
12 if [ "$1" = "" ] || [ "$1" = "-h" ] || [ "$1" = "-help" ] || [ "$1" = "--help" ];
13 then
14         echo "Usage: $0 masters ip address"
15 exit 0
16 fi
17 #This script must be run as postgres user
18 Whoami () {
19     if [[ $(whoami) != "postgres" ]]
20     then
21         echo "[INFO] This script must be run as postgres user !"
22         exit 1
23     fi
24 }
25
26 #Check if postgres server is running on remote host
27 CheckIfPostgresIsRunningOnRemoteHost () {
28         is_active=$(systemctl --host $1 is-active postgresql-9.6)
29
30         if [ "$is_active" == "active" ]
31         then
32                 echo "[OK] Postgres master running on remote host";
33         else
34                 echo "[ERROR] Postgres not running on the master. Exiting..";
35         exit 1
36         fi
37 }
38
39 #Check if the supposed master is actually a master
40 CheckIfMasterIsActuallyAMaster () {
41     ismaster="$(ssh postgres@"$1" 'if [ -f /var/lib/pgsql/9.6/data/recovery.done ]; then echo "postgres_is_a_master_instance"; else echo "postgres_is_not_master"; fi;')"
42
43     if [[ "$ismaster" = "postgres_is_not_master" ]]
44     then
45         echo "[ERROR] Postgres is already running as a slave. Exiting..";
46         exit 1
47     elif [[ "$ismaster" = "postgres_is_a_master_instance" ]]
48     then
49         echo "[INFO] Postgres is running as master (probably)";
50     elif echo "[ERROR] Unexpected response. Exiting.."
51     then
52         exit 1
53     fi
54 }
55
56 #prepare local server to become the new slave server.
57 PrepareLocalServer () {
58
59     if [ -f '/tmp/trigger_file' ]
60     then
61             rm /tmp/trigger_file
62     fi
63     echo "[INFO] Stopping slave node.."
64     #/usr/pgsql-9.6/bin/pg_ctl -D /var/lib/pgsql/9.6/data/ stop
65         sudo systemctl stop postgresql-9.6
66
67     if [[ -f "$datadir/recovery.done" ]];
68     then
69             mv "$datadir"/recovery.done "$datadir"/recovery.conf
70     fi 
71
72     #Remove old WAL logs
73     rm -f /var/lib/pgsql/9.6/archive/*
74 }
75
76
77 CheckForRecoveryConfig () {
78     if [[ -f "$datadir/recovery.conf" ]];
79     then
80         echo "[OK] Slave config file found, Continuing.."
81     else
82         echo "[ERROR] recovery.conf not found. Postgres is not a slave. Exiting.."
83         exit 1
84     fi
85 }
86
87
88 #Put master into backup mode
89 #Before doing PutMasterIntoBackupMode clean up archive logs (IE rm or mv /var/lib/pgsql/9.6/archive/*). They are not needed since we are effectivly createing a new base backup and then synching it.
90 PutMasterIntoBackupMode () {
91     echo "[INFO] Putting postgres master '$1' in backup mode."
92     ssh postgres@"$1" "rm -f /var/lib/pgsql/9.6/archive/*"
93     ssh postgres@"$1" "psql -c \"SELECT pg_start_backup('Streaming Replication', true)\" postgres"
94 }
95
96 #rsync master's data to local postgres dir
97 RsyncWhileLive () {
98     echo "[INFO] Transfering data from master '$1' ..."
99     rsync -C -av --delete --progress -e ssh --exclude server.key --exclude server.crt --exclude recovery.conf --exclude recovery.done --exclude postmaster.pid --exclude pg_xlog/ "$1":"$datadir"/ "$datadir"/ > /dev/null
100     if [ $? == 0 ]
101     then
102         echo "[OK] Transfert completed.";
103                 ln -sf $datadir/postgresql.conf.slave $datadir/postgresql.conf
104     else
105         echo "[ERROR] Error during transfer !";
106         exit 0;
107     fi
108 }
109
110
111 #This archives the WAL log (ends writing to it and moves it to the $archive dir
112 StopBackupModeAndArchiveIntoWallLog () {
113     echo "[INFO] Disable backup mode from master '$1'."
114     ssh postgres@"$1" "psql -c \"SELECT pg_stop_backup()\" postgres"
115     echo "[INFO] Synchronising master/slave archive directory..."
116     rsync -C -a --progress -e ssh "$1":"$archivedir"/ "$archivedirdest"/ > /dev/null
117     if [ $? == 0 ]
118     then
119         echo "[OK] Sync achieved.";
120     else
121         echo "[ERROR] Error during sync !";
122         exit 0;
123     fi
124 }
125
126 #stop postgres and copy transactions made during the last two rsync's
127 StopPostgreSqlAndFinishRsync () {
128     echo "[INFO] Stopping master node.."
129     ssh postgres@"$1" "sudo systemctl stop postgresql-9.6"
130     echo "[INFO] Transfering xlog files from master... "
131     rsync -av --delete --progress -e ssh "$sourcehost":"$datadir"/pg_xlog/ "$datadir"/pg_xlog/ > /dev/null
132     if [ $? == 0 ]
133     then
134         echo "[OK] Transfert completed.";
135     else
136         echo "[ERROR] Error during transfer !";
137         exit 0;
138     fi
139 }
140
141 #Start both Master and Slave
142 StartLocalAndThenRemotePostGreSql () {
143     echo "[INFO] Starting slave node.."
144         sudo systemctl start postgresql-9.6
145     if ! systemctl -q is-active postgresql-9.6 ; then echo '[ERROR] Slave not running !'; else echo "[OK] Slave started."; fi;
146
147
148     echo "[INFO] Starting master node.."
149     ssh postgres@"$1" "sudo systemctl start postgresql-9.6"
150     
151     status=$(systemctl --host $1 is-active postgresql-9.6)
152     if [ $status != "active" ]
153     then
154         echo "[ERROR] Master not running !";
155         exit 0;
156     else
157         echo "[OK] Master started.";
158     fi
159
160         echo -n "[INFO] Wating for replication to start "
161         while [ "`psql -c 'SELECT * from pg_stat_replication' -h $1 -t postgres postgres | wc -l`" -lt 2 ] ; do
162                 echo -n .
163                 sleep 1
164         done
165         echo "OK"
166
167 }
168
169 #Execute above operations
170 Whoami
171 CheckIfPostgresIsRunningOnRemoteHost "$1"
172 CheckIfMasterIsActuallyAMaster "$1"
173 PrepareLocalServer "$datadir"
174 CheckForRecoveryConfig "$datadir"
175 PutMasterIntoBackupMode "$1"
176 RsyncWhileLive "$1"
177 StopBackupModeAndArchiveIntoWallLog "$1" "$archivedir" "$archivedirdest"
178 StopPostgreSqlAndFinishRsync "$1"
179 StartLocalAndThenRemotePostGreSql "$1"