fixes for mysql handler for mysqld inside a vserver
[matthijs/upstream/backupninja.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 compress yes
14 getconf vsname
15
16 # authentication:
17 getconf user
18 getconf dbusername
19 getconf dbpassword
20 getconf configfile /etc/mysql/debian.cnf
21
22
23 # Decide if the handler should operate on a vserver or on the host.
24 # In the former case, check that $vsname exists and is running.
25 local usevserver=no
26 local vroot
27 if [ $vservers_are_available = yes ]; then
28    if [ -n "$vsname" ]; then
29       # does it exist ?
30       if ! vservers_exist "$vsname" ; then
31          fatal "The vserver given in vsname ($vsname) does not exist."
32       fi
33       # is it running ?
34       vservers_running $vsname || fatal "The vserver $vsname is not running."
35       # everything ok
36       info "Using vserver '$vsname'."
37       usevserver=yes
38       vroot="$VROOTDIR/$vsname"
39    else
40       info "No vserver name specified, actions will be performed on the host."
41    fi
42 fi
43
44 ## Prepare ignore part of the command
45 ## This only works for mysqldump at the moment
46
47 ignore=''
48 for i in $ignores $nodata; do
49        ignore="$ignore --ignore-table=$i"
50 done
51         
52 # create backup dirs, $vroot will be empty if no vsname was specified
53 # and we will instead proceed to operate on the host
54 [ -d $vroot$backupdir ] || mkdir -p $vroot$backupdir
55 [ -d $vroot$backupdir ] || fatal "Backup directory '$vroot$backupdir'"
56 hotdir="$backupdir/hotcopy"
57 dumpdir="$backupdir/sqldump"
58
59 if [ $usevserver = yes ]
60 then
61         [ "$sqldump" == "no" -o -d $vroot$dumpdir ] || $VSERVER $vsname exec mkdir -p $dumpdir
62         [ "$hotcopy" == "no" -o -d $vroot$hotdir ] || $VSERVER $vsname exec mkdir -p $hotdir
63 else
64         [ "$sqldump" == "no" -o -d $dumpdir ] || mkdir -p $dumpdir
65         [ "$hotcopy" == "no" -o -d $hotdir ] || mkdir -p $hotdir
66 fi
67
68 #######################################################################
69 ## AUTHENTICATION
70
71 #
72 # one of three authentication methods:
73 # 1. setting the user, so that /home/user/.my.cnf is used.
74 # 2. specifying the user and password in the handler config,
75 #    which generates a temporary .my.cnf in /root/.my.cnf
76 # 3. specify the config file with --defaults-extra-file
77 #    (this option DOESN'T WORK WITH MYSQLHOTCOPY)
78 #
79
80 # create .my.cnf
81 # only if dbusername and dbpassword specified.
82 # we create a tmp file because we don't want to
83 # specify the password on the command line.
84
85 defaultsfile=""
86
87 if [ "$dbusername" != "" -a "$dbpassword" != "" ]
88 then
89     if [ $usevserver = yes ]
90     then
91         home=`$VSERVER $vsname exec getent passwd "root" | @AWK@ -F: '{print $6}'`
92     else
93         home=`getent passwd "root" | @AWK@ -F: '{print $6}'`
94     fi
95
96     [ -d $home ] || fatal "Can't find root's home directory ($home)."
97     
98     mycnf="$home/.my.cnf"
99
100     if [ $usevserver = yes ]
101     then
102       workcnf="$vroot$mycnf"
103     else
104       workcnf="$mycnf"
105     fi
106
107     if [ -f $workcnf ]
108     then
109       # rename temporarily
110       tmpcnf="$workcnf.disable"
111       debug "mv $workcnf $tmpcnf"
112       mv $workcnf $tmpcnf
113     fi
114     
115     oldmask=`umask`
116     umask 077
117     cat > $workcnf <<EOF
118 # auto generated backupninja mysql conf
119 [mysql]
120 host=$dbhost
121 user=$dbusername
122 password="$dbpassword"
123
124 [mysqldump]
125 host=$dbhost
126 user=$dbusername
127 password="$dbpassword"
128
129 [mysqlhotcopy]
130 host=$dbhost
131 user=$dbusername
132 password="$dbpassword"
133
134 [mysqladmin]
135 host=$dbhost
136 user=$dbusername
137 password="$dbpassword"
138 EOF
139         umask $oldmask
140         defaultsfile="--defaults-extra-file=$mycnf"
141 fi
142
143 # if a user is not set, use $configfile, otherwise use $mycnf
144 if [ "$user" == "" ]; then
145         user=root;
146         defaultsfile="--defaults-extra-file=$configfile"
147 else
148         userset=true;
149         if [ $usevserver = yes ]
150         then
151             userhome=`$VSERVER $vsname exec getent passwd "$user" | @AWK@ -F: '{print $6}'`
152             if [ $? -eq 2 ]
153             then
154                 fatal "User $user not found in /etc/passwd"
155             fi
156             debug "User home set to: $vroot$userhome"
157             [ -f $vroot$userhome/.my.cnf ] || fatal "Can't find config file in $userhome/.my.cnf"
158         else
159             userhome=`getent passwd "$user" | @AWK@ -F: '{print $6}'`
160             if [ $? -eq 2 ]
161             then
162                 fatal "User $user not found in /etc/passwd"
163             fi
164             debug "User home set to: $userhome"
165             [ -f $userhome/.my.cnf ] || fatal "Can't find config file in $userhome/.my.cnf"
166         fi
167         
168         defaultsfile="--defaults-extra-file=$userhome/.my.cnf"
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 --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 --allowold $db $hotdir"
207                 else
208                         execstr="$MYSQLHOTCOPY --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 --lock-tables --complete-insert --add-drop-table --quick --quote-names"
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 $workcnf"
318         rm $workcnf
319         if [ -f "$tmpcnf" ]
320         then
321                 debug "mv $tmpcnf $workcnf"
322                 mv $tmpcnf $workcnf
323         fi
324 fi
325
326 return 0