aboutsummaryrefslogtreecommitdiff
path: root/handlers/pgsql.in
blob: fc337a033f023898107666f97e0dd13dafe4f4ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
# vim: set filetype=sh sw=3 sts=3 expandtab autoindent:
#
# PostgreSQL handler script for backupninja
#

getconf backupdir /var/backups/postgres
getconf databases all
getconf compress yes
getconf vsname
# format maps to pg_dump --format= option, old/default was plain
getconf format plain

localhost=`hostname`

# Decide if the handler should operate on a vserver or on the host.
# In the former case, check that $vsname exists and is running.
usevserver=no
vroot=''
if [ $vservers_are_available = yes ]; then
   if [ -n "$vsname" ]; then
      # does it exist ?
      if ! vservers_exist "$vsname" ; then
         fatal "The vserver given in vsname ($vsname) does not exist."
      fi
      # is it running ?
      vservers_running $vsname || fatal "The vserver $vsname is not running."
      # everything ok
      info "Using vserver '$vsname'."
      usevserver=yes
      vroot="$VROOTDIR/$vsname"
   else
      info "No vserver name specified, actions will be performed on the host."
   fi
fi

# Make sure that the system to backup has the needed executables
if [ $usevserver = yes ]; then
   debug "Examining vserver '$vsname'."
   if [ "$databases" == "all" ] && [ "$format" = "plain" ]; then
      [ -x "$vroot`$VSERVER $vsname exec which $PGSQLDUMPALL`" ] || \
         fatal "Can't find $PGSQLDUMPALL in vserver $vsname."
   elif [ "$format" != "plain" ]; then
      [ -x "$vroot`$VSERVER $vsname exec which $PGSQLDUMPALL`" ] || \
         fatal "Can't find $PGSQLDUMPALL in vserver $vsname."
      [ -x "$vroot`$VSERVER $vsname exec which $PGSQLDUMP`" ] || \
         fatal "Can't find $PGSQLDUMP in vserver $vsname."
      [ -x "$vroot`$VSERVER $vsname exec which $PSQL`" ] || \
         fatal "Can't find $PSQL in vserver $vsname."
   else
      [ -x "$vroot`$VSERVER $vsname exec which $PGSQLDUMP`" ] || \
         fatal "Can't find $PGSQLDUMP in vserver $vsname."
   fi
else
   if [ "$databases" == "all" ] && [ "$format" = "plain" ]; then
      [ -x "`which $PGSQLDUMPALL`" ] || \
         fatal "Can't find $PGSQLDUMPALL."
   elif [ "$format" != "plain" ]; then
      [ -x "`which $PGSQLDUMPALL`" ] || \
         fatal "Can't find $PGSQLDUMPALL."
      [ -x "`which $PGSQLDUMP`" ] || \
         fatal "Can't find $PGSQLDUMP."
      [ -x "`which $PSQL`" ] || \
         fatal "Can't find $PSQL."
   else
      [ -x "`which $PGSQLDUMP`" ] || \
         fatal "Can't find $PGSQLDUMP."
   fi
fi

# create backup dir, the vroot variable will be empty if no vsname was specified
# and will proceed to operate on the host
[ -d $vroot$backupdir ] || (debug "mkdir -p $vroot$backupdir"; mkdir -p $vroot$backupdir)
[ -d $vroot$backupdir ] || fatal "Backup directory '$vroot$backupdir' does not exist, and could not be created."

# give backup dir the good uid and permissions
# (in respect to the vserver, if $usevserver = yes)
if [ $usevserver = yes ]; then
   pguid=`$VSERVER $vsname exec getent passwd $PGSQLUSER | @AWK@ -F: '{print $3}'`
else
   pguid=`getent passwd $PGSQLUSER | @AWK@ -F: '{print $3}'`
fi
[ -n "$pguid" ] || \
   fatal "No user called $PGSQLUSER`[ $usevserver = no ] || echo \" on vserver $vsname\"`."
debug "chown $pguid $vroot$backupdir"
chown $pguid $vroot$backupdir
debug "chmod 700 $vroot$backupdir"
chmod 700 $vroot$backupdir


# If we are using the custom (best) or tar pg_dump format, and
# dumping "all" databases, we will substitute "all" for a list
# of all non-template databases to avoid the use of pg_dumpall.
dumpglobals="no"
if [ "$databases" = "all" ] && [ "$format" != "plain" ]; then
   cmdprefix=""
   if [ "$usevserver" = "yes" ]; then
      	cmdprefix="$VSERVER $vsname exec "
   fi
   execstr="${cmdprefix} su - $PGSQLUSER -c 'psql -AtU $PGSQLUSER -c \"SELECT datname FROM pg_database WHERE NOT datistemplate\"'"
   debug execstr
   dblist=""
   for db in $(eval $execstr 2>&1); do
      dblist="$dblist $db"
   done
   if [ "$dblist" != "" ]; then
      databases="$dblist"
   fi
   # Dump globals (pg_dumpall -g) for roles and tablespaces
   dumpglobals="yes"
fi


# if $databases = all, use pg_dumpall
if [ "$databases" == "all" ]; then
   if [ $usevserver = yes ]; then
      if [ "$compress" == "yes" ]; then
         execstr="$VSERVER $vsname exec su - $PGSQLUSER -s /bin/bash -c \"set -o pipefail ; $PGSQLDUMPALL | $GZIP $GZIP_OPTS > '$backupdir/${vsname}.sql.gz'\""
      else
         execstr="$VSERVER $vsname exec su - $PGSQLUSER -c \"$PGSQLDUMPALL > '$backupdir/${vsname}.sql'\""
      fi
   else
      if [ "$compress" == "yes" ]; then
         execstr="su - $PGSQLUSER -s /bin/bash -c \"set -o pipefail ; $PGSQLDUMPALL | $GZIP $GZIP_OPTS > '$backupdir/${localhost}-all.sql.gz'\""
      else
         execstr="su - $PGSQLUSER -c \"$PGSQLDUMPALL > '$backupdir/${localhost}-all.sql'\""
      fi
   fi
   debug "$execstr"
   if [ ! $test ]; then
      output=`eval $execstr 2>&1`
      code=$?
      if [ "$code" == "0" ]; then
         debug $output
         info "Successfully finished dump of pgsql cluster"
      else
         warning $output
         warning "Failed to dump pgsql cluster"
      fi
   fi

# else use pg_dump on each specified database
else
   # If we're not doing plain format, database=all may now be database=list
   # so we track the database=all selection in dumpglobals which tells us
   # to also dump the roles and tablespaces via pg_dumpall -g
   if [ "$dumpglobals" = "yes" ]; then
      globalscmd=""
      if [ "$compress" == "yes" ]; then
         globalscmd="set -o pipefail ; $PGSQLDUMPALL -g | $GZIP $GZIP_OPTS > '$backupdir/globals.sql.gz'"
      else
         globalscmd="$PGSQLDUMPALL -g > '$backupdir/globals.sql'"
      fi
      if [ $usevserver = yes ]; then
         execstr="$VSERVER $vsname exec su - $PGSQLUSER -s /bin/bash -c \"$globalscmd\""
      else
         execstr="su - $PGSQLUSER -s /bin/bash -c \"$globalscmd\""
      fi
      debug "$execstr"
      if [ ! $test ]; then
         output=`eval $execstr 2>&1`
         code=$?
         if [ "$code" == "0" ]; then
            debug $output
            info "Successfully finished pgsql globals (roles and tablespaces) dump"
         else
            warning $output
            warning "Failed to dump pgsql globals (roles and tablespaces)"
         fi
      fi
   fi
   for db in $databases; do
      dumpext="sql"
      if [ "$format" != "plain" ]; then
         dumpext="pg_dump"
      fi
      # To better support the backupninja global GZIP and rsync-friendly GZIP_OPTS
      # the custom archive format is told to disable compression. The plain format
      # is uncompressed by default and the tar format doesn't support pg_dump compression.
      disablecustomcompress=""
      if [ "$format" = "custom" ]; then
         disablecustomcompress="--compress=0"
      fi
      dumpcmd=""
      globalscmd=""
      if [ "$compress" == "yes" ]; then
         dumpcmd="set -o pipefail ; $PGSQLDUMP --format=$format ${disablecustomcompress} $db | $GZIP $GZIP_OPTS > '$backupdir/${db}.${dumpext}.gz'"
      else
         dumpcmd="$PGSQLDUMP --format=$format ${disablecustomcompress} $db > '$backupdir/${db}.${dumpext}'"
      fi
      if [ $usevserver = yes ]; then
         execstr="$VSERVER $vsname exec su - $PGSQLUSER -s /bin/bash -c \"$dumpcmd\""
      else
         execstr="su - $PGSQLUSER -s /bin/bash -c \"$dumpcmd\""
      fi
      debug "$execstr"
      if [ ! $test ]; then
         output=`eval $execstr 2>&1`
         code=$?
         if [ "$code" == "0" ]; then
            debug $output
            info "Successfully finished dump of pgsql database ${db}"
         else
            warning $output
            warning "Failed to dump pgsql database ${db}"
         fi
      fi
   done
fi

return 0