summaryrefslogtreecommitdiff
path: root/lib/backup
diff options
context:
space:
mode:
Diffstat (limited to 'lib/backup')
-rw-r--r--lib/backup/artifacts.rb4
-rw-r--r--lib/backup/builds.rb4
-rw-r--r--lib/backup/database.rb21
-rw-r--r--lib/backup/files.rb4
-rw-r--r--lib/backup/lfs.rb4
-rw-r--r--lib/backup/manager.rb158
-rw-r--r--lib/backup/packages.rb4
-rw-r--r--lib/backup/pages.rb4
-rw-r--r--lib/backup/registry.rb8
-rw-r--r--lib/backup/repositories.rb21
-rw-r--r--lib/backup/terraform_state.rb4
-rw-r--r--lib/backup/uploads.rb4
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