Class: Backup::Manager

Inherits:
Object
  • Object
show all
Defined in:
lib/backup/manager.rb

Constant Summary collapse

ARCHIVES_TO_BACKUP =
%w[uploads builds artifacts pages lfs registry].freeze
FOLDERS_TO_BACKUP =
%w[repositories db].freeze
FILE_NAME_SUFFIX =
'_gitlab_backup.tar'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(progress) ⇒ Manager

Returns a new instance of Manager.


11
12
13
# File 'lib/backup/manager.rb', line 11

def initialize(progress)
  @progress = progress
end

Instance Attribute Details

#progressObject (readonly)

Returns the value of attribute progress


9
10
11
# File 'lib/backup/manager.rb', line 9

def progress
  @progress
end

Instance Method Details

#cleanupObject


60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/backup/manager.rb', line 60

def cleanup
  progress.print "Deleting tmp directories ... "

  backup_contents.each do |dir|
    next unless File.exist?(File.join(backup_path, dir))

    if FileUtils.rm_rf(File.join(backup_path, dir))
      progress.puts "done".color(:green)
    else
      puts "deleting tmp directory '#{dir}' failed".color(:red)
      raise Backup::Error, 'Backup failed'
    end
  end
end

#packObject


26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/backup/manager.rb', line 26

def pack
  Dir.chdir(backup_path) do
    # create archive
    progress.print "Creating backup archive: #{tar_file} ... "
    # Set file permissions on open to prevent chmod races.
    tar_system_options = { out: [tar_file, 'w', Gitlab.config.backup.archive_permissions] }
    if Kernel.system('tar', '-cf', '-', *backup_contents, tar_system_options)
      progress.puts "done".color(:green)
    else
      puts "creating archive #{tar_file} failed".color(:red)
      raise Backup::Error, 'Backup failed'
    end
  end
end

#remove_oldObject


75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/backup/manager.rb', line 75

def remove_old
  # delete backups
  progress.print "Deleting old backups ... "
  keep_time = Gitlab.config.backup.keep_time.to_i

  if keep_time > 0
    removed = 0

    Dir.chdir(backup_path) do
      backup_file_list.each do |file|
        # For backward compatibility, there are 3 names the backups can have:
        # - 1495527122_gitlab_backup.tar
        # - 1495527068_2017_05_23_gitlab_backup.tar
        # - 1495527097_2017_05_23_9.3.0-pre_gitlab_backup.tar
        next unless file =~ /^(\d{10})(?:_\d{4}_\d{2}_\d{2}(_\d+\.\d+\.\d+((-|\.)(pre|rc\d))?(-ee)?)?)?_gitlab_backup\.tar$/

        timestamp = Regexp.last_match(1).to_i

        if Time.at(timestamp) < (Time.now - keep_time)
          begin
            FileUtils.rm(file)
            removed += 1
          rescue => e
            progress.puts "Deleting #{file} failed: #{e.message}".color(:red)
          end
        end
      end
    end

    progress.puts "done. (#{removed} removed)".color(:green)
  else
    progress.puts "skipping".color(:yellow)
  end
end

#skipped?(item) ⇒ Boolean

Returns:

  • (Boolean)

176
177
178
# File 'lib/backup/manager.rb', line 176

def skipped?(item)
  settings[:skipped] && settings[:skipped].include?(item) || disabled_features.include?(item)
end

#tar_versionObject


171
172
173
174
# File 'lib/backup/manager.rb', line 171

def tar_version
  tar_version, _ = Gitlab::Popen.popen(%w(tar --version))
  tar_version.dup.force_encoding('locale').split("\n").first
end

#unpackObject


127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/backup/manager.rb', line 127

def unpack
  if ENV['BACKUP'].blank? && non_tarred_backup?
    progress.puts "Non tarred backup found in #{backup_path}, using that"

    return false
  end

  Dir.chdir(backup_path) do
    # check for existing backups in the backup dir
    if backup_file_list.empty?
      progress.puts "No backups found in #{backup_path}"
      progress.puts "Please make sure that file name ends with #{FILE_NAME_SUFFIX}"
      exit 1
    elsif backup_file_list.many? && ENV["BACKUP"].nil?
      progress.puts 'Found more than one backup:'
      # print list of available backups
      progress.puts " " + available_timestamps.join("\n ")
      progress.puts 'Please specify which one you want to restore:'
      progress.puts 'rake gitlab:backup:restore BACKUP=timestamp_of_backup'
      exit 1
    end

    tar_file = if ENV['BACKUP'].present?
                 File.basename(ENV['BACKUP']) + FILE_NAME_SUFFIX
               else
                 backup_file_list.first
               end

    unless File.exist?(tar_file)
      progress.puts "The backup file #{tar_file} does not exist!"
      exit 1
    end

    progress.print 'Unpacking backup ... '

    if Kernel.system(*%W(tar -xf #{tar_file}))
      progress.puts 'done'.color(:green)
    else
      progress.puts 'unpacking backup failed'.color(:red)
      exit 1
    end
  end
end

#uploadObject


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/backup/manager.rb', line 41

def upload
  progress.print "Uploading backup archive to remote storage #{remote_directory} ... "

  connection_settings = Gitlab.config.backup.upload.connection
  if connection_settings.blank?
    progress.puts "skipped".color(:yellow)
    return
  end

  directory = connect_to_remote_directory(Gitlab.config.backup.upload)

  if directory.files.create(create_attributes)
    progress.puts "done".color(:green)
  else
    puts "uploading backup to #{remote_directory} failed".color(:red)
    raise Backup::Error, 'Backup failed'
  end
end

#verify_backup_versionObject


110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/backup/manager.rb', line 110

def verify_backup_version
  Dir.chdir(backup_path) do
    # restoring mismatching backups can lead to unexpected problems
    if settings[:gitlab_version] != Gitlab::VERSION
      progress.puts(<<~HEREDOC.color(:red))
        GitLab version mismatch:
          Your current GitLab version (#{Gitlab::VERSION}) differs from the GitLab version in the backup!
          Please switch to the following version and try again:
          version: #{settings[:gitlab_version]}
      HEREDOC
      progress.puts
      progress.puts "Hint: git checkout v#{settings[:gitlab_version]}"
      exit 1
    end
  end
end

#write_infoObject


15
16
17
18
19
20
21
22
23
24
# File 'lib/backup/manager.rb', line 15

def write_info
  # Make sure there is a connection
  ActiveRecord::Base.connection.reconnect!

  Dir.chdir(backup_path) do
    File.open("#{backup_path}/backup_information.yml", "w+") do |file|
      file << backup_information.to_yaml.gsub(/^---\n/, '')
    end
  end
end