backup 4.4.1 → 5.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/LICENSE +19 -0
- data/README.md +1 -1
- data/lib/backup.rb +74 -78
- data/lib/backup/archive.rb +31 -32
- data/lib/backup/binder.rb +2 -6
- data/lib/backup/cleaner.rb +14 -18
- data/lib/backup/cli.rb +104 -108
- data/lib/backup/cloud_io/base.rb +4 -7
- data/lib/backup/cloud_io/cloud_files.rb +60 -62
- data/lib/backup/cloud_io/s3.rb +69 -76
- data/lib/backup/compressor/base.rb +4 -7
- data/lib/backup/compressor/bzip2.rb +3 -7
- data/lib/backup/compressor/custom.rb +2 -6
- data/lib/backup/compressor/gzip.rb +16 -17
- data/lib/backup/config.rb +17 -18
- data/lib/backup/config/dsl.rb +16 -17
- data/lib/backup/config/helpers.rb +10 -16
- data/lib/backup/database/base.rb +22 -21
- data/lib/backup/database/mongodb.rb +36 -37
- data/lib/backup/database/mysql.rb +40 -41
- data/lib/backup/database/openldap.rb +8 -10
- data/lib/backup/database/postgresql.rb +29 -30
- data/lib/backup/database/redis.rb +27 -30
- data/lib/backup/database/riak.rb +15 -18
- data/lib/backup/database/sqlite.rb +4 -6
- data/lib/backup/encryptor/base.rb +2 -4
- data/lib/backup/encryptor/gpg.rb +49 -59
- data/lib/backup/encryptor/open_ssl.rb +11 -14
- data/lib/backup/errors.rb +7 -12
- data/lib/backup/logger.rb +16 -18
- data/lib/backup/logger/console.rb +5 -8
- data/lib/backup/logger/fog_adapter.rb +2 -6
- data/lib/backup/logger/logfile.rb +10 -12
- data/lib/backup/logger/syslog.rb +2 -4
- data/lib/backup/model.rb +75 -40
- data/lib/backup/notifier/base.rb +24 -26
- data/lib/backup/notifier/campfire.rb +9 -11
- data/lib/backup/notifier/command.rb +0 -3
- data/lib/backup/notifier/datadog.rb +9 -12
- data/lib/backup/notifier/flowdock.rb +13 -17
- data/lib/backup/notifier/hipchat.rb +11 -13
- data/lib/backup/notifier/http_post.rb +11 -14
- data/lib/backup/notifier/mail.rb +44 -47
- data/lib/backup/notifier/nagios.rb +5 -9
- data/lib/backup/notifier/pagerduty.rb +10 -12
- data/lib/backup/notifier/prowl.rb +15 -15
- data/lib/backup/notifier/pushover.rb +7 -10
- data/lib/backup/notifier/ses.rb +34 -16
- data/lib/backup/notifier/slack.rb +39 -40
- data/lib/backup/notifier/twitter.rb +2 -5
- data/lib/backup/notifier/zabbix.rb +11 -14
- data/lib/backup/package.rb +5 -9
- data/lib/backup/packager.rb +16 -17
- data/lib/backup/pipeline.rb +17 -21
- data/lib/backup/splitter.rb +8 -11
- data/lib/backup/storage/base.rb +5 -8
- data/lib/backup/storage/cloud_files.rb +21 -23
- data/lib/backup/storage/cycler.rb +10 -15
- data/lib/backup/storage/dropbox.rb +15 -21
- data/lib/backup/storage/ftp.rb +8 -10
- data/lib/backup/storage/local.rb +5 -8
- data/lib/backup/storage/qiniu.rb +8 -8
- data/lib/backup/storage/rsync.rb +24 -26
- data/lib/backup/storage/s3.rb +27 -28
- data/lib/backup/storage/scp.rb +10 -12
- data/lib/backup/storage/sftp.rb +10 -12
- data/lib/backup/syncer/base.rb +5 -8
- data/lib/backup/syncer/cloud/base.rb +27 -30
- data/lib/backup/syncer/cloud/cloud_files.rb +16 -18
- data/lib/backup/syncer/cloud/local_file.rb +5 -8
- data/lib/backup/syncer/cloud/s3.rb +23 -24
- data/lib/backup/syncer/rsync/base.rb +6 -10
- data/lib/backup/syncer/rsync/local.rb +1 -5
- data/lib/backup/syncer/rsync/pull.rb +6 -10
- data/lib/backup/syncer/rsync/push.rb +18 -22
- data/lib/backup/template.rb +9 -14
- data/lib/backup/utilities.rb +82 -69
- data/lib/backup/version.rb +1 -3
- metadata +100 -660
@@ -1,9 +1,6 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module Backup
|
4
2
|
module Encryptor
|
5
3
|
class OpenSSL < Base
|
6
|
-
|
7
4
|
##
|
8
5
|
# The password that'll be used to encrypt the backup. This
|
9
6
|
# password will be required to decrypt the backup later on.
|
@@ -42,7 +39,7 @@ module Backup
|
|
42
39
|
# so that any clean-up may be performed after the yield.
|
43
40
|
def encrypt_with
|
44
41
|
log!
|
45
|
-
yield "#{
|
42
|
+
yield "#{utility(:openssl)} #{options}", ".enc"
|
46
43
|
end
|
47
44
|
|
48
45
|
private
|
@@ -59,19 +56,19 @@ module Backup
|
|
59
56
|
# Always sets a password option, if even no password is given,
|
60
57
|
# but will prefer the password_file option if both are given.
|
61
58
|
def options
|
62
|
-
opts = [
|
63
|
-
opts <<
|
64
|
-
opts <<
|
59
|
+
opts = ["aes-256-cbc"]
|
60
|
+
opts << "-base64" if @base64
|
61
|
+
opts << "-salt" if @salt
|
65
62
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
63
|
+
opts <<
|
64
|
+
if @password_file.to_s.empty?
|
65
|
+
"-k #{Shellwords.escape(@password)}"
|
66
|
+
else
|
67
|
+
"-pass file:#{@password_file}"
|
68
|
+
end
|
71
69
|
|
72
|
-
opts.join(
|
70
|
+
opts.join(" ")
|
73
71
|
end
|
74
|
-
|
75
72
|
end
|
76
73
|
end
|
77
74
|
end
|
data/lib/backup/errors.rb
CHANGED
@@ -1,29 +1,25 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module Backup
|
4
|
-
|
5
2
|
# Provides cascading errors with formatted messages.
|
6
3
|
# See the specs for details.
|
7
4
|
module NestedExceptions
|
8
|
-
|
9
5
|
def self.included(klass)
|
10
|
-
klass.extend
|
6
|
+
klass.extend(Module.new do
|
11
7
|
def wrap(wrapped_exception, msg = nil)
|
12
8
|
new(msg, wrapped_exception)
|
13
9
|
end
|
14
|
-
|
10
|
+
end)
|
15
11
|
end
|
16
12
|
|
17
13
|
def initialize(obj = nil, wrapped_exception = nil)
|
18
14
|
@wrapped_exception = wrapped_exception
|
19
|
-
msg = (obj.respond_to?(:to_str) ? obj.to_str : obj.to_s)
|
20
|
-
|
21
|
-
msg = clean_name(self.class.name) + (msg.empty? ?
|
15
|
+
msg = (obj.respond_to?(:to_str) ? obj.to_str : obj.to_s)
|
16
|
+
.gsub(/^ */, " ").strip
|
17
|
+
msg = clean_name(self.class.name) + (msg.empty? ? "" : ": #{msg}")
|
22
18
|
|
23
19
|
if wrapped_exception
|
24
20
|
msg << "\n--- Wrapped Exception ---\n"
|
25
21
|
class_name = clean_name(wrapped_exception.class.name)
|
26
|
-
msg << class_name +
|
22
|
+
msg << class_name + ": " unless
|
27
23
|
wrapped_exception.message.start_with? class_name
|
28
24
|
msg << wrapped_exception.message
|
29
25
|
end
|
@@ -43,9 +39,8 @@ module Backup
|
|
43
39
|
private
|
44
40
|
|
45
41
|
def clean_name(name)
|
46
|
-
name.sub(/^Backup::/,
|
42
|
+
name.sub(/^Backup::/, "")
|
47
43
|
end
|
48
|
-
|
49
44
|
end
|
50
45
|
|
51
46
|
class Error < StandardError
|
data/lib/backup/logger.rb
CHANGED
@@ -1,13 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require 'backup/logger/syslog'
|
6
|
-
require 'backup/logger/fog_adapter'
|
1
|
+
require "backup/logger/console"
|
2
|
+
require "backup/logger/logfile"
|
3
|
+
require "backup/logger/syslog"
|
4
|
+
require "backup/logger/fog_adapter"
|
7
5
|
|
8
6
|
module Backup
|
9
7
|
class Logger
|
10
|
-
|
11
8
|
class Config
|
12
9
|
class Logger < Struct.new(:class, :options)
|
13
10
|
def enabled?
|
@@ -44,22 +41,22 @@ module Backup
|
|
44
41
|
# [YYYY/MM/DD HH:MM:SS][level] message line text
|
45
42
|
def formatted_lines
|
46
43
|
timestamp = time.strftime("%Y/%m/%d %H:%M:%S")
|
47
|
-
lines.map {|line| "[#{
|
44
|
+
lines.map { |line| "[#{timestamp}][#{level}] #{line}" }
|
48
45
|
end
|
49
46
|
|
50
47
|
def matches?(ignores)
|
51
48
|
text = lines.join("\n")
|
52
|
-
ignores.any?
|
49
|
+
ignores.any? do |obj|
|
53
50
|
obj.is_a?(Regexp) ? text.match(obj) : text.include?(obj)
|
54
|
-
|
51
|
+
end
|
55
52
|
end
|
56
53
|
end
|
57
54
|
|
58
55
|
class << self
|
59
56
|
extend Forwardable
|
60
57
|
def_delegators :logger,
|
61
|
-
|
62
|
-
|
58
|
+
:start!, :abort!, :info, :warn, :error,
|
59
|
+
:messages, :has_warnings?, :has_errors?
|
63
60
|
|
64
61
|
##
|
65
62
|
# Allows the Logger to be configured.
|
@@ -137,9 +134,9 @@ module Backup
|
|
137
134
|
# Sends a message to the Logger using the specified log level.
|
138
135
|
# +obj+ may be any Object that responds to #to_s (i.e. an Exception)
|
139
136
|
[:info, :warn, :error].each do |level|
|
140
|
-
define_method level
|
137
|
+
define_method level do |obj|
|
141
138
|
MUTEX.synchronize { log(obj, level) }
|
142
|
-
|
139
|
+
end
|
143
140
|
end
|
144
141
|
|
145
142
|
##
|
@@ -169,7 +166,7 @@ module Backup
|
|
169
166
|
@loggers << logger.class.new(logger.options) if logger.enabled?
|
170
167
|
end
|
171
168
|
messages.each do |message|
|
172
|
-
@loggers.each {|logger| logger.log(message) }
|
169
|
+
@loggers.each { |logger| logger.log(message) }
|
173
170
|
end
|
174
171
|
end
|
175
172
|
|
@@ -187,13 +184,14 @@ module Backup
|
|
187
184
|
def log(obj, level)
|
188
185
|
message = Message.new(Time.now.utc, level, obj.to_s.split("\n"))
|
189
186
|
|
190
|
-
|
191
|
-
|
187
|
+
if message.level == :warn && message.matches?(@config.ignores)
|
188
|
+
message.level = :info
|
189
|
+
end
|
192
190
|
@has_warnings ||= message.level == :warn
|
193
191
|
@has_errors ||= message.level == :error
|
194
192
|
|
195
193
|
messages << message
|
196
|
-
@loggers.each {|logger| logger.log(message) }
|
194
|
+
@loggers.each { |logger| logger.log(message) }
|
197
195
|
end
|
198
196
|
end
|
199
197
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module Backup
|
4
2
|
class Logger
|
5
3
|
class Console
|
@@ -30,22 +28,21 @@ module Backup
|
|
30
28
|
end
|
31
29
|
|
32
30
|
COLORS = {
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
31
|
+
info: "\e[32m%s\e[0m", # green
|
32
|
+
warn: "\e[33m%s\e[0m", # yellow
|
33
|
+
error: "\e[31m%s\e[0m" # red
|
36
34
|
}
|
37
35
|
|
38
|
-
def initialize(
|
36
|
+
def initialize(_options = nil)
|
39
37
|
$stdout.sync = $stderr.sync = true
|
40
38
|
end
|
41
39
|
|
42
40
|
def log(message)
|
43
41
|
io = message.level == :info ? $stdout : $stderr
|
44
42
|
lines = message.formatted_lines
|
45
|
-
lines.map! {|line| COLORS[message.level] % line } if io.tty?
|
43
|
+
lines.map! { |line| COLORS[message.level] % line } if io.tty?
|
46
44
|
io.puts lines
|
47
45
|
end
|
48
|
-
|
49
46
|
end
|
50
47
|
end
|
51
48
|
end
|
@@ -1,14 +1,11 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
# require only the logger
|
4
|
-
require
|
5
|
-
require
|
2
|
+
require "formatador"
|
3
|
+
require "fog/core/logger"
|
6
4
|
|
7
5
|
module Backup
|
8
6
|
class Logger
|
9
7
|
module FogAdapter
|
10
8
|
class << self
|
11
|
-
|
12
9
|
# Logged as :info so these won't generate warnings.
|
13
10
|
# This is mostly to keep STDOUT clean and to provide
|
14
11
|
# supplemental messages for our own warnings.
|
@@ -20,7 +17,6 @@ module Backup
|
|
20
17
|
def tty?
|
21
18
|
false
|
22
19
|
end
|
23
|
-
|
24
20
|
end
|
25
21
|
end
|
26
22
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module Backup
|
4
2
|
class Logger
|
5
3
|
class Logfile
|
@@ -60,7 +58,7 @@ module Backup
|
|
60
58
|
|
61
59
|
def initialize
|
62
60
|
@enabled = true
|
63
|
-
@log_path =
|
61
|
+
@log_path = ""
|
64
62
|
@max_bytes = 500_000
|
65
63
|
end
|
66
64
|
|
@@ -84,7 +82,7 @@ module Backup
|
|
84
82
|
end
|
85
83
|
|
86
84
|
def log(message)
|
87
|
-
File.open(@logfile,
|
85
|
+
File.open(@logfile, "a") { |f| f.puts message.formatted_lines }
|
88
86
|
end
|
89
87
|
|
90
88
|
private
|
@@ -95,17 +93,17 @@ module Backup
|
|
95
93
|
def setup_logfile
|
96
94
|
# strip any trailing '/' in case the user supplied this as part of
|
97
95
|
# an absolute path, so we can match it against File.expand_path()
|
98
|
-
path = @options.log_path.chomp(
|
96
|
+
path = @options.log_path.chomp("/")
|
99
97
|
if path.empty?
|
100
|
-
path = File.join(Backup::Config.root_path,
|
98
|
+
path = File.join(Backup::Config.root_path, "log")
|
101
99
|
elsif path != File.expand_path(path)
|
102
100
|
path = File.join(Backup::Config.root_path, path)
|
103
101
|
end
|
104
102
|
FileUtils.mkdir_p(path)
|
105
|
-
log_file = @options.log_file ||
|
103
|
+
log_file = @options.log_file || "backup.log"
|
106
104
|
path = File.join(path, log_file)
|
107
105
|
if File.exist?(path) && !File.writable?(path)
|
108
|
-
raise Error, "Log File at '#{
|
106
|
+
raise Error, "Log File at '#{path}' is not writable"
|
109
107
|
end
|
110
108
|
path
|
111
109
|
end
|
@@ -116,16 +114,16 @@ module Backup
|
|
116
114
|
return unless File.exist?(@logfile)
|
117
115
|
|
118
116
|
if File.stat(@logfile).size > @options.max_bytes
|
119
|
-
FileUtils.cp(@logfile, @logfile +
|
120
|
-
File.open(@logfile +
|
121
|
-
File.open(@logfile,
|
117
|
+
FileUtils.cp(@logfile, @logfile + "~")
|
118
|
+
File.open(@logfile + "~", "r") do |io_in|
|
119
|
+
File.open(@logfile, "w") do |io_out|
|
122
120
|
io_in.seek(-@options.max_bytes, IO::SEEK_END) && io_in.gets
|
123
121
|
while line = io_in.gets
|
124
122
|
io_out.puts line
|
125
123
|
end
|
126
124
|
end
|
127
125
|
end
|
128
|
-
FileUtils.rm_f(@logfile +
|
126
|
+
FileUtils.rm_f(@logfile + "~")
|
129
127
|
end
|
130
128
|
end
|
131
129
|
end
|
data/lib/backup/logger/syslog.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module Backup
|
4
2
|
class Logger
|
5
3
|
class Syslog
|
@@ -81,7 +79,7 @@ module Backup
|
|
81
79
|
|
82
80
|
def initialize
|
83
81
|
@enabled = false
|
84
|
-
@ident =
|
82
|
+
@ident = "backup"
|
85
83
|
@options = ::Syslog::LOG_PID
|
86
84
|
@facility = ::Syslog::LOG_LOCAL0
|
87
85
|
@info = ::Syslog::LOG_INFO
|
@@ -108,7 +106,7 @@ module Backup
|
|
108
106
|
def log(message)
|
109
107
|
level = @options.send(message.level)
|
110
108
|
::Syslog.open(@options.ident, @options.options, @options.facility) do |s|
|
111
|
-
message.lines.each {|line| s.log(level,
|
109
|
+
message.lines.each { |line| s.log(level, "%s", line) }
|
112
110
|
end
|
113
111
|
end
|
114
112
|
end
|
data/lib/backup/model.rb
CHANGED
@@ -1,10 +1,20 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module Backup
|
4
2
|
class Model
|
5
3
|
class Error < Backup::Error; end
|
6
4
|
class FatalError < Backup::FatalError; end
|
7
5
|
|
6
|
+
DEPRECATED_MODULES = %w[
|
7
|
+
Campfire
|
8
|
+
CloudFiles
|
9
|
+
FTP
|
10
|
+
Nagios
|
11
|
+
OpenLDAP
|
12
|
+
Prowl
|
13
|
+
Riak
|
14
|
+
Twitter
|
15
|
+
Zabbix
|
16
|
+
].freeze
|
17
|
+
|
8
18
|
class << self
|
9
19
|
##
|
10
20
|
# The Backup::Model.all class method keeps track of all the models
|
@@ -18,11 +28,11 @@ module Backup
|
|
18
28
|
# Return an Array of Models matching the given +trigger+.
|
19
29
|
def find_by_trigger(trigger)
|
20
30
|
trigger = trigger.to_s
|
21
|
-
if trigger.include?(
|
31
|
+
if trigger.include?("*")
|
22
32
|
regex = /^#{ trigger.gsub('*', '(.*)') }$/
|
23
|
-
all.select {|model| regex =~ model.trigger }
|
33
|
+
all.select { |model| regex =~ model.trigger }
|
24
34
|
else
|
25
|
-
all.select {|model| trigger == model.trigger }
|
35
|
+
all.select { |model| trigger == model.trigger }
|
26
36
|
end
|
27
37
|
end
|
28
38
|
|
@@ -128,7 +138,7 @@ module Backup
|
|
128
138
|
|
129
139
|
# trigger all defined databases to generate their #dump_filename
|
130
140
|
# so warnings may be logged if `backup perform --check` is used
|
131
|
-
databases.each {|db| db.send(:dump_filename) }
|
141
|
+
databases.each { |db| db.send(:dump_filename) }
|
132
142
|
|
133
143
|
Model.all << self
|
134
144
|
end
|
@@ -142,26 +152,48 @@ module Backup
|
|
142
152
|
##
|
143
153
|
# Adds an Database. Multiple Databases may be added to the model.
|
144
154
|
def database(name, database_id = nil, &block)
|
145
|
-
|
146
|
-
|
155
|
+
dsl_name = dsl_const_name(name)
|
156
|
+
if deprecated_module? dsl_name
|
157
|
+
Logger.warn "The Backup database \"#{dsl_name}\" is " \
|
158
|
+
"scheduled to be deprecated. If you're using this feature, " \
|
159
|
+
"please see: https://github.com/backup/backup/issues/851"
|
160
|
+
end
|
161
|
+
@databases << get_class_from_scope(Database, name)
|
162
|
+
.new(self, database_id, &block)
|
147
163
|
end
|
148
164
|
|
149
165
|
##
|
150
166
|
# Adds an Storage. Multiple Storages may be added to the model.
|
151
167
|
def store_with(name, storage_id = nil, &block)
|
152
|
-
|
153
|
-
|
168
|
+
dsl_name = dsl_const_name(name)
|
169
|
+
if deprecated_module? dsl_name
|
170
|
+
Logger.warn "The Backup storage \"#{dsl_name}\" is " \
|
171
|
+
"scheduled to be deprecated. If you're using this feature, " \
|
172
|
+
"please see: https://github.com/backup/backup/issues/851"
|
173
|
+
end
|
174
|
+
@storages << get_class_from_scope(Storage, name)
|
175
|
+
.new(self, storage_id, &block)
|
154
176
|
end
|
155
177
|
|
156
178
|
##
|
157
179
|
# Adds an Syncer. Multiple Syncers may be added to the model.
|
158
180
|
def sync_with(name, syncer_id = nil, &block)
|
181
|
+
dsl_name = dsl_const_name(name)
|
182
|
+
Logger.warn "The Backup syncer \"#{dsl_name}\" is " \
|
183
|
+
"scheduled to be deprecated. If you're using this feature, " \
|
184
|
+
"please see: https://github.com/backup/backup/issues/851"
|
159
185
|
@syncers << get_class_from_scope(Syncer, name).new(syncer_id, &block)
|
160
186
|
end
|
161
187
|
|
162
188
|
##
|
163
189
|
# Adds an Notifier. Multiple Notifiers may be added to the model.
|
164
190
|
def notify_by(name, &block)
|
191
|
+
dsl_name = dsl_const_name(name)
|
192
|
+
if deprecated_module? dsl_name
|
193
|
+
Logger.warn "The Backup notifier \"#{dsl_name}\" is " \
|
194
|
+
"scheduled to be deprecated. If you're using this feature, " \
|
195
|
+
"please see: https://github.com/backup/backup/issues/851"
|
196
|
+
end
|
165
197
|
@notifiers << get_class_from_scope(Notifier, name).new(self, &block)
|
166
198
|
end
|
167
199
|
|
@@ -270,14 +302,11 @@ module Backup
|
|
270
302
|
end
|
271
303
|
|
272
304
|
syncers.each(&:perform!)
|
273
|
-
|
274
305
|
rescue Interrupt
|
275
306
|
@interrupted = true
|
276
307
|
raise
|
277
|
-
|
278
308
|
rescue Exception => err
|
279
309
|
@exception = err
|
280
|
-
|
281
310
|
ensure
|
282
311
|
unless @interrupted
|
283
312
|
set_exit_status
|
@@ -296,14 +325,22 @@ module Backup
|
|
296
325
|
|
297
326
|
private
|
298
327
|
|
328
|
+
def dsl_const_name(name)
|
329
|
+
name.to_s.sub "Backup::Config::DSL::", ""
|
330
|
+
end
|
331
|
+
|
332
|
+
def deprecated_module?(name)
|
333
|
+
DEPRECATED_MODULES.include? name
|
334
|
+
end
|
335
|
+
|
299
336
|
##
|
300
337
|
# Returns an array of procedures that will be performed if any
|
301
338
|
# Archives or Databases are configured for the model.
|
302
339
|
def procedures
|
303
340
|
return [] unless databases.any? || archives.any?
|
304
341
|
|
305
|
-
[
|
306
|
-
|
342
|
+
[-> { prepare! }, databases, archives,
|
343
|
+
-> { package! }, -> { store! }, -> { clean! }]
|
307
344
|
end
|
308
345
|
|
309
346
|
##
|
@@ -341,8 +378,8 @@ module Backup
|
|
341
378
|
|
342
379
|
if first_exception
|
343
380
|
other_exceptions.each do |exception|
|
344
|
-
|
345
|
-
|
381
|
+
Logger.error exception.to_s
|
382
|
+
Logger.error exception.backtrace.join('\n')
|
346
383
|
end
|
347
384
|
raise first_exception
|
348
385
|
else
|
@@ -375,8 +412,8 @@ module Backup
|
|
375
412
|
#
|
376
413
|
def get_class_from_scope(scope, name)
|
377
414
|
klass = scope
|
378
|
-
name = name.to_s.sub(/^Backup::Config::DSL::/,
|
379
|
-
name.split(
|
415
|
+
name = name.to_s.sub(/^Backup::Config::DSL::/, "")
|
416
|
+
name.split("::").each do |chunk|
|
380
417
|
klass = klass.const_get(chunk)
|
381
418
|
end
|
382
419
|
klass
|
@@ -385,11 +422,12 @@ module Backup
|
|
385
422
|
##
|
386
423
|
# Sets or updates the model's #exit_status.
|
387
424
|
def set_exit_status
|
388
|
-
@exit_status =
|
389
|
-
exception
|
390
|
-
|
391
|
-
|
392
|
-
|
425
|
+
@exit_status =
|
426
|
+
if exception
|
427
|
+
exception.is_a?(StandardError) ? 2 : 3
|
428
|
+
else
|
429
|
+
Logger.has_warnings? ? 1 : 0
|
430
|
+
end
|
393
431
|
end
|
394
432
|
|
395
433
|
##
|
@@ -401,14 +439,13 @@ module Backup
|
|
401
439
|
def before_hook
|
402
440
|
return unless before
|
403
441
|
|
404
|
-
Logger.info
|
442
|
+
Logger.info "Before Hook Starting..."
|
405
443
|
before.call
|
406
|
-
Logger.info
|
407
|
-
|
444
|
+
Logger.info "Before Hook Finished."
|
408
445
|
rescue Exception => err
|
409
446
|
@before_hook_failed = true
|
410
447
|
ex = err.is_a?(StandardError) ? Error : FatalError
|
411
|
-
raise ex.wrap(err,
|
448
|
+
raise ex.wrap(err, "Before Hook Failed!")
|
412
449
|
end
|
413
450
|
|
414
451
|
##
|
@@ -418,16 +455,15 @@ module Backup
|
|
418
455
|
def after_hook
|
419
456
|
return unless after && !@before_hook_failed
|
420
457
|
|
421
|
-
Logger.info
|
458
|
+
Logger.info "After Hook Starting..."
|
422
459
|
after.call(exit_status)
|
423
|
-
Logger.info
|
460
|
+
Logger.info "After Hook Finished."
|
424
461
|
|
425
462
|
set_exit_status # in case hook logged warnings
|
426
|
-
|
427
463
|
rescue Exception => err
|
428
464
|
fatal = !err.is_a?(StandardError)
|
429
465
|
ex = fatal ? FatalError : Error
|
430
|
-
Logger.error ex.wrap(err,
|
466
|
+
Logger.error ex.wrap(err, "After Hook Failed!")
|
431
467
|
# upgrade exit_status if needed
|
432
468
|
(@exit_status = fatal ? 3 : 2) unless exit_status == 3
|
433
469
|
end
|
@@ -440,24 +476,24 @@ module Backup
|
|
440
476
|
def log!(action)
|
441
477
|
case action
|
442
478
|
when :started
|
443
|
-
Logger.info "Performing Backup for '#{
|
444
|
-
"[ backup #{
|
479
|
+
Logger.info "Performing Backup for '#{label} (#{trigger})'!\n" \
|
480
|
+
"[ backup #{VERSION} : #{RUBY_DESCRIPTION} ]"
|
445
481
|
|
446
482
|
when :finished
|
447
483
|
if exit_status > 1
|
448
484
|
ex = exit_status == 2 ? Error : FatalError
|
449
|
-
err = ex.wrap(exception, "Backup for #{
|
485
|
+
err = ex.wrap(exception, "Backup for #{label} (#{trigger}) Failed!")
|
450
486
|
Logger.error err
|
451
487
|
Logger.error "\nBacktrace:\n\s\s" + err.backtrace.join("\n\s\s") + "\n\n"
|
452
488
|
|
453
489
|
Cleaner.warnings(self)
|
454
490
|
else
|
455
|
-
msg = "Backup for '#{
|
491
|
+
msg = "Backup for '#{label} (#{trigger})' "
|
456
492
|
if exit_status == 1
|
457
|
-
msg << "Completed Successfully (with Warnings) in #{
|
493
|
+
msg << "Completed Successfully (with Warnings) in #{duration}"
|
458
494
|
Logger.warn msg
|
459
495
|
else
|
460
|
-
msg << "Completed Successfully in #{
|
496
|
+
msg << "Completed Successfully in #{duration}"
|
461
497
|
Logger.info msg
|
462
498
|
end
|
463
499
|
end
|
@@ -472,8 +508,7 @@ module Backup
|
|
472
508
|
remainder = duration - (hours * 3600)
|
473
509
|
minutes = remainder / 60
|
474
510
|
seconds = remainder - (minutes * 60)
|
475
|
-
|
511
|
+
sprintf "%02d:%02d:%02d", hours, minutes, seconds
|
476
512
|
end
|
477
|
-
|
478
513
|
end
|
479
514
|
end
|