module EY module Backup class MysqlEngine < Engine register 'mysql' def dump(database_name, basename) file = basename + '.sql' command = "mysqldump #{username_option} #{host_option} #{single_transaction_option(database_name)} #{routines_option} #{master_data_option} #{databases_option(database_name)} 2> /tmp/eybackup.$$.dumperr" if gpg? command << " | " << GPGEncryptor.command_for(key_id) file << GPGEncryptor.extension else command << " | " << GZipper.gzip file << GZipper.extension end command << " > #{file}" run(command, database_name) file end def load(database_name, file) cycle_database(database_name) command = "cat #{file}" if gpg? raise "Cannot load a GPG backup" else command << " | " << GZipper.gunzip end command << " | mysql #{username_option} #{host_option} #{database_name}" run(command) end def check_if_replica err_msg="ERROR: Target host: '#{host}' is currently: " err_msg=err_msg + "a replica based on 'show slave status', " if db_replicating? err_msg=err_msg + "in read_only mode, " if read_only_on? err_msg=err_msg + "restores should be processed against the master." EY::Backup.logger.fatal(%Q{#{err_msg}}) if db_replicating? or read_only_on? end def routines_option "--routines" end def master_data_option "--master-data=2" if log_bin_on? end def databases_option(db) "--add-drop-database --databases #{db}" end def host_option "-h#{host}" end def username_option "-u#{username}" end def single_transaction_option(database_name) '--single-transaction' unless db_has_myisam?(database_name) end def db_has_myisam?(database_name) query, stdout = "SELECT 1 FROM information_schema.tables WHERE table_schema='#{database_name}' AND engine='MyISAM' LIMIT 1;", StringIO.new spawn(%Q{mysql #{username_option} #{host_option} -N -e"#{query}"}, stdout) stdout.string.strip == '1' end def db_replicating? stdout = StringIO.new spawn(%Q{mysql #{username_option} #{host_option} -BN -e"show slave status"|wc -l}, stdout) stdout.string.to_i > 0 end def read_only_on? stdout = StringIO.new spawn(%Q{mysql #{username_option} #{host_option} -BN -e"select @@global.read_only"}, stdout) stdout.string.to_i == 1 end def log_bin_on? stdout = StringIO.new spawn(%Q{mysql #{username_option} #{host_option} -BN -e"select @@global.log_bin"}, stdout) stdout.string.to_i == 1 end def cycle_database(database_name) query = "show create database #{database_name} \\G" create_cmd = %x(mysql #{username_option} #{host_option} -NB -e "#{query}"|tail -n 1) create_cmd="Create database #{database_name}" if create_cmd=="" %x(mysql #{username_option} #{host_option} -e 'DROP DATABASE IF EXISTS #{database_name}') %x(mysql #{username_option} #{host_option} -e '#{create_cmd}') end def suffix /sql\.(gz|gpz)$/ end end end end