1
0
Fork 0
scripts-admin-quickndirty-p.../oldies/script_multi-instance-postgresql.sh

592 lines
23 KiB
Bash
Executable file

#!/bin/sh
# Ce script sert à créer ou détruire :
# - une instance PostgreSQL (PGDATA).
# Il peut également gérer un serveur esclave en définissant la
# variable $ESCLAVE . Dans ce cas là, mieux vaut avoir une authentification
# par clef (les opérations se font par ssh)
#
# Attention, ce script affiche les identifiants à l'écran.
# Prérequis :
# - PostgreSQL
# Si utilisation d'un esclave :
# - une authentification pour l'utilisateur root local vers root@$ESCLAVE par clef,
# - une authentification pour l'utilisateur postgres local vers postgres@$ESCLAVE par clef.
# Trucs à nettoyer (si quelque chose part en vrille, ou simplement
# pour désinstaller ):
# - TODO
# Version de PostgreSQL : 9.1 seule testée
VERSION_POSTGRESQL="9.1"
# Mettre ci-dessous le nom d'hôte ou l'IP du serveur esclave
# (utilisé par la config PG + les connexions SSH pour l'exécution
# des commandes distantes de ce script)
ESCLAVE=""
# idem pour le maître (vu depuis l'esclave en cas de réseau privé)
# (utilisé pour la config PG)
MAITRE=""
# Initialisation des variables globales
MODE_CREATION=0
MODE_DESTRUCTION=0
POSTGRESQL_REPLICATION_USER_NAME="repliquser"
POSTGRESQL_LOCALE="fr_FR.utf8"
POSTGRESQL_PORT=""
# Par défaut, on arrête le script à la première erreur non "catchée"
set -e
# On s'exécute dans un dossier accessible à l'utilisateur postgres
cd /tmp
# Fonctions
# affiche le message d'aide
usage() {
cat <<EOF
$0 -c cluster-name [ -e <hostname de l'esclave> -m <hostname du maître> ] [ -p <numéro de port> ]
$0 -d cluster-name [ -e <hostname de l'esclave> -m <hostname du maître> ]
$0 -h
-c xxx : création d'une instance/cluster nommée 'xxx'
-d xxx : destruction de l'instance nommée 'xxx'
-p nnn : numéro de port à affecter au nouveau cluster (par défaut, 'auto')
# Ce script peut générer la configuration nécessaire au streaming replication
-e esclave : nom d'hôte ou IP de l'esclave
-m maitre : nom d'hôte ou IP du serveur maître
-h : ce message d'aide
EOF
}
# Arguments
# $1 : IPv4, IPv6 ou nom d'hôte
# Cette fonction suffixe d'un /32 ou /128
# la chaîne si celle-ci est une adresse IP
add_mask_ip() {
test -n "$1" || exit 1
if [ $( echo "$1" | egrep -c "^([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}$" ) -gt 0 ]; then
printf "$1/32"
elif [ $( echo "$1" | egrep -c "^[[:xdigit:]:]*$" ) -gt 0 ]; then
printf "$1/128"
else
printf "$1"
fi
}
# Arguments
# $1 : IP esclave
# $2 : version PostgreSQL
# $3 : nom de l'instance
generate_patch_postgresqlconf_master() {
test -n "$1" && test -n "$2" && test -n "$3" || exit 1
cat <<EOF
@@ -56,6 +56,8 @@
# - Connection Settings -
+# Script MI PostgreSQL : écoute sur toutes les interfaces nécessaire pour la streaming replication
+listen_addresses = '*'
#listen_addresses = 'localhost' # what IP address(es) to listen on;
# comma-separated list of addresses;
# defaults to 'localhost', '*' = all
@@ -150,6 +152,8 @@ shared_buffers = 24MB # min 128kB
# - Settings -
+# Script MI PostgreSQL : serveur maître
+wal_level = hot_standby
#wal_level = minimal # minimal, archive, or hot_standby
# (change requires restart)
#fsync = on # turns forced synchronization on or off
@@ -178,9 +182,10 @@ shared_buffers = 24MB # min 128kB
# - Archiving -
-#archive_mode = off # allows archiving to be done
+# Script MI PostgreSQL : Serveur maître: activation de l'archivage et de l'envoi vers l'esclave
+archive_mode = on # allows archiving to be done
# (change requires restart)
-#archive_command = '' # command to use to archive a logfile segment
+archive_command = 'scp -q -B -C %p postgres@$1:/var/lib/postgresql/$2/$3/archives_from_master/%f' # command to use to archive a logfile segment
#archive_timeout = 0 # force a logfile segment switch after this
# number of seconds; 0 disables
@@ -193,10 +198,12 @@
# These settings are ignored on a standby server
+max_wal_senders = 3
#max_wal_senders = 0 # max number of walsender processes
# (change requires restart)
#wal_sender_delay = 1s # walsender cycle time, 1-10000 milliseconds
-#wal_keep_segments = 0 # in logfile segments, 16MB each; 0 disables
+# Script MI PostgreSQL : serveur maître: conservation des WAL
+wal_keep_segments = 32 # in logfile segments, 16MB each; 0 disables
#vacuum_defer_cleanup_age = 0 # number of xacts by which cleanup is delayed
#replication_timeout = 60s # in milliseconds; 0 disables
#synchronous_standby_names = '' # standby servers that provide sync rep
@@ -207,6 +213,9 @@ shared_buffers = 24MB # min 128kB
# These settings are ignored on a master server
+# Script MI PostgreSQL : mis en place sur le maître comme sur l'esclave, pour homogénéiser
+# comme il est ignoré sur le maître, ça ne pose pas de souci :)
+hot_standby = on
#hot_standby = off # "on" allows queries during recovery
# (change requires restart)
#max_standby_archive_delay = 30s # max delay before canceling queries
EOF
}
# Arguments
# $1 : nom de l'instance
generate_patch_postgresql_pghbaconf() {
test -n "$1" || exit 1
cat <<EOF
@@ -87,11 +87,11 @@ local all postgres peer
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
-local all all peer
+local $1 $1 md5
# IPv4 local connections:
-host all all 127.0.0.1/32 md5
+host $1 $1 127.0.0.1/32 md5
# IPv6 local connections:
-host all all ::1/128 md5
+host $1 $1 ::1/128 md5
# Allow replication connections from localhost, by a user with the
# replication privilege.
#local replication postgres peer
EOF
}
# Pas d'arguments
generate_patch_postgresqlconf_slave() {
cat <<EOF
@@ -56,6 +56,8 @@
# - Connection Settings -
+# Script MI PostgreSQL : écoute sur toutes les interfaces nécessaire pour la streaming replication
+listen_addresses = '*'
#listen_addresses = 'localhost' # what IP address(es) to listen on;
# comma-separated list of addresses;
# defaults to 'localhost', '*' = all
@@ -150,6 +152,8 @@ shared_buffers = 24MB # min 128kB
# - Settings -
+# Script MI PostgreSQL : serveur esclave
+wal_level = hot_standby
#wal_level = minimal # minimal, archive, or hot_standby
# (change requires restart)
#fsync = on # turns forced synchronization on or off
@@ -193,10 +198,12 @@
# These settings are ignored on a standby server
+max_wal_senders = 3
#max_wal_senders = 0 # max number of walsender processes
# (change requires restart)
#wal_sender_delay = 1s # walsender cycle time, 1-10000 milliseconds
-#wal_keep_segments = 0 # in logfile segments, 16MB each; 0 disables
+# Script MI PostgreSQL : serveur maître: conservation des WAL
+wal_keep_segments = 32 # in logfile segments, 16MB each; 0 disables
#vacuum_defer_cleanup_age = 0 # number of xacts by which cleanup is delayed
#replication_timeout = 60s # in milliseconds; 0 disables
#synchronous_standby_names = '' # standby servers that provide sync rep
@@ -207,6 +213,9 @@ shared_buffers = 24MB # min 128kB
# These settings are ignored on a master server
+# Script MI PostgreSQL : mis en place sur le maître comme sur l'esclave, pour homogénéiser
+# comme il est ignoré sur le maître, ça ne pose pas de souci :)
+hot_standby = on
#hot_standby = off # "on" allows queries during recovery
# (change requires restart)
#max_standby_archive_delay = 30s # max delay before canceling queries
EOF
}
# Arguments:
# $1 : IP maître
# $2 : port maître (idem esclave, en fait)
# $3 : utilisateur dédié à la réplication
# $4 : mot de passe dudit utilisateur
# $5 : version de PostgreSQL
# $6 : nom de l'instance
# $7 : chemin complet de pg_archivecleanup (si vide, désactivé)
generate_file_postgresqlrecoveryconf_slave() {
local ARCHIVE_CLEANUP_COMMAND
test -n "$1" && test -n "$2" && test -n "$3" && test -n "$4" && test -n "$5" && test -n "$6" || exit 1
if ! test -n "$7"; then
ARCHIVE_CLEANUP_COMMAND="#archive_cleanup_command = 'pg_archivecleanup /var/lib/postgresql/$5/$6/archives_from_master %r'"
else
ARCHIVE_CLEANUP_COMMAND="archive_cleanup_command = '$7 /var/lib/postgresql/$5/$6/archives_from_master %r'"
fi
cat <<EOF
# Note that recovery.conf must be in \$PGDATA directory.
# Specifies whether to start the server as a standby. In streaming replication,
# this parameter must be set to on.
standby_mode = 'on'
# Specifies a connection string which is used for the standby server to connect
# with the primary.
primary_conninfo = 'host=$1 port=$2 user=$3 password=$4'
# Specifies a trigger file whose presence should cause streaming replication to
# end (i.e., failover).
# Cf pg_ctlcluster promote pour une alternative
trigger_file = '/var/lib/postgresql/trigger-postgresql'
# Specifies a command to load archive segments from the WAL archive. If
# wal_keep_segments is a high enough number to retain the WAL segments
# required for the standby server, this may not be necessary. But
# a large workload can cause segments to be recycled before the standby
# is fully synchronized, requiring you to start again from a new base backup.
restore_command = 'cp /var/lib/postgresql/$5/$6/archives_from_master/%f "%p"'
# Specifies a command to clean up obsolete archive logs
$ARCHIVE_CLEANUP_COMMAND
EOF
}
# Arguments:
# $1 : Nom de la bdd / de l'utilisateur
# $2 : mot de passe de l'utilisateur
generate_script_postgresql_creation_db_et_user() {
local NOM_INSTANCE POSTGRESQL_PASSWORD
test -n "$1" && test -n "$2" || exit 1
NOM_INSTANCE="$1"
POSTGRESQL_PASSWORD="$2"
cat <<EOF
-- Création de l'utilisateur principal
CREATE USER "$NOM_INSTANCE" WITH PASSWORD '$POSTGRESQL_PASSWORD' CONNECTION LIMIT 50;
-- Restriction des privilèges par défaut
-- Cette partie du script vient en grande partie de :
-- http://wiki.postgresql.org/wiki/Shared_Database_Hosting
-- Connexion à template1
\c template1
-- Révocation sur la base template1
REVOKE ALL ON DATABASE template1 FROM public;
REVOKE ALL ON SCHEMA public FROM public;
GRANT ALL ON SCHEMA public TO postgres;
-- Ce passage-là est plus parano, mais à étudier avant suppression
REVOKE ALL ON pg_user FROM public;
REVOKE ALL ON pg_roles FROM public;
REVOKE ALL ON pg_group FROM public;
REVOKE ALL ON pg_authid FROM public;
REVOKE ALL ON pg_auth_members FROM public;
REVOKE ALL ON pg_database FROM public;
REVOKE ALL ON pg_tablespace FROM public;
REVOKE ALL ON pg_settings FROM public;
-- Création de la nouvelle base de données
CREATE DATABASE "$NOM_INSTANCE" WITH OWNER = "$NOM_INSTANCE" ENCODING = 'UTF8';
REVOKE ALL ON DATABASE "$NOM_INSTANCE" FROM public;
\c $NOM_INSTANCE
REVOKE ALL ON SCHEMA public FROM public;
GRANT ALL ON SCHEMA public TO "$NOM_INSTANCE";
EOF
}
# Arguments:
# $1 : nom de l'utilisateur dédié à la réplication
# $2 : mot de passe dudit utilisateur
generate_script_postgresql_creation_replication_user() {
test -n "$1" && test -n "$2" || exit 1
POSTGRESQL_REPLICATION_USER_NAME="$1"
POSTGRESQL_REPLICATION_PASSWORD="$2"
cat <<EOF
-- Création de l'utilisateur utilisé par l'esclave pour la streaming replication
CREATE USER $POSTGRESQL_REPLICATION_USER_NAME WITH PASSWORD '$POSTGRESQL_REPLICATION_PASSWORD' REPLICATION;
EOF
}
# Arguments
# none
log_alias() {
# Cette fonction est utilisée pour "capturer" les sorties des différentes
# commandes (hors messages générés par le script lui-même)
# Note : elle peut être modifiée pour envoyer les messages vers un fichier
# de log temporaire. Ça serait plus propre.
sed 's/^/ /'
}
fancylog() {
BEGINNING="$( printf "%s" "$1" | head -n 1 | sed -n "s/^\([A-Z]\+\):.*/\1/p" )"
if [ -n "$BEGINNING" ] && [ -t 1 ] && tput setaf 1 >/dev/null 2>&1; then
case "$BEGINNING" in
"ERREUR"|"ERROR")
tput setaf 1;;
"WARN"|"WARNING")
tput setaf 3;;
"INFO"|"DEBUG")
tput setaf 2;;
esac
printf "%s" "$BEGINNING"
tput op
printf "%s\n" "$( printf "%s" "$1" | sed '1 s/^[A-Z]\+:/:/' )"
else
printf "%s\n" "$1"
fi
}
# Début du code
# gestion des options de lancement
while getopts c:d:e:m:p:h f; do
case $f in
'c')
MODE_CREATION=1
NOM_INSTANCE="$OPTARG"
;;
'd')
MODE_DESTRUCTION=1
NOM_INSTANCE="$OPTARG"
;;
'e')
ESCLAVE="$OPTARG"
;;
'm')
MAITRE="$OPTARG"
;;
'p')
if [ "$OPTARG" = "auto" ]; then
unset POSTGRESQL_PORT
else
POSTGRESQL_PORT="$( printf "%d" "$OPTARG" )"
fi
;;
'h')
usage
exit 0
;;
\?)
usage >&2
exit 1
;;
esac
done
#(code inutile, mais que je garde parce qu'on ne sait jamais)
#shift $( expr $OPTIND - 1 )
#DATA="$1"
if [ -n "$MAITRE" ] && [ -n "$ESCLAVE" ]; then
MAITRE_WITH_MASK=$( add_mask_ip "$MAITRE" )
ESCLAVE_WITH_MASK=$( add_mask_ip "$ESCLAVE" )
fi
# Petite vérif.
case $(( $MODE_CREATION + $MODE_DESTRUCTION )) in
'0')
fancylog "ERREUR: veuillez choisir entre création et destruction." >&2
usage >&2
exit 1
;;
'2')
fancylog "ERREUR: tu veux créer et détruire en même temps, petit malin ?" >&2
exit 1
;;
esac
# Petites vérifications préliminaires :
fancylog "INFO: petites vérifications préliminaires..."
# - vérifications sur le nom du clustername fourni
OLD_LC_ALL="$LC_ALL"
export LC_ALL=C
export LANG=C
if [ $( printf "$NOM_INSTANCE" | egrep -c "^[a-z][a-z0-9_]{0,14}$" ) -ne 1 ]; then
fancylog "ERREUR: clustername vide ou contenant des caractères interdits : regexp : [a-z][a-z0-9_]{0,14}" >&2
exit 1
fi
export LC_ALL="$OLD_LC_ALL"
export LANG="$OLD_LC_ALL"
# - est-ce que l'auth. SSH par clef fonctionne pour root et postgres ?
if [ -n "$ESCLAVE" ]; then
# - vérification de l'auth. par clefs SSH
if ! ssh -o BatchMode=yes root@$ESCLAVE /bin/true; then
fancylog "ERREUR: auth. par clef SSH non configurée pour l'utilisateur 'root'."
exit 1
fi
if ! su -c "ssh -o BatchMode=yes postgres@$ESCLAVE /bin/true" postgres; then
fancylog "ERREUR: auth. par clef SSH non configurée pour l'utilisateur 'postgres'."
exit 1
fi
# - vérification de la présence de $MAITRE
if [ ! -n "$MAITRE" ]; then
fancylog "ERREUR: serveur esclave indiqué, mais pas de serveur maître (option -m)." >&2
exit 1
fi
fi
# - est-ce qu'on est bien sur une Debian 6 ou 7
# (c'est surtout pour éviter les mauvaises surprises, ce script n'ayant pas été testé ailleurs)
if [ ! -f "/etc/debian_version" ] || [ $( egrep -c "^(6.|7.)" /etc/debian_version ) -ne 1 ]; then
fancylog "ERREUR: mauvaise version de Debian détectée. Arrêt par prudence. Vérifiez le code de ce script avant de forcer." >&2
exit 1
fi
if [ -n "$ESCLAVE" ] && [ "$( ssh root@$ESCLAVE 'egrep -c "^(6.|7.)" /etc/debian_version' )" -ne 1 ]; then
fancylog "ERREUR: ESCLAVE: mauvaise version de Debian détectée. Arrêt par prudence. Vérifiez le code de ce script avant de forcer." >&2
exit 1
fi
# - est-ce que la version attendue de PostgreSQL est bien installée ?
if ! dpkg -s "postgresql-$VERSION_POSTGRESQL" >/dev/null 2>&1; then
fancylog "ERREUR: PostgreSQL $VERSION_POSTGRESQL ne semble pas installée." >&2
exit 1
fi
if [ -n "$ESCLAVE" ] && ! ssh root@$ESCLAVE dpkg -s "postgresql-$VERSION_POSTGRESQL" >/dev/null 2>&1; then
fancylog "ERREUR: PostgreSQL $VERSION_POSTGRESQL ne semble pas installée." >&2
exit 1
fi
# Fin des vérifications
fancylog "INFO: fin des vérifications. Lancement des opérations."
if [ "$MODE_CREATION" -eq 1 ]; then
POSTGRESQL_PASSWORD=$( dd if=/dev/random 2>/dev/null bs=1 count=10 status=noxfer | base64 | sed 's#[/=]##g' )
POSTGRESQL_REPLICATION_PASSWORD=$( dd if=/dev/random 2>/dev/null bs=1 count=20 status=noxfer | base64 | sed 's#[/=]##g' )
# Création de l'instance dédiée
fancylog "INFO: création du cluster PG primaire..."
if [ -z "$POSTGRESQL_PORT" ]; then
pg_createcluster --locale=$POSTGRESQL_LOCALE --start-conf=auto "$VERSION_POSTGRESQL" "$NOM_INSTANCE"
# Détermination du port généré
# TODO: récupérer ça via pg_lsclusters serait plus "propre"
POSTGRESQL_PORT=$( grep "^port" /etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/postgresql.conf | sed 's/^port[[:space:]]*=[[:space:]]*\([0-9]\+\).*$/\1/' )
else
pg_createcluster --locale=$POSTGRESQL_LOCALE --start-conf=auto --port "$POSTGRESQL_PORT" "$VERSION_POSTGRESQL" "$NOM_INSTANCE"
fi
fancylog "INFO: modification du pg_hba.conf..."
if ! generate_patch_postgresql_pghbaconf "$NOM_INSTANCE" | patch -s --dry-run /etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/pg_hba.conf; then
fancylog "ERREUR: modification du fichier pg_hba.conf en échec. Arrêt."
exit 1
fi
generate_patch_postgresql_pghbaconf "$NOM_INSTANCE" | patch -s /etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/pg_hba.conf
fancylog "INFO: démarrage de l'instance PostgreSQL..."
pg_ctlcluster "$VERSION_POSTGRESQL" "$NOM_INSTANCE" start
# Lancement du script fourre-tout
fancylog "INFO: création de l'utilisateur et de la base de données, et affinage des droits d'accès..."
generate_script_postgresql_creation_db_et_user "$NOM_INSTANCE" "$POSTGRESQL_PASSWORD" "$POSTGRESQL_REPLICATION_USER_NAME" "$POSTGRESQL_REPLICATION_PASSWORD" | su -c "psql -p $POSTGRESQL_PORT -v ON_ERROR_STOP=1" postgres
if [ -n "$ESCLAVE" ]; then
fancylog "INFO: création de l'utilisateur de réplication..."
generate_script_postgresql_creation_replication_user "$POSTGRESQL_REPLICATION_USER_NAME" "$POSTGRESQL_REPLICATION_PASSWORD" | su -c "psql -p $POSTGRESQL_PORT -v ON_ERROR_STOP=1" postgres
# configuration en tant que maître
fancylog "INFO: modification de la configuration BDD de l'instance primaire..."
if ! generate_patch_postgresqlconf_master "$ESCLAVE" "$VERSION_POSTGRESQL" "$NOM_INSTANCE" | patch -s --dry-run /etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/postgresql.conf; then
fancylog "ERREUR: modification du fichier postgresql.conf en échec. Arrêt."
exit 1
fi
generate_patch_postgresqlconf_master "$ESCLAVE" "$VERSION_POSTGRESQL" "$NOM_INSTANCE" | patch -s /etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/postgresql.conf
# On rajoute les lignes pour la connexion streaming replication dans le pg_hba.conf
echo "host replication $POSTGRESQL_REPLICATION_USER_NAME $ESCLAVE_WITH_MASK md5" >>/etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/pg_hba.conf
echo "host replication $POSTGRESQL_REPLICATION_USER_NAME $MAITRE_WITH_MASK md5" >>/etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/pg_hba.conf
# Création sur l'esclave
# Note: on commence par créer l'arborescence de l'esclave pour
# avoir le répertoire de destination des archives logs
# le plus tôt possible (en tout cas, avant le pg_stop_backup()
# qui envoie forcément un WAL)
fancylog "INFO: création du cluster PG secondaire..."
ssh "root@$ESCLAVE" "cd /tmp; pg_createcluster --locale='$POSTGRESQL_LOCALE' -p '$POSTGRESQL_PORT' --start-conf=auto '$VERSION_POSTGRESQL' '$NOM_INSTANCE'"
fancylog "INFO: création du dossier de réception des archives logs et arret du backup..."
su -c "mkdir '/var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/archives_from_master'" postgres
su -c "ssh postgres@$ESCLAVE mkdir '/var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/archives_from_master'" postgres
fancylog "INFO: redémarrage du serveur primaire..."
pg_ctlcluster "$VERSION_POSTGRESQL" "$NOM_INSTANCE" restart
# rsync du PGDATA vers l'esclave
fancylog "INFO: écrasement du PGDATA secondaire par celui de l'instance primaire..."
echo "SELECT pg_start_backup('script_mi_pg', true);" | su -c "psql -p $POSTGRESQL_PORT -v ON_ERROR_STOP=1" postgres
# on attend un peu, il y a parfois des fichiers WAL qui "vanished" pendant le rsync
sleep 1
# On exclut :
# - postmaster.pid : raison évidente :)
# - postmaster.opts : a priori, le contenu est identique mais par prudence...
# - server.key/server.crt : rsync génère une erreur sur la date de modification des symlinks :-/
# - recovery.* : le recovery.done du maitre référence l'esclave, et vice versa pour le recovery.conf de l'esclave
# - archives_from_master : cela écraserait tout éventuel WAL déjà envoyé
# - lost+found : au cas où la partition existe déjà (pg_createcluster se bloque mais ça permet de récupérer cette ligne de commande ailleurs :)
# A étudier : pas de --delete ?
# test -c car problème de synchro bizarre
su -c "rsync -aHc --exclude=/postmaster.pid --exclude=/postmaster.opts --exclude=/server.key --exclude=/server.crt --exclude=/recovery.conf --exclude=/recovery.done --exclude=/archives_from_master --exclude=lost+found /var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/ postgres@$ESCLAVE:/var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/" postgres
echo "SELECT pg_stop_backup();" | su -c "psql -p $POSTGRESQL_PORT -v ON_ERROR_STOP=1" postgres
# configuration de l'esclave
fancylog "INFO: configuration de l'instance PG secondaire..."
if ! ssh root@$ESCLAVE dpkg -s "postgresql-contrib-$VERSION_POSTGRESQL" >/dev/null 2>&1; then
fancylog "WARNING: Le paquet postgresql-contrib-$VERSION_POSTGRESQL ne semble pas installé sur le serveur esclave, archive_cleanup_command sera désactivé." >&2
fancylog "NOTICE: cf fichier /var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/recovery.conf en cas d'installation après-coup." >&2
ARCHIVE_CLEANUP_COMMAND=""
else
# TODO: à rendre plus portable ?
ARCHIVE_CLEANUP_COMMAND="/usr/lib/postgresql/$VERSION_POSTGRESQL/bin/pg_archivecleanup"
fi
generate_file_postgresqlrecoveryconf_slave "$MAITRE" "$POSTGRESQL_PORT" "$POSTGRESQL_REPLICATION_USER_NAME" "$POSTGRESQL_REPLICATION_PASSWORD" "$VERSION_POSTGRESQL" "$NOM_INSTANCE" "$ARCHIVE_CLEANUP_COMMAND" | su -c "ssh postgres@$ESCLAVE 'cat - >/var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/recovery.conf'" postgres
generate_file_postgresqlrecoveryconf_slave "$ESCLAVE" "$POSTGRESQL_PORT" "$POSTGRESQL_REPLICATION_USER_NAME" "$POSTGRESQL_REPLICATION_PASSWORD" "$VERSION_POSTGRESQL" "$NOM_INSTANCE" "$ARCHIVE_CLEANUP_COMMAND" | su -c "cat - >/var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/recovery.done" postgres
generate_patch_postgresqlconf_slave | ssh "root@$ESCLAVE" patch -s /etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/postgresql.conf
# (note: même fichier pg_hba.conf pour tout le monde, homogénéisation avec peu de risques il me semble)
scp -q /etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/pg_hba.conf root@$ESCLAVE:/etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/pg_hba.conf
# démarrage des instances maître et esclave
fancylog "INFO: démarrage de l'instance PostgreSQL esclave..."
ssh root@$ESCLAVE pg_ctlcluster "$VERSION_POSTGRESQL" "$NOM_INSTANCE" start
# Vérification de la réplication
# TODO (via numéro de transaction (requête) ? processus/connexion ?)
fi
# Fin
fancylog "INFO: Création terminée. Instance PostgreSQL allumée."
fancylog "INFO: pour mémo :"
fancylog "INFO: BDD: $NOM_INSTANCE, port: $POSTGRESQL_PORT, login: $NOM_INSTANCE, mdp: $POSTGRESQL_PASSWORD"
TMP="$MAITRE"
if [ -z "$MAITRE" ]; then
TMP="localhost"
fi
fancylog "INFO: pgpass: $TMP:$POSTGRESQL_PORT:$NOM_INSTANCE:$NOM_INSTANCE:$POSTGRESQL_PASSWORD"
fi
if [ "$MODE_DESTRUCTION" -eq 1 ]; then
fancylog "INFO: suppression de l'instance locale..."
# Note : en guise de garde-fou, on ne met pas l'option --stop
pg_dropcluster "$VERSION_POSTGRESQL" "$NOM_INSTANCE"
if [ -n "$ESCLAVE" ]; then
fancylog "INFO: suppression de l'instance esclave..."
ssh root@$ESCLAVE pg_dropcluster "$VERSION_POSTGRESQL" "$NOM_INSTANCE"
fi
fi