Files
gitlab-foss/lib/tasks/gitlab/backup.rb
2025-04-16 12:11:00 +00:00

116 lines
3.4 KiB
Ruby

# frozen_string_literal: true
module Tasks
module Gitlab
module Backup
PID = Process.pid.freeze
PID_FILE = "#{Rails.application.root}/tmp/backup_restore.pid".freeze
def self.create_backup
lock_backup do
::Gitlab::TaskHelpers.warn_user_is_not_gitlab
success = ::Backup::Manager.new(backup_progress).create
exit 1 unless success # rubocop:disable Rails/Exit -- Rake task helper
end
end
def self.restore_backup
lock_backup do
::Gitlab::TaskHelpers.warn_user_is_not_gitlab
::Backup::Manager.new(backup_progress).restore
end
end
# Verify backup file to ensure it is compatible with current GitLab's version
def self.verify_backup
lock_backup do
::Backup::Manager.new(backup_progress).verify!
end
end
def self.create_task(task_id)
lock_backup do
backup_manager = ::Backup::Manager.new(backup_progress)
task = backup_manager.find_task(task_id)
success = backup_manager.run_create_task(task)
exit 1 unless success # rubocop:disable Rails/Exit -- Rake task helper
end
end
def self.restore_task(task_id)
lock_backup do
backup_manager = ::Backup::Manager.new(backup_progress)
task = backup_manager.find_task(task_id)
backup_manager.run_restore_task(task)
end
end
# A Backup only includes regular repositories, after a restore we need to reinitialize their respective pools.
# This process is done by changing its original state to 'none' and scheduling its creation process again
def self.reset_pool_repositories!
::Backup::Restore::PoolRepositories.reinitialize_pools! do |pool_result|
puts pool_result.to_h.to_json
end
end
def self.backup_progress
# We need an object we can say 'puts' and 'print' to; let's use a StringIO.
return StringIO.new if ENV['CRON']
$stdout
end
def self.lock_backup
File.open(PID_FILE, File::RDWR | File::CREAT) do |f|
f.flock(File::LOCK_EX)
file_content = f.read
read_pid(file_content) unless file_content.blank?
f.rewind
f.write(PID)
f.flush
ensure
f.flock(File::LOCK_UN)
end
begin
yield
ensure
backup_progress.puts(
"#{Time.current} " +
Rainbow('-- Deleting backup and restore PID file at [').blue +
PID_FILE.to_s + Rainbow('] ... ').blue +
Rainbow('done').green
)
File.delete(PID_FILE)
end
end
def self.read_pid(file_content)
Process.getpgid(file_content.to_i)
backup_progress.puts(Rainbow(<<~MESSAGE).red)
Backup and restore in progress:
There is a backup and restore task in progress (PID #{file_content}).
Try to run the current task once the previous one ends.
MESSAGE
exit 1 # rubocop:disable Rails/Exit -- Rake task helper
rescue Errno::ESRCH
backup_progress.puts(Rainbow(<<~MESSAGE).blue)
The PID file #{PID_FILE} exists and contains #{file_content}, but the process is not running.
The PID file will be rewritten with the current process ID #{PID}.
MESSAGE
end
private_class_method :backup_progress, :lock_backup, :read_pid
end
end
end