diff options
Diffstat (limited to 'lib/backup')
-rw-r--r-- | lib/backup/artifacts.rb | 4 | ||||
-rw-r--r-- | lib/backup/builds.rb | 4 | ||||
-rw-r--r-- | lib/backup/database.rb | 21 | ||||
-rw-r--r-- | lib/backup/files.rb | 4 | ||||
-rw-r--r-- | lib/backup/lfs.rb | 4 | ||||
-rw-r--r-- | lib/backup/manager.rb | 158 | ||||
-rw-r--r-- | lib/backup/packages.rb | 4 | ||||
-rw-r--r-- | lib/backup/pages.rb | 4 | ||||
-rw-r--r-- | lib/backup/registry.rb | 8 | ||||
-rw-r--r-- | lib/backup/repositories.rb | 21 | ||||
-rw-r--r-- | lib/backup/terraform_state.rb | 4 | ||||
-rw-r--r-- | lib/backup/uploads.rb | 4 |
12 files changed, 229 insertions, 11 deletions
diff --git a/lib/backup/artifacts.rb b/lib/backup/artifacts.rb index 6a45baa60ec..163446998e9 100644 --- a/lib/backup/artifacts.rb +++ b/lib/backup/artifacts.rb @@ -9,5 +9,9 @@ module Backup super('artifacts', JobArtifactUploader.root, excludes: ['tmp']) end + + def human_name + _('artifacts') + end end end diff --git a/lib/backup/builds.rb b/lib/backup/builds.rb index 9c3b7165de7..51a68ca933d 100644 --- a/lib/backup/builds.rb +++ b/lib/backup/builds.rb @@ -9,5 +9,9 @@ module Backup super('builds', Settings.gitlab_ci.builds_path) end + + def human_name + _('builds') + end end end diff --git a/lib/backup/database.rb b/lib/backup/database.rb index a4ac404d245..de26dbab038 100644 --- a/lib/backup/database.rb +++ b/lib/backup/database.rb @@ -90,7 +90,26 @@ module Backup report_success(success) raise Backup::Error, 'Restore failed' unless success - errors + if errors.present? + warning = <<~MSG + 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 + + warn warning.color(:red) + Gitlab::TaskHelpers.ask_to_continue + end + end + + def enabled + true + end + + def human_name + _('database') end protected diff --git a/lib/backup/files.rb b/lib/backup/files.rb index 4e51dcfb79e..880522bc0f5 100644 --- a/lib/backup/files.rb +++ b/lib/backup/files.rb @@ -63,6 +63,10 @@ module Backup end end + def enabled + true + end + def tar if system(*%w[gtar --version], out: '/dev/null') # It looks like we can get GNU tar by running 'gtar' diff --git a/lib/backup/lfs.rb b/lib/backup/lfs.rb index 514d52d7f65..17f7b8bf8b0 100644 --- a/lib/backup/lfs.rb +++ b/lib/backup/lfs.rb @@ -9,5 +9,9 @@ module Backup super('lfs', Settings.lfs.storage_path) end + + def human_name + _('lfs objects') + end end end diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb index ed2e001cefc..5b393cf9477 100644 --- a/lib/backup/manager.rb +++ b/lib/backup/manager.rb @@ -10,6 +10,137 @@ module Backup def initialize(progress) @progress = progress + + max_concurrency = ENV.fetch('GITLAB_BACKUP_MAX_CONCURRENCY', 1).to_i + max_storage_concurrency = ENV.fetch('GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY', 1).to_i + + @tasks = { + 'db' => Database.new(progress), + 'repositories' => Repositories.new(progress, + strategy: repository_backup_strategy, + max_concurrency: max_concurrency, + max_storage_concurrency: max_storage_concurrency), + 'uploads' => Uploads.new(progress), + 'builds' => Builds.new(progress), + 'artifacts' => Artifacts.new(progress), + 'pages' => Pages.new(progress), + 'lfs' => Lfs.new(progress), + 'terraform_state' => TerraformState.new(progress), + 'registry' => Registry.new(progress), + 'packages' => Packages.new(progress) + }.freeze + end + + def create + @tasks.keys.each do |task_name| + run_create_task(task_name) + end + + write_info + + if ENV['SKIP'] && ENV['SKIP'].include?('tar') + upload + else + pack + upload + cleanup + remove_old + end + + progress.puts "Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data \n" \ + "and are not included in this backup. You will need these files to restore a backup.\n" \ + "Please back them up manually.".color(:red) + progress.puts "Backup task is done." + end + + def run_create_task(task_name) + task = @tasks[task_name] + + puts_time "Dumping #{task.human_name} ... ".color(:blue) + + unless task.enabled + puts_time "[DISABLED]".color(:cyan) + return + end + + if ENV["SKIP"] && ENV["SKIP"].include?(task_name) + puts_time "[SKIPPED]".color(:cyan) + return + end + + task.dump + puts_time "done".color(:green) + + rescue Backup::DatabaseBackupError, Backup::FileBackupError => e + progress.puts "#{e.message}" + end + + def restore + cleanup_required = unpack + verify_backup_version + + unless skipped?('db') + begin + unless ENV['force'] == 'yes' + warning = <<-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 + puts warning.color(:red) + Gitlab::TaskHelpers.ask_to_continue + 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 + puts_time 'Cleaning the database ... '.color(:blue) + Rake::Task['gitlab:db:drop_tables'].invoke + puts_time 'done'.color(:green) + run_restore_task('db') + rescue Gitlab::TaskAbortedByUserError + puts "Quitting...".color(:red) + exit 1 + end + end + + @tasks.except('db').keys.each do |task_name| + run_restore_task(task_name) unless skipped?(task_name) + end + + Rake::Task['gitlab:shell:setup'].invoke + Rake::Task['cache:clear'].invoke + + if cleanup_required + cleanup + end + + remove_tmp + + puts "Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data \n" \ + "and are not included in this backup. You will need to restore these files manually.".color(:red) + puts "Restore task is done." + end + + def run_restore_task(task_name) + task = @tasks[task_name] + + puts_time "Restoring #{task.human_name} ... ".color(:blue) + + unless task.enabled + puts_time "[DISABLED]".color(:cyan) + return + end + + task.restore + puts_time "done".color(:green) end def write_info @@ -188,11 +319,15 @@ module Backup end def skipped?(item) - settings[:skipped] && settings[:skipped].include?(item) || disabled_features.include?(item) + settings[:skipped] && settings[:skipped].include?(item) || !enabled_task?(item) end private + def enabled_task?(task_name) + @tasks[task_name].enabled + end + def backup_file?(file) file.match(/^(\d{10})(?:_\d{4}_\d{2}_\d{2}(_\d+\.\d+\.\d+((-|\.)(pre|rc\d))?(-ee)?)?)?_gitlab_backup\.tar$/) end @@ -256,12 +391,6 @@ module Backup FOLDERS_TO_BACKUP.select { |name| !skipped?(name) && Dir.exist?(File.join(backup_path, name)) } end - def disabled_features - features = [] - features << 'registry' unless Gitlab.config.registry.enabled - features - end - def settings @settings ||= YAML.load_file("backup_information.yml") end @@ -317,6 +446,21 @@ module Backup def google_provider? Gitlab.config.backup.upload.connection&.provider&.downcase == 'google' end + + def repository_backup_strategy + if Feature.enabled?(:gitaly_backup, default_enabled: :yaml) + max_concurrency = ENV['GITLAB_BACKUP_MAX_CONCURRENCY'].presence + max_storage_concurrency = ENV['GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY'].presence + Backup::GitalyBackup.new(progress, max_parallelism: max_concurrency, storage_parallelism: max_storage_concurrency) + else + Backup::GitalyRpcBackup.new(progress) + end + end + + def puts_time(msg) + progress.puts "#{Time.now} -- #{msg}" + Gitlab::BackupLogger.info(message: "#{Rainbow.uncolor(msg)}") + end end end diff --git a/lib/backup/packages.rb b/lib/backup/packages.rb index 7b6a8f086ed..037ff31fd9b 100644 --- a/lib/backup/packages.rb +++ b/lib/backup/packages.rb @@ -9,5 +9,9 @@ module Backup super('packages', Settings.packages.storage_path, excludes: ['tmp']) end + + def human_name + _('packages') + end end end diff --git a/lib/backup/pages.rb b/lib/backup/pages.rb index 393cf4108a1..724972d212d 100644 --- a/lib/backup/pages.rb +++ b/lib/backup/pages.rb @@ -13,5 +13,9 @@ module Backup super('pages', Gitlab.config.pages.path, excludes: [LEGACY_PAGES_TMP_PATH]) end + + def human_name + _('pages') + end end end diff --git a/lib/backup/registry.rb b/lib/backup/registry.rb index 9645a07dfb8..7ba3a9e9c60 100644 --- a/lib/backup/registry.rb +++ b/lib/backup/registry.rb @@ -9,5 +9,13 @@ module Backup super('registry', Settings.registry.path) end + + def human_name + _('container registry images') + end + + def enabled + Gitlab.config.registry.enabled + end end end diff --git a/lib/backup/repositories.rb b/lib/backup/repositories.rb index 4c39e58c87d..e7c3e869928 100644 --- a/lib/backup/repositories.rb +++ b/lib/backup/repositories.rb @@ -4,12 +4,14 @@ require 'yaml' module Backup class Repositories - def initialize(progress, strategy:) + def initialize(progress, strategy:, max_concurrency: 1, max_storage_concurrency: 1) @progress = progress @strategy = strategy + @max_concurrency = max_concurrency + @max_storage_concurrency = max_storage_concurrency end - def dump(max_concurrency:, max_storage_concurrency:) + def dump strategy.start(:create) # gitaly-backup is designed to handle concurrency on its own. So we want @@ -19,6 +21,11 @@ module Backup return enqueue_consecutive end + if max_concurrency < 1 || max_storage_concurrency < 1 + puts "GITLAB_BACKUP_MAX_CONCURRENCY and GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY must have a value of at least 1".color(:red) + exit 1 + end + check_valid_storages! semaphore = Concurrent::Semaphore.new(max_concurrency) @@ -54,9 +61,17 @@ module Backup restore_object_pools end + def enabled + true + end + + def human_name + _('repositories') + end + private - attr_reader :progress, :strategy + attr_reader :progress, :strategy, :max_concurrency, :max_storage_concurrency def check_valid_storages! repository_storage_klasses.each do |klass| diff --git a/lib/backup/terraform_state.rb b/lib/backup/terraform_state.rb index 5f71e18f1b4..be82793fe03 100644 --- a/lib/backup/terraform_state.rb +++ b/lib/backup/terraform_state.rb @@ -9,5 +9,9 @@ module Backup super('terraform_state', Settings.terraform_state.storage_path, excludes: ['tmp']) end + + def human_name + _('terraform states') + end end end diff --git a/lib/backup/uploads.rb b/lib/backup/uploads.rb index 9665624f71b..7048a9a8ff5 100644 --- a/lib/backup/uploads.rb +++ b/lib/backup/uploads.rb @@ -9,5 +9,9 @@ module Backup super('uploads', File.join(Gitlab.config.uploads.storage_path, "uploads"), excludes: ['tmp']) end + + def human_name + _('uploads') + end end end |