Commit fb790bf6 authored by James Fargher's avatar James Fargher

Set gitaly-backup to create incremental backups

Incremental backups require a different filesystem layout.
In `gitaly-backup` we do this using `-layout pointer`. This writes files
called `LATEST` that point to the latest full backup and the latest
increment.

Note that in the future we will likely need to use `-id` but for now we
are only using it to make tests repeatable.
parent e53b3f95
...@@ -9,10 +9,13 @@ module Backup ...@@ -9,10 +9,13 @@ module Backup
# @param [StringIO] progress IO interface to output progress # @param [StringIO] progress IO interface to output progress
# @param [Integer] max_parallelism max parallelism when running backups # @param [Integer] max_parallelism max parallelism when running backups
# @param [Integer] storage_parallelism max parallelism per storage (is affected by max_parallelism) # @param [Integer] storage_parallelism max parallelism per storage (is affected by max_parallelism)
def initialize(progress, max_parallelism: nil, storage_parallelism: nil) # @param [String] backup_id unique identifier for the backup
def initialize(progress, max_parallelism: nil, storage_parallelism: nil, incremental: false, backup_id: nil)
@progress = progress @progress = progress
@max_parallelism = max_parallelism @max_parallelism = max_parallelism
@storage_parallelism = storage_parallelism @storage_parallelism = storage_parallelism
@incremental = incremental
@backup_id = backup_id
end end
def start(type, backup_repos_path) def start(type, backup_repos_path)
...@@ -30,6 +33,13 @@ module Backup ...@@ -30,6 +33,13 @@ module Backup
args = [] args = []
args += ['-parallel', @max_parallelism.to_s] if @max_parallelism args += ['-parallel', @max_parallelism.to_s] if @max_parallelism
args += ['-parallel-storage', @storage_parallelism.to_s] if @storage_parallelism args += ['-parallel-storage', @storage_parallelism.to_s] if @storage_parallelism
if Feature.enabled?(:incremental_repository_backup, default_enabled: :yaml)
args += ['-layout', 'pointer']
if type == :create
args += ['-incremental'] if @incremental
args += ['-id', @backup_id] if @backup_id
end
end
@input_stream, stdout, @thread = Open3.popen2(build_env, bin_path, command, '-path', backup_repos_path, *args) @input_stream, stdout, @thread = Open3.popen2(build_env, bin_path, command, '-path', backup_repos_path, *args)
......
...@@ -21,6 +21,7 @@ module Backup ...@@ -21,6 +21,7 @@ module Backup
max_concurrency = ENV.fetch('GITLAB_BACKUP_MAX_CONCURRENCY', 1).to_i max_concurrency = ENV.fetch('GITLAB_BACKUP_MAX_CONCURRENCY', 1).to_i
max_storage_concurrency = ENV.fetch('GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY', 1).to_i max_storage_concurrency = ENV.fetch('GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY', 1).to_i
force = ENV['force'] == 'yes' force = ENV['force'] == 'yes'
incremental = Gitlab::Utils.to_boolean(ENV['INCREMENTAL'], default: false)
@definitions = definitions || { @definitions = definitions || {
'db' => TaskDefinition.new( 'db' => TaskDefinition.new(
...@@ -32,7 +33,7 @@ module Backup ...@@ -32,7 +33,7 @@ module Backup
destination_path: 'repositories', destination_path: 'repositories',
destination_optional: true, destination_optional: true,
task: Repositories.new(progress, task: Repositories.new(progress,
strategy: repository_backup_strategy, strategy: repository_backup_strategy(incremental),
max_concurrency: max_concurrency, max_concurrency: max_concurrency,
max_storage_concurrency: max_storage_concurrency) max_storage_concurrency: max_storage_concurrency)
), ),
...@@ -481,11 +482,11 @@ module Backup ...@@ -481,11 +482,11 @@ module Backup
Gitlab.config.backup.upload.connection&.provider&.downcase == 'google' Gitlab.config.backup.upload.connection&.provider&.downcase == 'google'
end end
def repository_backup_strategy def repository_backup_strategy(incremental)
if Feature.enabled?(:gitaly_backup, default_enabled: :yaml) if Feature.enabled?(:gitaly_backup, default_enabled: :yaml)
max_concurrency = ENV['GITLAB_BACKUP_MAX_CONCURRENCY'].presence max_concurrency = ENV['GITLAB_BACKUP_MAX_CONCURRENCY'].presence
max_storage_concurrency = ENV['GITLAB_BACKUP_MAX_STORAGE_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) Backup::GitalyBackup.new(progress, incremental: incremental, max_parallelism: max_concurrency, storage_parallelism: max_storage_concurrency)
else else
Backup::GitalyRpcBackup.new(progress) Backup::GitalyRpcBackup.new(progress)
end end
......
This diff is collapsed.
...@@ -176,8 +176,8 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -176,8 +176,8 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect(exit_status).to eq(0) expect(exit_status).to eq(0)
expect(tar_contents).to match(user_backup_path) expect(tar_contents).to match(user_backup_path)
expect(tar_contents).to match("#{user_backup_path}/custom_hooks.tar") expect(tar_contents).to match("#{user_backup_path}/.+/001.custom_hooks.tar")
expect(tar_contents).to match("#{user_backup_path}.bundle") expect(tar_contents).to match("#{user_backup_path}/.+/001.bundle")
end end
it 'restores files correctly' do it 'restores files correctly' do
...@@ -360,14 +360,14 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -360,14 +360,14 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect(exit_status).to eq(0) expect(exit_status).to eq(0)
[ [
"#{project_a.disk_path}.bundle", "#{project_a.disk_path}/.+/001.bundle",
"#{project_a.disk_path}.wiki.bundle", "#{project_a.disk_path}.wiki/.+/001.bundle",
"#{project_a.disk_path}.design.bundle", "#{project_a.disk_path}.design/.+/001.bundle",
"#{project_b.disk_path}.bundle", "#{project_b.disk_path}/.+/001.bundle",
"#{project_snippet_a.disk_path}.bundle", "#{project_snippet_a.disk_path}/.+/001.bundle",
"#{project_snippet_b.disk_path}.bundle" "#{project_snippet_b.disk_path}/.+/001.bundle"
].each do |repo_name| ].each do |repo_name|
expect(tar_lines.grep(/#{repo_name}/).size).to eq 1 expect(tar_lines).to include(a_string_matching(repo_name))
end end
end end
...@@ -428,7 +428,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -428,7 +428,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect(::Backup::Repositories).to receive(:new) expect(::Backup::Repositories).to receive(:new)
.with(anything, strategy: anything, max_concurrency: 5, max_storage_concurrency: 2) .with(anything, strategy: anything, max_concurrency: 5, max_storage_concurrency: 2)
.and_call_original .and_call_original
expect(::Backup::GitalyBackup).to receive(:new).with(anything, max_parallelism: 5, storage_parallelism: 2).and_call_original expect(::Backup::GitalyBackup).to receive(:new).with(anything, max_parallelism: 5, storage_parallelism: 2, incremental: false).and_call_original
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment