39c1fb9c2729819b5d80f86873d910f0f808917c
[matthijs/upstream/backupninja-vserver.git] / handlers / mysql.in
1 # -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
2 #
3 # mysql handler script for backupninja
4 #
5
6 getconf backupdir /var/backups/mysql
7 getconf databases all
8 getconf ignores
9 getconf nodata
10 getconf dbhost localhost
11 getconf hotcopy no
12 getconf sqldump no
13 getconf sqldumpoptions "--lock-tables --complete-insert --add-drop-table --quick --quote-names"
14 getconf compress yes
15 getconf vsname
16
17 # authentication:
18 getconf user
19 getconf dbusername
20 getconf dbpassword
21 getconf configfile /etc/mysql/debian.cnf
22
23
24 # Decide if the handler should operate on a vserver or on the host.
25 # In the former case, check that $vsname exists and is running.
26 local usevserver=no
27 local vroot
28 if [ $vservers_are_available = yes ]; then
29    if [ -n "$vsname" ]; then
30       # does it exist ?
31       if ! vservers_exist "$vsname" ; then
32          fatal "The vserver given in vsname ($vsname) does not exist."
33       fi
34       # is it running ?
35       vservers_running $vsname || fatal "The vserver $vsname is not running."
36       # everything ok
37       info "Using vserver '$vsname'."
38       usevserver=yes
39       vroot="$VROOTDIR/$vsname"
40    else
41       info "No vserver name specified, actions will be performed on the host."
42    fi
43 else
44    [ -z "$vsname" ] || warning 'vservers support disabled in backupninja.conf, vsname configuration line will be ignored'
45 fi
46
47 ## Prepare ignore part of the command
48 ## This only works for mysqldump at the moment
49
50 ignore=''
51 for i in $ignores $nodata; do
52        ignore="$ignore --ignore-table=$i"
53 done
54         
55 # create backup dirs, $vroot will be empty if no vsname was specified
56 # and we will instead proceed to operate on the host
57 [ -d $vroot$backupdir ] || mkdir -p $vroot$backupdir
58 [ -d $vroot$backupdir ] || fatal "Backup directory '$vroot$backupdir'"
59 hotdir="$backupdir/hotcopy"
60 dumpdir="$backupdir/sqldump"
61
62 if [ $usevserver = yes ]
63 then
64         [ "$sqldump" == "no" -o -d $vroot$dumpdir ] || $VSERVER $vsname exec mkdir -p $dumpdir
65         [ "$hotcopy" == "no" -o -d $vroot$hotdir ] || $VSERVER $vsname exec mkdir -p $hotdir
66 else
67         [ "$sqldump" == "no" -o -d $dumpdir ] || mkdir -p $dumpdir
68         [ "$hotcopy" == "no" -o -d $hotdir ] || mkdir -p $hotdir
69 fi
70
71 #######################################################################
72 ## AUTHENTICATION
73
74 #
75 # one of three authentication methods:
76 # 1. setting the user, so that /home/user/.my.cnf is used.
77 # 2. specifying the user and password in the handler config,
78 #    which generates a temporary .my.cnf in /root/.my.cnf
79 # 3. specify the config file with --defaults-extra-file
80 #    (this option DOESN'T WORK WITH MYSQLHOTCOPY)
81 #
82
83 # create .my.cnf
84 # only if dbusername and dbpassword specified.
85 # we create a tmp file because we don't want to
86 # specify the password on the command line.
87
88 defaultsfile=""
89
90 if [ "$dbusername" != "" -a "$dbpassword" != "" ]
91 then
92     if [ $usevserver = yes ]
93     then
94         vhome=`$VSERVER $vsname exec getent passwd "root" | @AWK@ -F: '{print $6}'`
95         home="$vroot$vhome"
96     else
97         home=`getent passwd "root" | @AWK@ -F: '{print $6}'`
98     fi
99
100     [ -d $home ] || fatal "Can't find root's home directory ($home)."
101     
102     mycnf="$home/.my.cnf"
103     
104     if [ -f $mycnf ]
105     then
106         # rename temporarily
107         tmpcnf="$home/my.cnf.disable"
108         debug "mv $mycnf $tmpcnf"
109         mv $mycnf $tmpcnf
110     fi
111     
112     oldmask=`umask`
113     umask 077
114     cat > $mycnf <<EOF
115 # auto generated backupninja mysql conf
116 [mysql]
117 host=$dbhost
118 user=$dbusername
119 password="$dbpassword"
120
121 [mysqldump]
122 host=$dbhost
123 user=$dbusername
124 password="$dbpassword"
125
126 [mysqlhotcopy]
127 host=$dbhost
128 user=$dbusername
129 password="$dbpassword"
130 EOF
131         umask $oldmask
132         if [ $usevserver = yes ] 
133         then
134             defaultsfile="--defaults-extra-file=$vhome/.my.cnf"
135         else
136             defaultsfile="--defaults-extra-file=$mycnf"
137         fi
138 fi
139
140 # if a user is not set, use $configfile, otherwise use $mycnf
141 if [ "$user" == "" ]; then
142         user=root;
143         defaultsfile="--defaults-extra-file=$configfile"
144 else
145         userset=true;
146         if [ $usevserver = yes ]
147         then
148             vuserhome=`$VSERVER $vsname exec getent passwd "$user" | @AWK@ -F: '{print $6}'`
149             if [ $? -eq 2 ]
150             then
151                 fatal "User $user not found in /etc/passwd"
152             fi
153             userhome="$vroot$vuserhome"
154         else
155             userhome=`getent passwd "$user" | @AWK@ -F: '{print $6}'`
156             if [ $? -eq 2 ]
157             then
158                 fatal "User $user not found in /etc/passwd"
159             fi
160         fi
161         
162         debug "User home set to: $userhome"
163         [ -f $userhome/.my.cnf ] || fatal "Can't find config file in $userhome/.my.cnf"
164         if [ $usevserver = yes ]; then
165             defaultsfile="--defaults-extra-file=$vuserhome/.my.cnf"
166         else
167             defaultsfile="--defaults-extra-file=$userhome/.my.cnf"
168         fi
169         debug "using $defaultsfile"
170 fi
171
172 #######################################################################
173 ## HOT COPY
174
175 if [ "$hotcopy" == "yes" ]
176 then
177     info "Initializing hotcopy method"
178     if [ "$databases" == "all" ]
179     then
180         if [ $usevserver = yes ]
181         then
182                 info "dbhost: $dbhost"
183                 execstr="$VSERVER $vsname exec $MYSQLHOTCOPY -h $dbhost --quiet --allowold --regexp /.\*/./.\*/ $hotdir"
184         else
185                 execstr="$MYSQLHOTCOPY -h $dbhost --quiet --allowold --regexp /.\*/./.\*/ $hotdir"
186         fi
187         debug "su $user -c \"$execstr\""
188         if [ ! $test ]
189         then
190                 output=`su $user -c "$execstr" 2>&1`
191                 code=$?
192                 if [ "$code" == "0" ]
193                 then
194                         debug $output
195                         info "Successfully finished hotcopy of all mysql databases"
196                 else
197                         warning $output
198                         warning "Failed to hotcopy all mysql databases"
199                 fi
200         fi
201     else        
202         for db in $databases
203         do
204                 if [ $usevserver = yes ]
205                 then
206                         execstr="$VSERVER $vsname exec $MYSQLHOTCOPY -h $dbhost --allowold $db $hotdir"
207                 else
208                         execstr="$MYSQLHOTCOPY -h $dbhost --allowold $db $hotdir"
209                 fi
210                 debug 'su $user -c \"$execstr\"'
211                 if [ ! $test ]
212                 then
213                         output=`su $user -c "$execstr" 2>&1`
214                         code=$?
215                         if [ "$code" == "0" ]
216                         then
217                                 debug $output
218                                 info "Successfully finished hotcopy of mysql database $db"
219                         else
220                                 warning $output
221                                 warning "Failed to hotcopy mysql database $db"
222                         fi
223                 fi
224         done
225      fi
226 fi
227
228 ##########################################################################
229 ## SQL DUMP
230
231 if [ "$sqldump" == "yes" ]
232 then
233     info "Initializing SQL dump method"
234     if [ "$databases" == "all" ]
235     then
236         if [ $usevserver = yes ]
237         then
238             debug 'echo show databases | $VSERVER $vsname exec su $user -c \"$MYSQL $defaultsfile\" | grep -v Database'
239             databases=`echo 'show databases' | $VSERVER $vsname exec su $user -c "$MYSQL $defaultsfile" | grep -v Database`
240             if [ $? -ne 0 ]
241             then
242                 fatal "Authentication problem, maybe user/password is wrong or mysqld is not running?"
243             fi
244         else
245                 databases=$(su $user -c "$MYSQL $defaultsfile -N -B -e 'show databases'" | sed 's/|//g;/\+----/d')
246                 if [ $? -ne 0 ]
247                 then
248                     fatal "Authentication problem, maybe user/password is wrong or mysqld is not running?"
249                 fi
250         fi
251     fi
252
253         for db in $databases
254         do
255            DUMP_BASE="$MYSQLDUMP $defaultsfile $sqldumpoptions"
256
257            # Dumping structure and data
258            DUMP="$DUMP_BASE $ignore $db"
259
260            # If requested, dump only the table structure for this database
261            if echo "$nodata" | grep -E '(^|[[:space:]])'"$db\." >/dev/null
262            then
263               # Get the structure of the tables, without data
264               DUMP_STRUCT="$DUMP_BASE --no-data $db"
265               for qualified_table in $nodata
266               do
267                  table=$( expr match "$qualified_table" "$db\.\([^\w]*\)" )
268                  DUMP_STRUCT="$DUMP_STRUCT $table"
269               done
270               DUMP="( $DUMP; $DUMP_STRUCT )"
271            fi
272                 if [ $usevserver = yes ]
273                 then
274                    # Test to make sure mysqld is running, if it is not sqldump will not work
275                    $VSERVER $vsname exec su $user -c "$MYSQLADMIN $defaultsfile ping"
276                    if [ $? -ne 0 ]; then
277                       fatal "Either you have an authentication problem, or mysqld doesn't appear to be running!"
278                    fi
279                    if [ "$compress" == "yes" ]; then
280                       execstr="$VSERVER $vsname exec $DUMP | $GZIP > $vroot$dumpdir/${db}.sql.gz"
281                    else
282                       execstr="$VSERVER $vsname exec $DUMP -r $vroot$dumpdir/${db}.sql"
283                    fi
284                 else
285                    # Test to make sure mysqld is running, if it is not sqldump will not work
286                    su $user -c "$MYSQLADMIN $defaultsfile ping"
287                    if [ $? -ne 0 ]; then
288                       fatal "Either you have an authentication problem, or mysqld doesn't appear to be running!"
289                    fi
290                    if [ "$compress" == "yes" ]; then
291                       execstr="$DUMP | $GZIP > $dumpdir/${db}.sql.gz"
292                    else
293                       execstr="$DUMP -r $dumpdir/${db}.sql"
294                    fi
295                 fi
296                 debug "su $user -c \"$execstr\""
297                 if [ ! $test ]
298                 then
299                         output=`su $user -c "$execstr" 2>&1`
300                         code=$?
301                         if [ "$code" == "0" ]
302                         then
303                                 debug $output
304                                 info "Successfully finished dump of mysql database $db"
305                         else
306                                 warning $output
307                                 warning "Failed to dump mysql databases $db"
308                         fi
309                 fi
310         done
311 fi
312
313 # clean up tmp config file
314 if [ "$dbusername" != "" -a "$dbpassword" != "" ]
315 then
316         ## clean up tmp config file
317         debug "rm $mycnf"
318         rm $mycnf
319         if [ -f "$tmpcnf" ]
320         then
321                 debug "mv $tmpcnf $mycnf"
322                 mv $tmpcnf $mycnf
323         fi
324 fi
325
326 return 0