gitlab-org--gitlab-foss/lib/backup/files.rb
Drew Blessing d6584c94a4 # This is a combination of 2 commits.
# This is the 1st commit message:

Add `copy` backup strategy to combat file changed errors

The backup Rake task used to stream data directly from the live
data directory into the backup. Under many circumstances this worked
OK. However, really active instances would experience a 'file changed
as we read it' error - especially with data like the registry. This
now copies the data first, then compresses it. It will take a bit
more disk space while the backup is in progress, but it's a
necessary thing.

# The commit message #2 will be skipped:

#	Add env var
2017-02-21 16:03:54 -06:00

55 lines
1.8 KiB
Ruby

require 'open3'
module Backup
class Files
attr_reader :name, :app_files_dir, :backup_tarball, :files_parent_dir
def initialize(name, app_files_dir)
@name = name
@app_files_dir = File.realpath(app_files_dir)
@files_parent_dir = File.realpath(File.join(@app_files_dir, '..'))
@backup_files_dir = File.join(Gitlab.config.backup.path, File.basename(@app_files_dir) )
@backup_tarball = File.join(Gitlab.config.backup.path, name + '.tar.gz')
end
# Copy files from public/files to backup/files
def dump
FileUtils.mkdir_p(Gitlab.config.backup.path)
FileUtils.rm_f(backup_tarball)
if ENV['STRATEGY'] == 'copy'
cmd = %W(cp -a #{app_files_dir} #{Gitlab.config.backup.path})
output, status = Gitlab::Popen.popen(cmd)
unless status.zero?
puts output
abort 'Backup failed'
end
run_pipeline!([%W(tar -C #{@backup_files_dir} -cf - .), %W(gzip -c -1)], out: [backup_tarball, 'w', 0600])
FileUtils.rm_rf(@backup_files_dir)
else
run_pipeline!([%W(tar -C #{app_files_dir} -cf - .), %W(gzip -c -1)], out: [backup_tarball, 'w', 0600])
end
end
def restore
backup_existing_files_dir
create_files_dir
run_pipeline!([%W(gzip -cd), %W(tar -C #{app_files_dir} -xf -)], in: backup_tarball)
end
def backup_existing_files_dir
timestamped_files_path = File.join(files_parent_dir, "#{name}.#{Time.now.to_i}")
if File.exist?(app_files_dir)
FileUtils.mv(app_files_dir, File.expand_path(timestamped_files_path))
end
end
def run_pipeline!(cmd_list, options={})
status_list = Open3.pipeline(*cmd_list, options)
abort 'Backup failed' unless status_list.compact.all?(&:success?)
end
end
end