Added RPM patches submitted by Robert Napier
[matthijs/upstream/backupninja.git] / handlers / mysql
index 165ebc68829c35ec63a59154183c7d0e0b5b19e1..cd72fc9087bb7033e009f0c8125c0e75ef80b9a4 100644 (file)
+# -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
 #
 # mysql handler script for backupninja
 #
 
 getconf backupdir /var/backups/mysql
 getconf databases all
-getconf compress yes
-getconf dbusername
-getconf dbpassword
+getconf ignores
 getconf dbhost localhost
 getconf hotcopy no
 getconf sqldump no
-getconf user root
+getconf compress yes
+getconf vsname
 
-# create backup dirs
+# authentication:
+getconf user
+getconf dbusername
+getconf dbpassword
+getconf configfile /etc/mysql/debian.cnf
 
-[ -d $backupdir ] || mkdir -p $backupdir
-[ -d $backupdir ] || fatal "Backup directory '$backupdir'"
+
+# Decide if the handler should operate on a vserver or on the host.
+# In the former case, check that $vsname exists and is running.
+local usevserver=no
+local 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 ?
+      $VSERVERINFO -q $vsname RUNNING
+      if [ $? -ne 0 ]; then
+         fatal "The vserver $vsname is not running."
+      fi
+      # 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
+
+## Prepare ignore part of the command
+## This only works for mysqldump at the moment
+
+ignore=''
+for i in $ignores; do
+       ignore="$ignore --ignore-table=$i"
+done
+       
+# create backup dirs, $vroot will be empty if no vsname was specified
+# and we will instead proceed to operate on the host
+[ -d $vroot$backupdir ] || mkdir -p $vroot$backupdir
+[ -d $vroot$backupdir ] || fatal "Backup directory '$vroot$backupdir'"
 hotdir="$backupdir/hotcopy"
 dumpdir="$backupdir/sqldump"
-[ "$sqldump" == "no" -o -d $dumpdir ] || mkdir -p $dumpdir
-[ "$hotcopy" == "no" -o -d $hotdir ] || mkdir -p $hotdir
+
+if [ $usevserver = yes ]
+then
+       [ "$sqldump" == "no" -o -d $vroot$dumpdir ] || $VSERVER $vsname exec mkdir -p $dumpdir
+       [ "$hotcopy" == "no" -o -d $vroot$hotdir ] || $VSERVER $vsname exec mkdir -p $hotdir
+else
+       [ "$sqldump" == "no" -o -d $dumpdir ] || mkdir -p $dumpdir
+       [ "$hotcopy" == "no" -o -d $hotdir ] || mkdir -p $hotdir
+fi
+
+#######################################################################
+## AUTHENTICATION
+
+#
+# one of three authentication methods:
+# 1. setting the user, so that /home/user/.my.cnf is used.
+# 2. specifying the user and password in the handler config,
+#    which generates a temporary .my.cnf in /root/.my.cnf
+# 3. specify the config file with --defaults-extra-file
+#    (this option DOESN'T WORK WITH MYSQLHOTCOPY)
+#
 
 # create .my.cnf
- # (we do this because we don't want to have to specify the password on the command line
- # because then anyone would be able to see it with a 'ps aux'. instead, we create a 
- # temporary ~/.my.cnf in root's home directory).
-
-if [ "$dbusername" != "" ]; then
-       home=`grep '^root' /etc/passwd | awk -F: '{print $6}'`
-       [ -d $home ] || fatal "Can't find root's home directory ($home)."
-       mycnf="$home/.my.cnf"
-       if [ -f $mycnf ]; then
-               # rename temporarily
-               tmpcnf="$home/my.cnf.disable"
-               debug "mv $mycnf $tmpcnf"
-               mv $mycnf $tmpcnf
-       fi
-       oldmask=`umask`
-       umask 077
-       cat > $mycnf <<EOF
+# only if dbusername and dbpassword specified.
+# we create a tmp file because we don't want to
+# specify the password on the command line.
+
+defaultsfile=""
+
+if [ "$dbusername" != "" -a "$dbpassword" != "" ]
+then
+    if [ $usevserver = yes ]
+    then
+       vhome=`$VSERVER $vsname exec getent passwd "root" | awk -F: '{print $6}'`
+       home="$vroot$vhome"
+    else
+       home=`getent passwd "root" | awk -F: '{print $6}'`
+    fi
+
+    [ -d $home ] || fatal "Can't find root's home directory ($home)."
+    
+    mycnf="$home/.my.cnf"
+    
+    if [ -f $mycnf ]
+    then
+       # rename temporarily
+       tmpcnf="$home/my.cnf.disable"
+       debug "mv $mycnf $tmpcnf"
+       mv $mycnf $tmpcnf
+    fi
+    
+    oldmask=`umask`
+    umask 077
+    cat > $mycnf <<EOF
 # auto generated backupninja mysql conf
 [mysql]
+host=$dbhost
 user=$dbusername
-password=$dbpassword
+password="$dbpassword"
 
 [mysqldump]
+host=$dbhost
 user=$dbusername
-password=$dbpassword
+password="$dbpassword"
 
 [mysqlhotcopy]
+host=$dbhost
 user=$dbusername
-password=$dbpassword
+password="$dbpassword"
 EOF
        umask $oldmask
+       if [ $usevserver = yes ] 
+       then
+           defaultsfile="--defaults-extra-file=$vhome/.my.cnf"
+       else
+           defaultsfile="--defaults-extra-file=$mycnf"
+       fi
 fi
+
+# if a user is not set, use $configfile, otherwise use $mycnf
+if [ "$user" == "" ]; then
+       user=root;
+       defaultsfile="--defaults-extra-file=$configfile"
+else
+       userset=true;
+       if [ $usevserver = yes ]
+       then
+           vuserhome=`$VSERVER $vsname exec getent passwd "$user" | awk -F: '{print $6}'`
+           if [ $? -eq 2 ]
+           then
+               fatal "User $user not found in /etc/passwd"
+           fi
+           userhome="$vroot$vuserhome"
+       else
+           userhome=`getent passwd "$user" | awk -F: '{print $6}'`
+           if [ $? -eq 2 ]
+           then
+               fatal "User $user not found in /etc/passwd"
+           fi
+               fi
        
+       debug "User home set to: $userhome"
+       [ -f $userhome/.my.cnf ] || fatal "Can't find config file in $userhome/.my.cnf"
+       defaultsfile="--defaults-extra-file=$userhome/.my.cnf"
+       debug "using $defaultsfile"
+fi
+
+#######################################################################
 ## HOT COPY
 
-if [ "$hotcopy" == "yes" ]; then 
-       if [ "$databases" == "all" ]; then
+if [ "$hotcopy" == "yes" ]
+then
+    info "Initializing hotcopy method"
+    if [ "$databases" == "all" ]
+    then
+       if [ $usevserver = yes ]
+       then
+               info "dbhost: $dbhost"
+               execstr="$VSERVER $vsname exec $MYSQLHOTCOPY -h $dbhost --quiet --allowold --regexp /.\*/./.\*/ $hotdir"
+       else
                execstr="$MYSQLHOTCOPY --quiet --allowold --regexp /.\*/./.\*/ $hotdir"
-               debug "su $user -c '$execstr'"
-               if [ ! $test ]; then
+       fi
+       debug "su $user -c \"$execstr\""
+       if [ ! $test ]
+       then
+               output=`su $user -c "$execstr" 2>&1`
+               code=$?
+               if [ "$code" == "0" ]
+               then
+                       debug $output
+                       info "Successfully finished hotcopy of all mysql databases"
+               else
+                       warning $output
+                       warning "Failed to hotcopy all mysql databases"
+               fi
+       fi
+    else       
+       for db in $databases
+       do
+               if [ $usevserver = yes ]
+               then
+                       execstr="$VSERVER $vsname exec $MYSQLHOTCOPY --allowold $db $hotdir"
+               else
+                       execstr="$MYSQLHOTCOPY --allowold $db $hotdir"
+               fi
+               debug 'su $user -c \"$execstr\"'
+               if [ ! $test ]
+               then
                        output=`su $user -c "$execstr" 2>&1`
                        code=$?
-                       if [ "$code" == "0" ]; then
+                       if [ "$code" == "0" ]
+                       then
                                debug $output
-                               info "Successfully finished hotcopy of all mysql databases"
+                               info "Successfully finished hotcopy of mysql database $db"
                        else
                                warning $output
-                               warning "Failed to hotcopy all mysql databases"
+                               warning "Failed to hotcopy mysql database $db"
                        fi
                fi
-       else    
-               for db in $databases; do
-                       execstr="$MYSQLHOTCOPY --allowold $db $hotdir"
-                       debug "su $user -c '$execstr'"
-                       if [ ! $test ]; then
-                               output=`su $user -c "$execstr" 2>&1`
-                               code=$?
-                               if [ "$code" == "0" ]; then
-                                       debug $output
-                                       info "Successfully finished hotcopy of mysql database $db"
-                               else
-                                       warning $output
-                                       warning "Failed to hotcopy mysql database $db"
-                               fi
-                       fi
-               done
-       fi
+       done
+     fi
 fi
-       
+
+##########################################################################
 ## SQL DUMP
 
-if [ "$sqldump" == "yes" ]; then
-       if [ "$databases" == "all" ]; then
-               databases=`echo 'show databases' | su $user -c "$MYSQL" | grep -v Database`
+if [ "$sqldump" == "yes" ]
+then
+    info "Initializing SQL dump method"
+    if [ "$databases" == "all" ]
+    then
+       if [ $usevserver = yes ]
+       then
+           debug 'echo show databases | $VSERVER $vsname exec su $user -c \"$MYSQL $defaultsfile\" | grep -v Database'
+           databases=`echo 'show databases' | $VSERVER $vsname exec su $user -c "$MYSQL $defaultsfile" | grep -v Database`
+           if [ $? -ne 0 ]
+           then
+               fatal "Authentication problem, maybe user/password is wrong"
+           fi
+       else
+               databases=`echo 'show databases' | su $user -c "$MYSQL $defaultsfile" | grep -v Database`
+               if [ $? -ne 0 ]
+               then
+                   fatal "Authentication problem, maybe user/password is wrong"
+               fi
        fi
+fi
 
-       for db in $databases; do
-               execstr="$MYSQLDUMP --lock-tables --complete-insert --add-drop-table --quick --quote-names $db > $dumpdir/${db}.sql"
-               debug "su $user -c '$execstr'"
-               if [ ! $test ]; then
+       for db in $databases
+       do
+               if [ $usevserver = yes ]
+               then
+                   if [ "$compress" == "yes" ]; then
+                      execstr="$VSERVER $vsname exec $MYSQLDUMP $defaultsfile --lock-tables --complete-insert --add-drop-table --quick --quote-names $ignore $db | $GZIP > $vroot$dumpdir/${db}.sql.gz"
+                   else
+                      execstr="$VSERVER $vsname exec $MYSQLDUMP $defaultsfile --lock-tables --complete-insert --add-drop-table --quick --quote-names $ignore $db > $vroot$dumpdir/${db}.sql"
+                   fi
+               else
+                   if [ "$compress" == "yes" ]; then
+                      execstr="$MYSQLDUMP $defaultsfile --lock-tables --complete-insert --add-drop-table --quick --quote-names $ignore $db | $GZIP > $dumpdir/${db}.sql.gz"
+                   else
+                      execstr="$MYSQLDUMP $defaultsfile --lock-tables --complete-insert --add-drop-table --quick --quote-names $ignore $db > $dumpdir/${db}.sql"
+                   fi
+               fi
+               debug "su $user -c \"$execstr\""
+               if [ ! $test ]
+               then
                        output=`su $user -c "$execstr" 2>&1`
                        code=$?
-                       if [ "$code" == "0" ]; then
+                       if [ "$code" == "0" ]
+                       then
                                debug $output
                                info "Successfully finished dump of mysql database $db"
                        else
@@ -113,18 +276,16 @@ if [ "$sqldump" == "yes" ]; then
                        fi
                fi
        done
-       
-       if [ "$compress" == "yes" ]; then
-               output=`$GZIP -f $dumpdir/*.sql 2>&1`
-               debug $output
-       fi
 fi
 
-if [ "$dbusername" != "" ]; then
+# clean up tmp config file
+if [ "$dbusername" != "" -a "$dbpassword" != "" ]
+then
        ## clean up tmp config file
        debug "rm $mycnf"
        rm $mycnf
-       if [ -f "$tmpcnf" ]; then
+       if [ -f "$tmpcnf" ]
+       then
                debug "mv $tmpcnf $mycnf"
                mv $tmpcnf $mycnf
        fi