Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/backup/database.rb')
-rw-r--r--lib/backup/database.rb277
1 files changed, 0 insertions, 277 deletions
diff --git a/lib/backup/database.rb b/lib/backup/database.rb
deleted file mode 100644
index 962214407d9..00000000000
--- a/lib/backup/database.rb
+++ /dev/null
@@ -1,277 +0,0 @@
-# frozen_string_literal: true
-
-require 'yaml'
-
-module Backup
- class Database < Task
- extend ::Gitlab::Utils::Override
- include Backup::Helper
- attr_reader :force
-
- IGNORED_ERRORS = [
- # Ignore warnings
- /WARNING:/,
- # Ignore the DROP errors; recent database dumps will use --if-exists with pg_dump
- /does not exist$/,
- # User may not have permissions to drop extensions or schemas
- /must be owner of/
- ].freeze
- IGNORED_ERRORS_REGEXP = Regexp.union(IGNORED_ERRORS).freeze
-
- def initialize(progress, options:, force:)
- super(progress, options: options)
- @force = force
- end
-
- override :dump
- def dump(destination_dir, _)
- FileUtils.mkdir_p(destination_dir)
-
- each_database(destination_dir) do |backup_connection|
- pg_env = backup_connection.database_configuration.pg_env_variables
- active_record_config = backup_connection.database_configuration.activerecord_variables
- pg_database_name = active_record_config[:database]
-
- dump_file_name = file_name(destination_dir, backup_connection.connection_name)
- FileUtils.rm_f(dump_file_name)
-
- progress.print "Dumping PostgreSQL database #{pg_database_name} ... "
-
- schemas = []
-
- if Gitlab.config.backup.pg_schema
- schemas << Gitlab.config.backup.pg_schema
- schemas.push(*Gitlab::Database::EXTRA_SCHEMAS.map(&:to_s))
- end
-
- pg_dump = ::Gitlab::Backup::Cli::Utils::PgDump.new(
- database_name: pg_database_name,
- snapshot_id: backup_connection.snapshot_id,
- schemas: schemas,
- env: pg_env)
-
- success = Backup::Dump::Postgres.new.dump(dump_file_name, pg_dump)
-
- backup_connection.release_snapshot! if backup_connection.snapshot_id
-
- raise DatabaseBackupError.new(active_record_config, dump_file_name) unless success
-
- report_success(success)
- progress.flush
- end
- ensure
- ::Gitlab::Database::EachDatabase.each_connection(
- only: base_models_for_backup.keys, include_shared: false
- ) do |connection, _|
- Gitlab::Database::TransactionTimeoutSettings.new(connection).restore_timeouts
- end
- end
-
- override :restore
- def restore(destination_dir, backup_id)
- base_models_for_backup.each do |database_name, _|
- backup_connection = Backup::DatabaseConnection.new(database_name)
-
- config = backup_connection.database_configuration.activerecord_variables
-
- db_file_name = file_name(destination_dir, database_name)
- database = config[:database]
-
- unless File.exist?(db_file_name)
- raise(Backup::Error, "Source database file does not exist #{db_file_name}") if main_database?(database_name)
-
- progress.puts "Source backup for the database #{database_name} doesn't exist. Skipping the task"
- return false
- end
-
- unless force
- progress.puts 'Removing all tables. Press `Ctrl-C` within 5 seconds to abort'.color(:yellow)
- sleep(5)
- end
-
- # Drop all tables Load the schema to ensure we don't have any newer tables
- # hanging out from a failed upgrade
- drop_tables(database_name)
-
- pg_env = backup_connection.database_configuration.pg_env_variables
- success = with_transient_pg_env(pg_env) do
- decompress_rd, decompress_wr = IO.pipe
- decompress_pid = spawn(decompress_cmd, out: decompress_wr, in: db_file_name)
- decompress_wr.close
-
- status, @errors =
- case config[:adapter]
- when "postgresql" then
- progress.print "Restoring PostgreSQL database #{database} ... "
- execute_and_track_errors(pg_restore_cmd(database), decompress_rd)
- end
- decompress_rd.close
-
- Process.waitpid(decompress_pid)
- $?.success? && status.success?
- end
-
- if @errors.present?
- progress.print "------ BEGIN ERRORS -----\n".color(:yellow)
- progress.print @errors.join.color(:yellow)
- progress.print "------ END ERRORS -------\n".color(:yellow)
- end
-
- report_success(success)
- raise Backup::Error, 'Restore failed' unless success
- end
- end
-
- override :pre_restore_warning
- def pre_restore_warning
- return if force
-
- <<-MSG.strip_heredoc
- Be sure to stop Puma, Sidekiq, and any other process that
- connects to the database before proceeding. For Omnibus
- installs, see the following link for more information:
- https://docs.gitlab.com/ee/raketasks/backup_restore.html#restore-for-omnibus-gitlab-installations
-
- Before restoring the database, we will remove all existing
- tables to avoid future upgrade problems. Be aware that if you have
- custom tables in the GitLab database these tables and all data will be
- removed.
- MSG
- end
-
- override :post_restore_warning
- def post_restore_warning
- return unless @errors.present?
-
- <<-MSG.strip_heredoc
- There were errors in restoring the schema. This may cause
- issues if this results in missing indexes, constraints, or
- columns. Please record the errors above and contact GitLab
- Support if you have questions:
- https://about.gitlab.com/support/
- MSG
- end
-
- protected
-
- def base_models_for_backup
- @base_models_for_backup ||= Gitlab::Database.database_base_models_with_gitlab_shared
- end
-
- def main_database?(database_name)
- database_name.to_sym == :main
- end
-
- def file_name(base_dir, database_name)
- prefix = if database_name.to_sym != :main
- "#{database_name}_"
- else
- ''
- end
-
- File.join(base_dir, "#{prefix}database.sql.gz")
- end
-
- def ignore_error?(line)
- IGNORED_ERRORS_REGEXP.match?(line)
- end
-
- def execute_and_track_errors(cmd, decompress_rd)
- errors = []
-
- Open3.popen3(ENV, *cmd) do |stdin, stdout, stderr, thread|
- stdin.binmode
-
- out_reader = Thread.new do
- data = stdout.read
- $stdout.write(data)
- end
-
- err_reader = Thread.new do
- until (raw_line = stderr.gets).nil?
- warn(raw_line)
- errors << raw_line unless ignore_error?(raw_line)
- end
- end
-
- begin
- IO.copy_stream(decompress_rd, stdin)
- rescue Errno::EPIPE
- end
-
- stdin.close
- [thread, out_reader, err_reader].each(&:join)
- [thread.value, errors]
- end
- end
-
- def report_success(success)
- if success
- progress.puts '[DONE]'.color(:green)
- else
- progress.puts '[FAILED]'.color(:red)
- end
- end
-
- private
-
- def drop_tables(database_name)
- puts_time 'Cleaning the database ... '.color(:blue)
-
- if Rake::Task.task_defined? "gitlab:db:drop_tables:#{database_name}"
- Rake::Task["gitlab:db:drop_tables:#{database_name}"].invoke
- else
- # In single database (single or two connections)
- Rake::Task["gitlab:db:drop_tables"].invoke
- end
-
- puts_time 'done'.color(:green)
- end
-
- # @deprecated This will be removed when restore operation is refactored to use extended_env directly
- def with_transient_pg_env(extended_env)
- ENV.merge!(extended_env)
- result = yield
- ENV.reject! { |k, _| extended_env.key?(k) }
-
- result
- end
-
- def pg_restore_cmd(database)
- ['psql', database]
- end
-
- def each_database(destination_dir, &block)
- databases = []
-
- # each connection will loop through all database connections defined in `database.yml`
- # and reject the ones that are shared, so we don't get duplicates
- #
- # we consider a connection to be shared when it has `database_tasks: false`
- ::Gitlab::Database::EachDatabase.each_connection(
- only: base_models_for_backup.keys, include_shared: false
- ) do |_, database_connection_name|
- backup_connection = Backup::DatabaseConnection.new(database_connection_name)
- databases << backup_connection
-
- next unless multiple_databases?
-
- begin
- # Trigger a transaction snapshot export that will be used by pg_dump later on
- backup_connection.export_snapshot!
- rescue ActiveRecord::ConnectionNotEstablished
- raise Backup::DatabaseBackupError.new(
- backup_connection.database_configuration.activerecord_variables,
- file_name(destination_dir, database_connection_name)
- )
- end
- end
-
- databases.each(&block)
- end
-
- def multiple_databases?
- Gitlab::Database.database_mode == Gitlab::Database::MODE_MULTIPLE_DATABASES
- end
- end
-end