mysql: No longer prepend vroot to the backupdir.
[matthijs/upstream/backupninja.git] / handlers / mysql.in
index f79a0b2b9b235c3bfeb4fd2e83bdc9757f1ff544..db4159d412a87bc111af4c0dd97fd0184e311df1 100644 (file)
@@ -13,6 +13,7 @@ getconf sqldump no
 getconf sqldumpoptions "--lock-tables --complete-insert --add-drop-table --quick --quote-names"
 getconf compress yes
 getconf vsname
+getconf vsnames
 
 # authentication:
 getconf user
@@ -25,22 +26,30 @@ getconf configfile /etc/mysql/debian.cnf
 # 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 ?
-      vservers_running $vsname || fatal "The vserver $vsname is not running."
-      # everything ok
-      info "Using vserver '$vsname'."
-      usevserver=yes
+
+if [ -n "$vsname" ]; then
+   if [ -z "$vsnames" ]; then
+      warning "Using deprecated 'vsname' configuration variable"
+      vsnames="$vsname"
+      info "Prepending '%v' to backupdir to emulate legacy behaviour"
+      backupdir="%v/$backupdir"
    else
-      info "No vserver name specified, actions will be performed on the host."
+      warning "Ignoring (deprecated) vsname configuration variable, since vsnames is given"
+   fi
+fi
+
+if [ $vservers_are_available = yes -a -n "$vsnames" ]; then
+   if [ "$vsnames" = all ]; then
+      vsnames="$found_vservers"
+   else
+      if ! vservers_exist "$vsnames" ; then
+         fatal "At least one of the vservers listed in vsnames ($vsnames) does not exist."
+      fi
    fi
+   info "Using vservers '$vsnames'"
+   usevserver=yes
 else
-   [ -z "$vsname" ] || warning 'vservers support disabled in backupninja.conf, vsname configuration line will be ignored'
+   [ -z "$vsnames" ] || warning 'vservers support disabled in backupninja.conf, vsnames configuration line will be ignored'
 fi
 
 ## Prepare ignore part of the command
@@ -48,231 +57,255 @@ fi
 
 ignore=''
 for i in $ignores $nodata; do
-       ignore="$ignore --ignore-table=$i"
+   ignore="$ignore --ignore-table=$i"
 done
 
-if [ $usevserver = yes ]; then
-   vroot="$VROOTDIR/$vsname"
-   vexec="$VSERVER $vsname exec"
-else
-   vroot=""
-   vexec=""
-fi
+function make_backup() {
+   vsname="$1"
+   if [ -z "$vsname" ]; then
+      info "Running on host"
+      vroot=""
+      vexec=""
+   else
+      if ! vservers_running "$vsname"; then
+         error "vserver $vsname is not running!"
+         return 1
+      fi
+      info "Running on vserver $vsname"
+      vroot="$VROOTDIR/$vsname"
+      vexec="$VSERVER $vsname exec"
+   fi
 
-# 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"
+   interpolated=`interpolate "$backupdir" "$vsname"`
 
-[ "$sqldump" == "no" -o -d $vroot$dumpdir ] || $vexec mkdir -p $vroot$dumpdir
-[ "$hotcopy" == "no" -o -d $vroot$hotdir ] || $vexec mkdir -p $vroot$hotdir
+   # create backup dirs
+   [ -d $interpolated ] || mkdir -p $interpolated
+   [ -d $interpolated ] || fatal "Failed to create backup directory '$interpolated'"
 
-#######################################################################
-## AUTHENTICATION
+   hotdir="$interpolated/hotcopy"
+   dumpdir="$interpolated/sqldump"
 
-#
-# 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)
-#
+   [ "$sqldump" == "no" -o -d $dumpdir ] || mkdir -p $dumpdir
+   [ "$hotcopy" == "no" -o -d $hotdir ] || mkdir -p $hotdir
+
+   #######################################################################
+   ## 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
+   # 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
+      vhome=`$vexec getent passwd "root" | @AWK@ -F: '{print $6}'`
+      home=$vroot$vhome
+
+      [ -d $home ] || fatal "Can't find root's home directory ($home)."
 
-# create .my.cnf
-# 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
-    vhome=`$vexec getent passwd "root" | @AWK@ -F: '{print $6}'`
-    home=$vroot$vhome
-
-    [ -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"
-
-[mysqldump]
-host=$dbhost
-user=$dbusername
-password="$dbpassword"
-
-[mysqlhotcopy]
-host=$dbhost
-user=$dbusername
-password="$dbpassword"
+      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"
+
+   [mysqldump]
+   host=$dbhost
+   user=$dbusername
+   password="$dbpassword"
+
+   [mysqlhotcopy]
+   host=$dbhost
+   user=$dbusername
+   password="$dbpassword"
 EOF
-       umask $oldmask
-        defaultsfile="--defaults-extra-file=$vhome/.my.cnf"
-fi
+      umask $oldmask
+      defaultsfile="--defaults-extra-file=$vhome/.my.cnf"
+   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=`$vexec getent passwd "$user" | @AWK@ -F: '{print $6}'`
-           if [ $? -eq 2 ]
-           then
-               fatal "User $user not found in /etc/passwd"
-           fi
-           userhome="$vroot$vuserhome"
-               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=$vuserhome/.my.cnf"
-       debug "using $defaultsfile"
-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=`$vexec getent passwd "$user" | @AWK@ -F: '{print $6}'`
+         if [ $? -eq 2 ]
+         then
+            fatal "User $user not found in /etc/passwd"
+         fi
+         userhome="$vroot$vuserhome"
+      fi
 
-#######################################################################
-## HOT COPY
-
-if [ "$hotcopy" == "yes" ]
-then
-    info "Initializing hotcopy method"
-    if [ "$databases" == "all" ]
-    then
-        info "dbhost: $dbhost"
-        execstr="$vexec $MYSQLHOTCOPY -h $dbhost --quiet --allowold --regexp /.\*/./.\*/ $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 all mysql databases"
-               else
-                       warning $output
-                       warning "Failed to hotcopy all mysql databases"
-               fi
-       fi
-    else       
-       for db in $databases
-       do
-                execstr="$vexec $MYSQLHOTCOPY -h $dbhost --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
-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=$vuserhome/.my.cnf"
+      debug "using $defaultsfile"
+   fi
+
+   #######################################################################
+   ## HOT COPY
+
+   if [ "$hotcopy" == "yes" ]
+   then
+      if starts_with "$hotdir" "$vroot"; then
+         info "Initializing hotcopy method"
+         vhotdir=`strip_prefix "$hotdir" "$vroot"`
+         if [ "$databases" == "all" ]
+         then
+            info "dbhost: $dbhost"
+            execstr="$vexec $MYSQLHOTCOPY -h $dbhost --quiet --allowold --regexp /.\*/./.\*/ $vhotdir"
+
+            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
+               execstr="$vexec $MYSQLHOTCOPY -h $dbhost --allowold $db $vhotdir"
+
+               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
+      else
+         error "hotcopy method can only be used when the backupdir ($hotdir) is within the vserver ($vroot)"
+      fi
+   fi
 
-##########################################################################
-## SQL DUMP
-
-if [ "$sqldump" == "yes" ]
-then
-    info "Initializing SQL dump method"
-    if [ "$databases" == "all" ]
-    then
-        debug "$vexec su $user -c \"$MYSQL $defaultsfile -N -B -e 'show databases'\" | sed 's/|//g;/\+----/d'"
-        # -N removes the column title and -B should remove the ASCII table borders, but doesn't always so we use sed to make sure.
-        databases=`$vexec su $user -c "$MYSQL $defaultsfile -N -B -e 'show databases'" | sed 's/|//g;/\+----/d'`
-        if [ $? -ne 0 ]
-        then
-            fatal "Authentication problem, maybe user/password is wrong or mysqld is not running?"
-        fi
-    fi
-
-       for db in $databases
-       do
-           DUMP_BASE="$MYSQLDUMP $defaultsfile $sqldumpoptions"
-
-           # Dumping structure and data
-           DUMP="$DUMP_BASE $ignore $db"
-
-           # If requested, dump only the table structure for this database
-           if echo "$nodata" | grep -E '(^|[[:space:]])'"$db\." >/dev/null
+   ##########################################################################
+   ## SQL DUMP
+
+   if [ "$sqldump" == "yes" ]
+   then
+       info "Initializing SQL dump method"
+       if [ "$databases" == "all" ]
+       then
+           debug "$vexec su $user -c \"$MYSQL $defaultsfile -N -B -e 'show databases'\" | sed 's/|//g;/\+----/d'"
+           # -N removes the column title and -B should remove the ASCII table borders, but doesn't always so we use sed to make sure.
+           databases=`$vexec su $user -c "$MYSQL $defaultsfile -N -B -e 'show databases'" | sed 's/|//g;/\+----/d'`
+           if [ $? -ne 0 ]
            then
-              # Get the structure of the tables, without data
-              DUMP_STRUCT="$DUMP_BASE --no-data $db"
-              for qualified_table in $nodata
-              do
-                 table=$( expr match "$qualified_table" "$db\.\([^\w]*\)" )
-                 DUMP_STRUCT="$DUMP_STRUCT $table"
-              done
-              DUMP="( $DUMP; $DUMP_STRUCT )"
+               fatal "Authentication problem, maybe user/password is wrong or mysqld is not running?"
            fi
-                # Test to make sure mysqld is running, if it is not sqldump will not work
-                $vexec su $user -c "$MYSQLADMIN $defaultsfile ping"
-                if [ $? -ne 0 ]; then
-                   fatal "Either you have an authentication problem, or mysqld doesn't appear to be running!"
-                fi
-                if [ "$compress" == "yes" ]; then
-                   execstr="$vexec $DUMP | $GZIP > $vroot$dumpdir/${db}.sql.gz"
-                else
-                   execstr="$vexec $DUMP -r $vroot$dumpdir/${db}.sql"
-                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 dump of mysql database $db"
-                       else
-                               warning $output
-                               warning "Failed to dump mysql databases $db"
-                       fi
-               fi
-       done
-fi
+       fi
+
+           for db in $databases
+           do
+              DUMP_BASE="$MYSQLDUMP $defaultsfile $sqldumpoptions"
+
+              # Dumping structure and data
+              DUMP="$DUMP_BASE $ignore $db"
+
+              # If requested, dump only the table structure for this database
+              if echo "$nodata" | grep -E '(^|[[:space:]])'"$db\." >/dev/null
+              then
+                 # Get the structure of the tables, without data
+                 DUMP_STRUCT="$DUMP_BASE --no-data $db"
+                 for qualified_table in $nodata
+                 do
+                    table=$( expr match "$qualified_table" "$db\.\([^\w]*\)" )
+                    DUMP_STRUCT="$DUMP_STRUCT $table"
+                 done
+                 DUMP="( $DUMP; $DUMP_STRUCT )"
+              fi
+                   # Test to make sure mysqld is running, if it is not sqldump will not work
+                   $vexec su $user -c "$MYSQLADMIN $defaultsfile ping"
+                   if [ $? -ne 0 ]; then
+                      fatal "Either you have an authentication problem, or mysqld doesn't appear to be running!"
+                   fi
+                   if [ "$compress" == "yes" ]; then
+                      execstr="$vexec $DUMP | $GZIP > $dumpdir/${db}.sql.gz"
+                   else
+                      execstr="$vexec $DUMP -r $dumpdir/${db}.sql"
+                   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 dump of mysql database $db"
+                           else
+                                   warning $output
+                                   warning "Failed to dump mysql databases $db"
+                           fi
+                   fi
+           done
+   fi
 
-# clean up tmp config file
-if [ "$dbusername" != "" -a "$dbpassword" != "" ]
-then
-       ## clean up tmp config file
-       debug "rm $mycnf"
-       rm $mycnf
-       if [ -f "$tmpcnf" ]
-       then
-               debug "mv $tmpcnf $mycnf"
-               mv $tmpcnf $mycnf
-       fi
+   # clean up tmp config file
+   if [ "$dbusername" != "" -a "$dbpassword" != "" ]
+   then
+           ## clean up tmp config file
+           debug "rm $mycnf"
+           rm $mycnf
+           if [ -f "$tmpcnf" ]
+           then
+                   debug "mv $tmpcnf $mycnf"
+                   mv $tmpcnf $mycnf
+           fi
+   fi
+}
+
+if [ $usevserver = yes ]; then
+   for vserver in $vsnames; do
+      make_backup "$vserver"
+   done
+else
+   make_backup ""
 fi
 
 return 0