180 lines
6.4 KiB
Ruby
180 lines
6.4 KiB
Ruby
class SiteServerFileBackup
|
|
include Mongoid::Document
|
|
include Mongoid::Timestamps
|
|
PeriodsTypes=['daily','weekly','monthly']
|
|
DefaultConf='/etc/rsnapshot.conf'
|
|
belongs_to :site_server
|
|
field :disable, type: Boolean, default: false
|
|
field :backup_time, type: String, default: '04:15'
|
|
field :path , type: String ,default: '/home/backup/orbit'
|
|
field :period, type: Integer, default: 0 # 0 => daily , 1 => weekly , 2 => monthly
|
|
field :retain_count, type: Integer, default: 7
|
|
field :rsnapshot_conf_path, type: String, default: DefaultConf
|
|
field :backup_dir, type: String, default: '/home/{{user_name}}'
|
|
field :backup_prefix, type: String, default: 'localhost/'
|
|
field :need_rewrite, type: Boolean, default: true
|
|
|
|
before_create do
|
|
unless @skip_callback
|
|
other_rsnapshot_conf_path = self.class.where(:site_server_id=>self.site_server_id).pluck(:rsnapshot_conf_path)
|
|
if other_rsnapshot_conf_path.include?(self.rsnapshot_conf_path)
|
|
max_postfix = other_rsnapshot_conf_path.select{|s| s.start_with?('/etc/')}.map{|s| tmp = File.basename(s).split('.conf')[0].match(/\d+/); tmp ? tmp[0].to_i : 0}.max
|
|
self.rsnapshot_conf_path = "#{self.rsnapshot_conf_path.split('.conf')[0]}#{max_postfix + 1}.conf"
|
|
end
|
|
end
|
|
end
|
|
before_save do
|
|
unless @skip_callback
|
|
if self.changed?
|
|
self.need_rewrite = true
|
|
end
|
|
end
|
|
end
|
|
def to_crontab_script
|
|
# minute , hour, day(of month, 1~31), month(1~12), day(of week,0~6)
|
|
crontab_time = ['*', '*', '*', '*', '*']
|
|
time = self.backup_time.split(':').map{|s| s.sub(/0(\d)/){$1}} rescue []
|
|
crontab_time[0] = time[1].to_i.to_s rescue '0'
|
|
crontab_time[1] = time[0].to_i.to_s rescue '0'
|
|
if self.period == 1 #weekly
|
|
crontab_time[4] = '0' #every Sunday
|
|
elsif self.period == 2 #monthly
|
|
crontab_time[2] = '1' #day 1 of every month
|
|
end
|
|
extra_arg = ''
|
|
if self.rsnapshot_conf_path != DefaultConf
|
|
extra_arg = " -c #{rsnapshot_conf_path} "
|
|
end
|
|
"#{crontab_time.join(' ')} /usr/bin/rsnapshot #{extra_arg}#{period_text}"
|
|
end
|
|
def period_text
|
|
PeriodsTypes[self.period]
|
|
end
|
|
def retain_text
|
|
"retain\t#{self.period_text}\t#{self.retain_count}"
|
|
end
|
|
def override_text(contents, org_regex, new_text)
|
|
exist_flag = false
|
|
contents = contents.gsub(org_regex).with_index do |s, i|
|
|
if i == 0
|
|
exist_flag = true
|
|
"#{new_text}#{(s[-1] == "\n" ? "\n" : '')}"
|
|
else
|
|
"##{s}"
|
|
end
|
|
end
|
|
unless exist_flag
|
|
contents += "\n#{new_text}"
|
|
end
|
|
contents
|
|
end
|
|
def gsub_rsnapshot_conf(contents)
|
|
contents = self.override_text(contents, /^retain\s+[^\n]*(\n|$)/m, self.retain_text)
|
|
contents = self.override_text(contents, /^snapshot_root\s+[^\n]*(\n|$)/m, self.snapshot_root)
|
|
contents = self.override_text(contents, /^backup\s+[^\n]*(\n|$)/m, self.backup_path)
|
|
end
|
|
def backup_path
|
|
home_dir = self.backup_dir
|
|
if home_dir.include?('{{user_name}}')
|
|
user_name = self.site_server.account
|
|
home_dir = home_dir.sub('{{user_name}}', user_name)
|
|
self.backup_dir = home_dir
|
|
self.save
|
|
end
|
|
backup_text = "backup\t#{home_dir}/\t#{self.backup_prefix}"
|
|
extra_exclude_path = []
|
|
if self.class.class_variable_defined?(:@@db_backup_paths)
|
|
extra_exclude_path = @@db_backup_paths.select{|p| p.start_with?(home_dir)}
|
|
end
|
|
if self.path.start_with?(home_dir)
|
|
extra_exclude_path << self.path if extra_exclude_path.exclude?(self.path)
|
|
end
|
|
if extra_exclude_path.count != 0
|
|
tmp = []
|
|
extra_exclude_path.each do |s|
|
|
if tmp.count == 0
|
|
tmp << s
|
|
else
|
|
if tmp.exclude?(s)
|
|
s2 = File.dirname(s)
|
|
idx = tmp.index{|ss| File.dirname(ss) == s2}
|
|
if idx
|
|
tmp[idx] = s2
|
|
else
|
|
tmp << s
|
|
end
|
|
end
|
|
end
|
|
end
|
|
backup_text += "\t#{tmp.map{|p| "exclude=#{p}"}.join(',')}"
|
|
end
|
|
backup_text
|
|
end
|
|
def snapshot_root
|
|
"snapshot_root\t#{self.path}"
|
|
end
|
|
def self.read_from_crontab_line(crontab_line)
|
|
if crontab_line.include?('rsnapshot')
|
|
tmp = crontab_line.split(/\s+[^\s]*rsnapshot\s+/) # ex: ["15 4 * * *", "daily"], ["15 4 * * *", "-c /etc/rsnapshot.conf daily"]
|
|
if tmp.count == 2
|
|
crontab_time = tmp[0].split(/\s+/)
|
|
period_text = tmp[1]
|
|
rsnapshot_conf_path = DefaultConf
|
|
if period_text.start_with?('-c')
|
|
tmp2 = period_text.split(/\s+/)
|
|
if tmp2.count == 3
|
|
rsnapshot_conf_path = tmp2[1]
|
|
period_text = tmp2[2]
|
|
else
|
|
period_text = tmp2.last
|
|
end
|
|
end
|
|
if PeriodsTypes.include?(period_text)
|
|
period = PeriodsTypes.index(period_text)
|
|
else
|
|
period = 0
|
|
end
|
|
time = "#{crontab_time[1].rjust(2, "0")}:#{crontab_time[0].rjust(2, "0")}"
|
|
return [time, rsnapshot_conf_path, period]
|
|
else
|
|
return nil
|
|
end
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
def self.clean_crontab_setting(crontab_lines_str)
|
|
crontab_lines = crontab_lines_str.split("\n")
|
|
crontab_lines_str = crontab_lines.map do |crontab_line|
|
|
if crontab_line.include?('rsnapshot')
|
|
nil
|
|
else
|
|
crontab_line
|
|
end
|
|
end.compact.join("\n")
|
|
end
|
|
def self.init_class_variables(site_server)
|
|
@@db_backup_paths = SiteServerDbBackup.where(:site_server_id=> site_server.id, :disable=>false).pluck(:path)
|
|
end
|
|
def self.write_crontab_setting(site_server, crontab_lines_str)
|
|
new_crontab_lines = self.where(:site_server_id=> site_server.id, :disable=>false).flat_map{|file_backup| file_backup.to_crontab_script.split("\n")}
|
|
crontab_lines = crontab_lines_str.split("\n")
|
|
exists_indices = new_crontab_lines.map do |new_crontab_line|
|
|
match_reg = ::Regexp.new(new_crontab_line.gsub(/\s+/, '\s+'))
|
|
crontab_lines.index{|l| l.match(match_reg)}
|
|
end
|
|
crontab_lines = crontab_lines.map.with_index do |crontab_line, i|
|
|
if crontab_line.include?('rsnapshot') && exists_indices.exclude?(i)
|
|
nil
|
|
else
|
|
crontab_line
|
|
end
|
|
end
|
|
exists_indices.each_with_index do |idx, i|
|
|
if idx.nil?
|
|
crontab_lines << new_crontab_lines[i]
|
|
end
|
|
end
|
|
crontab_lines_str = crontab_lines.compact.join("\n")
|
|
end
|
|
end |