gat 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +84 -0
- data/PostInstall.txt +22 -0
- data/README.txt +49 -0
- data/Rakefile +12 -0
- data/bin/gat +15 -0
- data/lib/gat.rb +323 -0
- data/lib/gat/action/base.rb +197 -0
- data/lib/gat/action/ruby_method.rb +35 -0
- data/lib/gat/action/shell_command.rb +185 -0
- data/lib/gat/boot.rb +63 -0
- data/lib/gat/checks.rb +136 -0
- data/lib/gat/debug.rb +29 -0
- data/lib/gat/dependence/argument.rb +62 -0
- data/lib/gat/dependence/base.rb +54 -0
- data/lib/gat/dependence/folder.rb +104 -0
- data/lib/gat/dependence/program.rb +36 -0
- data/lib/gat/email.rb +80 -0
- data/lib/gat/exceptions.rb +163 -0
- data/lib/gat/extends.rb +102 -0
- data/lib/gat/help.rb +79 -0
- data/lib/gat/interpreter.rb +93 -0
- data/lib/gat/launcher.rb +100 -0
- data/lib/gat/logger.rb +331 -0
- data/lib/gat/operation.rb +253 -0
- data/lib/gat/version.rb +20 -0
- data/lib/gatgets/dar_backup/dar_backup.rb +367 -0
- data/lib/gatgets/dar_backup/dar_backup.yml +387 -0
- data/lib/gatgets/dar_backup/launcher.rb +44 -0
- data/lib/gatgets/dar_backup/templates/list_backups.erb +31 -0
- data/lib/gatgets/dar_backup/templates/search.erb +33 -0
- data/lib/gatgets/gatgets_manager/gatgets_manager.rb +65 -0
- data/lib/gatgets/gatgets_manager/gatgets_manager.yml +71 -0
- data/lib/gatgets/gatgets_manager/templates/list.erb +9 -0
- data/lib/gatgets/synchronization/README +26 -0
- data/lib/gatgets/synchronization/launcher.rb +20 -0
- data/lib/gatgets/synchronization/launcher_cron.sh +69 -0
- data/lib/gatgets/synchronization/synchronization.rb +123 -0
- data/lib/gatgets/synchronization/synchronization.yml +144 -0
- data/test/test_gat.rb +36 -0
- data/test/test_helper.rb +3 -0
- metadata +131 -0
data/lib/gat/version.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
=begin
|
2
|
+
This file is part of GAT: http://gat.rubyforge.org
|
3
|
+
|
4
|
+
(c) 2008-2009 A.C. Gnoxys info@gnoxys.net
|
5
|
+
|
6
|
+
GAT (Gnoxys Administration Tools) is released under the GPL License 3 or higher.
|
7
|
+
You can get a copy of the license easily at http://www.gnu.org/licenses/gpl.html.
|
8
|
+
|
9
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
10
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
11
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
12
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
13
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
14
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
15
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
16
|
+
=end
|
17
|
+
|
18
|
+
module Gat
|
19
|
+
VERSION = '0.2.8'
|
20
|
+
end
|
@@ -0,0 +1,367 @@
|
|
1
|
+
=begin
|
2
|
+
This file is part of GAT: http://gat.rubyforge.org
|
3
|
+
|
4
|
+
(c) 2008-2009 A.C. Gnoxys info@gnoxys.net
|
5
|
+
|
6
|
+
GAT (Gnoxys Administration Tools) is released under the GPL License 3 or higher.
|
7
|
+
You can get a copy of the license easily at http://www.gnu.org/licenses/gpl.html.
|
8
|
+
|
9
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
10
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
11
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
12
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
13
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
14
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
15
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
16
|
+
=end
|
17
|
+
|
18
|
+
require 'gat'
|
19
|
+
|
20
|
+
GATGET_DAR_BACKUP_ROOT = File.expand_path(File.dirname(__FILE__))
|
21
|
+
|
22
|
+
class GatgetDarBackup < Gat::Base
|
23
|
+
|
24
|
+
|
25
|
+
# helpers
|
26
|
+
def set_flag_mysql_dumps
|
27
|
+
set_flag("active_mysql_dumps", get_dependence_value("static", "mysql_dumps"))
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_flag_catalog_exists
|
31
|
+
catalog_name = "bbdd_#{ self.config['server_name'] || 'backup' }"
|
32
|
+
set_dependence_variable("catalog_name", catalog_name)
|
33
|
+
set_dependence_variable("catalog_path", "#{ get_dependence_value("folders", "backups_folder_catalog") }/#{ catalog_name }")
|
34
|
+
set_flag("catalog_exists", File.exists?(get_dependence_variable("catalog_path")))
|
35
|
+
end
|
36
|
+
|
37
|
+
# get all the system backups and catalogs backups
|
38
|
+
def get_all_backups
|
39
|
+
get_system_backups
|
40
|
+
get_catalog_backups
|
41
|
+
end
|
42
|
+
|
43
|
+
# We are going to set the backups variables. Which ones must be deleted and the name of the current backup
|
44
|
+
def set_do_backup_variables
|
45
|
+
# if we dont have a backup
|
46
|
+
if not get_current_complete_backup
|
47
|
+
|
48
|
+
# * perform a complet backup
|
49
|
+
# * set the minimum space required at 1 kb
|
50
|
+
# * mark backups to delete, if nothing to delete,system will get it
|
51
|
+
# * create new dir and link it to current through new_link_current flag
|
52
|
+
|
53
|
+
set_variables_to_complete_backup
|
54
|
+
set_dependence_variable("last_backup_size", 1)
|
55
|
+
set_backups_to_delete
|
56
|
+
set_flag("delete_old_backups", true)
|
57
|
+
set_flag("new_complete_folder", true)
|
58
|
+
|
59
|
+
# if we have a complet backup but today is complet
|
60
|
+
elsif get_dependence_value("static", "complet_backup_days").include?(Date.today.wday)
|
61
|
+
|
62
|
+
# * perform a complet backup
|
63
|
+
# * get the last size of complet backup
|
64
|
+
# * identify backups to delete and mark delete flag
|
65
|
+
# * mark delete current link
|
66
|
+
# * create new dir and link it to current through new_link_current flag
|
67
|
+
|
68
|
+
set_variables_to_complete_backup
|
69
|
+
set_dependence_variable("last_backup_size", get_last_backup_size('complet'))
|
70
|
+
set_backups_to_delete
|
71
|
+
set_flag("delete_old_backups", true)
|
72
|
+
set_flag("delete_current_link", true)
|
73
|
+
set_flag("new_complete_folder", true)
|
74
|
+
|
75
|
+
# else, we must do a diff backup, do
|
76
|
+
else
|
77
|
+
# * perform diff backup
|
78
|
+
# * dont care about delete or new dirs... etc..
|
79
|
+
# * get the last size of diff backup
|
80
|
+
set_variables_to_diff_backup
|
81
|
+
set_dependence_variable("last_backup_size", get_last_backup_size('diff'))
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def exists_backup_file
|
86
|
+
get_system_backups
|
87
|
+
backup_folder = get_dependence_value("folders", "backups_folder_data_local")
|
88
|
+
backup_dar_name = get_dependence_value("arguments", "backup_dar_name")
|
89
|
+
backups_with_dar_name = get_dependence_variable("system_backups").select { |b| b['dar_name'] == backup_dar_name }
|
90
|
+
if backups_with_dar_name.empty?
|
91
|
+
self.logger.log("direct", "action_result", "\n ERROR: Backup dar name #{ backup_dar_name } not found\n\n Type $> #{ $0 } list_backups to see avalaibles backups\n\n")
|
92
|
+
set_flag("exists_backup_file", false)
|
93
|
+
else
|
94
|
+
backup = backups_with_dar_name.first
|
95
|
+
set_dependence_variable("backup_to_show_content", "#{ backup['folder'] }/#{ backup['dar_name']}")
|
96
|
+
set_flag("exists_backup_file", true)
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
# ruby methods
|
102
|
+
def list_backups_data
|
103
|
+
end
|
104
|
+
|
105
|
+
def show_nice_search
|
106
|
+
get_catalog_backups
|
107
|
+
end
|
108
|
+
|
109
|
+
# We need to have enough space to do backup
|
110
|
+
def check_enough_space_for_backup
|
111
|
+
|
112
|
+
last_backup_size = get_dependence_variable("last_backup_size")
|
113
|
+
backup_folder = get_dependence_value("folders", "backups_folder_data_local")
|
114
|
+
thresold = get_dependence_value("static", "space_thresold").to_i * 1024 * 1024 # to Bytes
|
115
|
+
# check it
|
116
|
+
if not check_enough_space({'where' => backup_folder, 'space_needed' => last_backup_size}) and not check_enough_space({'where' => backup_folder, 'space_needed' => thresold})
|
117
|
+
raise Gat::GatgetProcessException.new("System doesnt have enough space", "check_enough_space_for_backup")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# failed action launch_backup_rescue callback
|
122
|
+
# Dar, when the backup is so big, usually end with a 2 status, that means some files changed during backup operations. That
|
123
|
+
# is normal while is working over logs, mysql, etc...
|
124
|
+
# So, we have to discriminate what the non zero exit status means.
|
125
|
+
def launch_backup_rescue
|
126
|
+
# get the backup action
|
127
|
+
launch_backup = Gat::Action::Base.get_current_action
|
128
|
+
|
129
|
+
# Exit level 4 but with callback to delete backup
|
130
|
+
if launch_backup.exit_level == 4 and launch_backup.output.include?('No space left on device, you have the opportunity to make room now')
|
131
|
+
# disk is full, mark bad backup flag that will delete current backup
|
132
|
+
self.logger.log('trace', 'onfail_launch_backup_rescue', 'Disk is full, delete current backup')
|
133
|
+
|
134
|
+
delete_action = Gat::Action::ShellCommand.new('delete_bad_backup', get_element_config('actions', 'delete_bad_backup'), self.operation)
|
135
|
+
delete_action.execute
|
136
|
+
|
137
|
+
if delete_action.exit_level == 0
|
138
|
+
launch_backup.onfail_message = "Dar backup collapse disk, but backup was deleted"
|
139
|
+
else
|
140
|
+
launch_backup.onfail_message = "Dar backup collapse disk and backup WASNT DELETED."
|
141
|
+
end
|
142
|
+
|
143
|
+
# mark action to abort
|
144
|
+
launch_backup.onfail = 'abort'
|
145
|
+
|
146
|
+
# 4 exit level always means problems
|
147
|
+
elsif launch_backup.exit_level == 4 or launch_backup.exit_level == 2
|
148
|
+
# mark action to abort
|
149
|
+
launch_backup.onfail = 'abort'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# send rescue email will send a email for notification errors at do_backup operation
|
154
|
+
def onfail
|
155
|
+
|
156
|
+
unless self.config['email_config']
|
157
|
+
raise Gat::GatgetConfigException.new("Default email config is empty at gatget.config['email_config']", "run_output_email")
|
158
|
+
end
|
159
|
+
|
160
|
+
email_subject = "[GAT] [#{ self.class.name }] [#{ self.operation.name.camelize }] [FAILED]"
|
161
|
+
|
162
|
+
|
163
|
+
email_body = "Gatget #{ self.class.name } was stopped by raising of #{ self.onfail_error.class } at #{ Time.now }\n\n"
|
164
|
+
email_body << "#{ onfail_error.exit_error }"
|
165
|
+
email_body << "\n\n Errors log: \n\n #{self.logger.entries.select{ |e| e.global_type == 'error' }.map{ |e| e.inspect }.join("\n") }\n\n"
|
166
|
+
email_body << "\n\n Warning log: \n\n #{self.logger.entries.select{ |e| e.global_type == 'warning' }.map{ |e| e.inspect }.join("\n") }\n\n"
|
167
|
+
email_body << "\n\n Whole log: \n\n #{self.logger.entries.map{ |e| e.inspect }.join("\n") }"
|
168
|
+
|
169
|
+
self.create_and_deliver_email(self.config['email_config']['send_to'], { 'subject' => email_subject, 'body' => email_body }, self.config['email_config'])
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
# nothing to delete if catalog is empty
|
174
|
+
def catalog_is_empty
|
175
|
+
set_flag("catalog_is_not_empty", get_dependence_variable("catalog_backups").any?)
|
176
|
+
end
|
177
|
+
|
178
|
+
def print_status
|
179
|
+
if check_i_am_running
|
180
|
+
ret = "running"
|
181
|
+
else
|
182
|
+
ret = "not running"
|
183
|
+
end
|
184
|
+
puts ret
|
185
|
+
Gat::Action::Base.get_current_action.output = ret
|
186
|
+
end
|
187
|
+
|
188
|
+
private
|
189
|
+
def get_system_backups
|
190
|
+
backup_entries = []
|
191
|
+
local_data_folder = get_dependence_value("folders", "backups_folder_data_local")
|
192
|
+
|
193
|
+
# get the current folder
|
194
|
+
current_folder = nil
|
195
|
+
if File.exists?("#{ local_data_folder }/current")
|
196
|
+
# on some S.O, readlink return folder with last slash. remove it anyway.
|
197
|
+
current_folder = File.readlink("#{ local_data_folder }/current").gsub(/\//,'')
|
198
|
+
end
|
199
|
+
|
200
|
+
(Dir.entries(local_data_folder) - ['current', '.', '..']).each do |backup_folder|
|
201
|
+
backup_folder_path = "#{ local_data_folder }/#{ backup_folder }"
|
202
|
+
(Dir.entries(backup_folder_path) - ['..', '.' ]).each do |backup_file|
|
203
|
+
backup_entries << { 'type' => backup_file.include?('complet') ? 'complet' : 'diff',
|
204
|
+
'name' => backup_file,
|
205
|
+
'path' => "#{ local_data_folder }/#{ backup_folder }/#{ backup_file }",
|
206
|
+
'dar_name'=> backup_file.split('.').first,
|
207
|
+
'isolate' => backup_file.include?('isolate'),
|
208
|
+
'folder' => backup_folder,
|
209
|
+
'current' => backup_folder == current_folder }
|
210
|
+
end
|
211
|
+
end
|
212
|
+
set_dependence_variable("system_backups", backup_entries)
|
213
|
+
end
|
214
|
+
|
215
|
+
def get_catalog_backups
|
216
|
+
backup_entries = []
|
217
|
+
# define a new action to get all the catalogs in database
|
218
|
+
action = Gat::Action::ShellCommand.new('identify_all_backups_in_catalog', get_element_config('actions', 'identify_backups_in_catalog'), self.operation)
|
219
|
+
action.execute
|
220
|
+
|
221
|
+
backup_in_catalog = action.output
|
222
|
+
backup_in_catalog.each_line do |line|
|
223
|
+
if line.include?('complet') or line.include?('diff')
|
224
|
+
line = line.strip
|
225
|
+
backup_entries << { 'type' => line.include?('complet') ? 'complet' : 'diff',
|
226
|
+
'dar_name'=> line.split(' ')[2],
|
227
|
+
'id' => line.split(' ')[0],
|
228
|
+
'folder' => line.split(' ')[1] }
|
229
|
+
end
|
230
|
+
end
|
231
|
+
set_dependence_variable("catalog_backups", backup_entries)
|
232
|
+
end
|
233
|
+
|
234
|
+
def get_current_complete_backup
|
235
|
+
stored_backups = get_dependence_variable("system_backups")
|
236
|
+
|
237
|
+
# select complete and current
|
238
|
+
complet_and_current = stored_backups.select { |backup| backup['type'] == 'complet' and backup['current'] and !backup['isolate']}
|
239
|
+
if complet_and_current.empty?
|
240
|
+
complet_backup_file = false
|
241
|
+
else
|
242
|
+
set_dependence_variable("backup_complet_folder", complet_and_current.first['folder'] )
|
243
|
+
set_dependence_variable("backup_complet_file", complet_and_current.first['name'].split('.').first)
|
244
|
+
complet_backup_file = true
|
245
|
+
end
|
246
|
+
complet_backup_file
|
247
|
+
end
|
248
|
+
|
249
|
+
def set_variables_to_complete_backup
|
250
|
+
backups_folder = get_dependence_value("folders", "backups_folder_data_local")
|
251
|
+
backup_folder = "#{ Date.today }"
|
252
|
+
backup_name = "#{ Date.today }_#{ self.config['server_name'] || 'backup' }_complet"
|
253
|
+
backup_path = "#{ backups_folder }/#{ backup_folder }/#{ backup_name }"
|
254
|
+
# set the variables
|
255
|
+
set_dependence_variable("backup_launch_argument", "-c #{ backup_path }")
|
256
|
+
set_dependence_variable("backup_folder", backup_folder)
|
257
|
+
set_dependence_variable("backup_name", backup_name)
|
258
|
+
set_dependence_variable("backup_path", backup_path)
|
259
|
+
end
|
260
|
+
|
261
|
+
def set_variables_to_diff_backup
|
262
|
+
backups_folder = get_dependence_value("folders", "backups_folder_data_local")
|
263
|
+
backup_folder = get_dependence_variable("backup_complet_folder")
|
264
|
+
backup_name = "#{ Date.today }_#{ self.config['server_name'] || 'backup' }_diff"
|
265
|
+
backup_path = "#{ backups_folder }/#{ backup_folder }/#{ backup_name }"
|
266
|
+
backup_complet = "#{ backups_folder }/#{ backup_folder }/#{ get_dependence_variable("backup_complet_file") }"
|
267
|
+
# set the variables
|
268
|
+
set_dependence_variable("backup_launch_argument", "-c #{ backup_path } -A #{ backup_complet }")
|
269
|
+
set_dependence_variable("backup_folder", backup_folder)
|
270
|
+
set_dependence_variable("backup_name", backup_name)
|
271
|
+
set_dependence_variable("backup_path", backup_path)
|
272
|
+
end
|
273
|
+
|
274
|
+
def set_backups_to_delete
|
275
|
+
folders_backups_to_delete = []
|
276
|
+
catalog_backups_to_delete = []
|
277
|
+
number_stored_backups = get_dependence_value("static", "number_backup_stored")
|
278
|
+
stored_entries = Dir.entries(get_dependence_value("folders", "backups_folder_data_local")) - [".","..","current"]
|
279
|
+
catalog_backups = get_dependence_variable("catalog_backups")
|
280
|
+
(stored_entries.sort.reverse[number_stored_backups..stored_entries.size] || []).each do |backup|
|
281
|
+
folders_backups_to_delete << backup
|
282
|
+
cbtd = catalog_backups.select { |b| b['folder'] == "#{ get_dependence_value("folders", "backups_folder_data_local") }/#{ backup }" }
|
283
|
+
if cbtd.any?
|
284
|
+
catalog_backups_to_delete << cbtd
|
285
|
+
end
|
286
|
+
end
|
287
|
+
# set dependence_variable to delete system folders
|
288
|
+
set_dependence_variable("backup_folders_to_delete", folders_backups_to_delete)
|
289
|
+
|
290
|
+
# anyway, need to delete?
|
291
|
+
set_flag("delete_system_backups_if_any", folders_backups_to_delete.any?)
|
292
|
+
|
293
|
+
# set depedendece variable to delete catalog files
|
294
|
+
set_dependence_variable("backup_catalog_to_delete", catalog_backups_to_delete.flatten.uniq.map{ |b| '1' })
|
295
|
+
# any way, need to delete?
|
296
|
+
set_flag("delete_catalog_backups_if_any", catalog_backups_to_delete.any?)
|
297
|
+
|
298
|
+
end
|
299
|
+
|
300
|
+
def get_last_backup_size(backup_type)
|
301
|
+
size = 0
|
302
|
+
system_backups = get_dependence_variable("system_backups")
|
303
|
+
if backup_type == 'complet'
|
304
|
+
complet_and_current = system_backups.select { |backup| backup['type'] == 'complet' and backup['current']}
|
305
|
+
complet_and_current.each do |backup_entry|
|
306
|
+
size += File.size("#{ get_dependence_value("folders","backups_folder_data_local") }/current/#{ backup_entry['name'] }")
|
307
|
+
end
|
308
|
+
elsif backup_type == 'diff'
|
309
|
+
# get the last diff backups
|
310
|
+
last_diff_backups = system_backups.select{ |backup| backup['type'] == 'diff' and not backup['isolate'] }
|
311
|
+
# select all the backup files with the same dar_name and calculate size if we have a last_diff_backup
|
312
|
+
if last_diff_backups and last_diff_backups.any?
|
313
|
+
system_backups.select { |backup| backup['dar_name'] == last_diff_backups.last['dar_name'] }.each do |backup_entry|
|
314
|
+
size += File.size("#{ get_dependence_value("folders","backups_folder_data_local") }/#{ backup_entry ['folder'] }/#{ backup_entry['name'] }")
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
size
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
|
323
|
+
module Gat
|
324
|
+
|
325
|
+
module Action
|
326
|
+
|
327
|
+
class ShellCommand < Base
|
328
|
+
|
329
|
+
# dar mixes a little bit its stdout and stderr outputs
|
330
|
+
def reinterpret_output_and_error(output, error, status)
|
331
|
+
all_errors = error.split("\n")
|
332
|
+
all_outputs = output.split("\n")
|
333
|
+
ret_error = Array.new
|
334
|
+
ret_output = ""
|
335
|
+
all_errors.each do |line|
|
336
|
+
if line != ""
|
337
|
+
if line == "No terminal found for user interaction. All questions will be assumed a negative answer (less destructive choice), which most of the time will abort the program."
|
338
|
+
status = 0 if status == 5
|
339
|
+
else
|
340
|
+
ret_error << line
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
add_next_line = false
|
345
|
+
all_outputs.each do |line|
|
346
|
+
if add_next_line
|
347
|
+
ret_error << line
|
348
|
+
add_next_line = false
|
349
|
+
elsif line.index("FATAL error") == 0
|
350
|
+
ret_error << line
|
351
|
+
status = 99 if status == 0
|
352
|
+
add_next_line = true
|
353
|
+
elsif line.index("Error") != nil
|
354
|
+
ret_error << line
|
355
|
+
status = 99 if status == 0
|
356
|
+
add_next_line = true
|
357
|
+
else
|
358
|
+
ret_output = line + "\n"
|
359
|
+
end
|
360
|
+
end
|
361
|
+
return ret_output, ret_error.join(". \n"), status
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
end
|
366
|
+
|
367
|
+
end
|
@@ -0,0 +1,387 @@
|
|
1
|
+
# Gatget Config Script for DarBackup Gatget
|
2
|
+
# -----------------------------------------
|
3
|
+
|
4
|
+
description: 'Gatget backup manager with DAR'
|
5
|
+
|
6
|
+
static:
|
7
|
+
complet_backup_days: [ 0 ]
|
8
|
+
number_backup_stored: 1
|
9
|
+
# mysql dumps options
|
10
|
+
mysql_dumps: false
|
11
|
+
mysql_user: root
|
12
|
+
mysql_password: ''
|
13
|
+
|
14
|
+
# space limit to perform backup, in megas
|
15
|
+
space_thresold: 3000M
|
16
|
+
|
17
|
+
# dar tunned options
|
18
|
+
# enable compression. nil disable
|
19
|
+
dar_compression: 256
|
20
|
+
# size of division each file
|
21
|
+
dar_file_size: 3500M
|
22
|
+
# enable backup empty folders
|
23
|
+
dar_enable_empty_folders: true
|
24
|
+
# root folder from backup
|
25
|
+
dar_root_backup: '/'
|
26
|
+
# password to encrypt backups
|
27
|
+
dar_encrypt_passwd: 'none'
|
28
|
+
# password to decrypt backups
|
29
|
+
dar_decrypt_passwd: 'none'
|
30
|
+
# exclude foolders
|
31
|
+
exclude_folders:
|
32
|
+
- boot
|
33
|
+
- dev
|
34
|
+
- lib64
|
35
|
+
- media
|
36
|
+
- opt
|
37
|
+
- root
|
38
|
+
- selinux
|
39
|
+
- sys
|
40
|
+
- usr
|
41
|
+
- cdrom
|
42
|
+
- lib
|
43
|
+
- lost+found
|
44
|
+
- mnt
|
45
|
+
- proc
|
46
|
+
- sbin
|
47
|
+
- srv
|
48
|
+
- tmp
|
49
|
+
- home
|
50
|
+
- var
|
51
|
+
- etc
|
52
|
+
# exclude files
|
53
|
+
exclude_files:
|
54
|
+
- *.dar
|
55
|
+
- /initrd.img.old
|
56
|
+
- /vmlinuz
|
57
|
+
- /initrd.img
|
58
|
+
- /vmlinuz.old
|
59
|
+
exclude_to_compress:
|
60
|
+
- *.gz
|
61
|
+
- *.bz2
|
62
|
+
- *.zip
|
63
|
+
- *.png
|
64
|
+
|
65
|
+
arguments:
|
66
|
+
search_pattern:
|
67
|
+
description: File or Folder pattern to search in catalog
|
68
|
+
backup_dar_name:
|
69
|
+
description: "Backup Dar name (for example: 2009_08_01_your_machine_complet)"
|
70
|
+
backup_id:
|
71
|
+
description: "Backup Dar catalog ID from data will be restored"
|
72
|
+
pattern_to_restore:
|
73
|
+
description: "Pattern to restore. It will be restored all the files or folder that match with pattern, even they are folders, subfolders, or files"
|
74
|
+
|
75
|
+
folders:
|
76
|
+
backups_folder:
|
77
|
+
path: /tmp/backups
|
78
|
+
tree:
|
79
|
+
- data
|
80
|
+
- data/local
|
81
|
+
- data/external
|
82
|
+
- catalog
|
83
|
+
- extras
|
84
|
+
- extras/mysql
|
85
|
+
- restore
|
86
|
+
|
87
|
+
programs:
|
88
|
+
dar:
|
89
|
+
description: Disk Linux Archive
|
90
|
+
dar_manager:
|
91
|
+
description: Dar manager for backups
|
92
|
+
mysql:
|
93
|
+
description: MySQl client
|
94
|
+
mysqldump:
|
95
|
+
description: Mysql Dumper
|
96
|
+
gzip:
|
97
|
+
description: Compressor
|
98
|
+
|
99
|
+
|
100
|
+
parameters:
|
101
|
+
backup_id:
|
102
|
+
type: dependence
|
103
|
+
value: arguments/backup_id
|
104
|
+
backup_files:
|
105
|
+
type: dependence
|
106
|
+
value: variable/backup_launch_argument
|
107
|
+
backups_folder_mysql:
|
108
|
+
type: dependence
|
109
|
+
value: folders/backups_folder_extras_mysql
|
110
|
+
backups_folder_data_local:
|
111
|
+
type: dependence
|
112
|
+
value: folders/backups_folder_data_local
|
113
|
+
backups_folder_restore:
|
114
|
+
type: dependence
|
115
|
+
value: folders/backups_folder_restore
|
116
|
+
backup_path:
|
117
|
+
type: dependence
|
118
|
+
value: variable/backup_path
|
119
|
+
backups_path_for_dar:
|
120
|
+
type: dependence
|
121
|
+
value: variable/system_backups
|
122
|
+
array_method: "select{|b| b['isolate'] }.map{|b| b['folder'] + '/' + b['dar_name'].gsub(/_isolate$/,'') }"
|
123
|
+
catalog_path:
|
124
|
+
type: dependence
|
125
|
+
value: variable/catalog_path
|
126
|
+
catalog_entries:
|
127
|
+
type: dependence
|
128
|
+
value: variable/catalog_backups
|
129
|
+
array_method: "map{|b| '1' }"
|
130
|
+
complete_folder:
|
131
|
+
type: dependence
|
132
|
+
value: variable/backup_folder
|
133
|
+
current_date:
|
134
|
+
type: eval
|
135
|
+
value: "Date.today"
|
136
|
+
dar_compression:
|
137
|
+
type: dependence
|
138
|
+
value: static/dar_compression
|
139
|
+
dar_encrypt_password:
|
140
|
+
type: dependence
|
141
|
+
value: static/dar_encrypt_passwd
|
142
|
+
dar_decrypt_password:
|
143
|
+
type: dependence
|
144
|
+
value: static/dar_decrypt_passwd
|
145
|
+
dar_file_size:
|
146
|
+
type: dependence
|
147
|
+
value: static/dar_file_size
|
148
|
+
dar_manager_program:
|
149
|
+
type: dependence
|
150
|
+
value: programs/dar_manager
|
151
|
+
dar_program:
|
152
|
+
type: dependence
|
153
|
+
value: programs/dar
|
154
|
+
dar_root_backup:
|
155
|
+
type: dependence
|
156
|
+
value: static/dar_root_backup
|
157
|
+
exclude_to_compress:
|
158
|
+
type: dependence
|
159
|
+
value: static/exclude_to_compress
|
160
|
+
join: "' -Z '"
|
161
|
+
exclude_folders:
|
162
|
+
type: dependence
|
163
|
+
value: static/exclude_folders
|
164
|
+
join: "' -P '"
|
165
|
+
gzip_program:
|
166
|
+
type: dependence
|
167
|
+
value: programs/gzip
|
168
|
+
last_backup_size:
|
169
|
+
type: dependence
|
170
|
+
value: variable/last_backup_size
|
171
|
+
mysql_databases:
|
172
|
+
type: dependence
|
173
|
+
value: action_output/get_mysql_databases
|
174
|
+
array_method: 'split("\n")'
|
175
|
+
mysql_dump_program:
|
176
|
+
type: dependence
|
177
|
+
value: programs/mysqldump
|
178
|
+
mysql_password:
|
179
|
+
type: dependence
|
180
|
+
value: static/mysql_password
|
181
|
+
mysql_program:
|
182
|
+
type: dependence
|
183
|
+
value: programs/mysql
|
184
|
+
mysql_user:
|
185
|
+
type: dependence
|
186
|
+
value: static/mysql_user
|
187
|
+
pattern_simple_for_search:
|
188
|
+
type: dependence
|
189
|
+
value: arguments/search_pattern
|
190
|
+
pattern_to_restore:
|
191
|
+
type: dependence
|
192
|
+
value: arguments/pattern_to_restore
|
193
|
+
old_backups_at_catalog_ids:
|
194
|
+
type: dependence
|
195
|
+
value: variable/backup_catalog_to_delete
|
196
|
+
old_system_backups:
|
197
|
+
type: dependence
|
198
|
+
value: variable/backup_folders_to_delete
|
199
|
+
server_name:
|
200
|
+
type: dependence
|
201
|
+
value: static/server_name
|
202
|
+
show_backup_path:
|
203
|
+
type: dependence
|
204
|
+
value: variable/backup_to_show_content
|
205
|
+
|
206
|
+
actions:
|
207
|
+
delete_old_mysql_dumps:
|
208
|
+
type: shell_command
|
209
|
+
flags: [ active_mysql_dumps ]
|
210
|
+
syntax: rm -f {{backups_folder_mysql}}/*.sql.gz {{backups_folder_mysql}}/*.sql
|
211
|
+
onfail: continue
|
212
|
+
get_mysql_databases:
|
213
|
+
type: shell_command
|
214
|
+
flags: [ active_mysql_dumps ]
|
215
|
+
syntax: "{{mysql_program}} -u {{mysql_user}} -p'{{mysql_password}}' -NBse 'Show databases'"
|
216
|
+
onfail: continue
|
217
|
+
do_mysql_dumps:
|
218
|
+
type: shell_command
|
219
|
+
flags: [ active_mysql_dumps ]
|
220
|
+
syntax: "cd {{backups_folder_mysql}}; {{mysql_dump_program}} -u {{mysql_user}} -p'{{mysql_password}}' {{mysql_databases}} -r mysqldump_{{mysql_databases}}_{{current_date}}.sql"
|
221
|
+
multiple: [ mysql_databases ]
|
222
|
+
compress_mysql_dumps:
|
223
|
+
type: shell_command
|
224
|
+
flags: [ active_mysql_dumps ]
|
225
|
+
syntax: "cd {{backups_folder_mysql}}; {{gzip_program}} -9 mysqldump_{{mysql_databases}}_{{current_date}}.sql"
|
226
|
+
multiple: [ mysql_databases ]
|
227
|
+
remove_old_system_backups:
|
228
|
+
type: shell_command
|
229
|
+
flags: [ delete_old_backups, delete_system_backups_if_any ]
|
230
|
+
syntax: 'rm -rf {{backups_folder_data_local}}/{{old_system_backups}}'
|
231
|
+
multiple: [ old_system_backups ]
|
232
|
+
remove_old_catalog_backups:
|
233
|
+
type: shell_command
|
234
|
+
flags: [ delete_old_backups, catalog_exists, delete_catalog_backups_if_any ]
|
235
|
+
syntax: '{{dar_manager_program}} -B {{catalog_path}} -D {{old_backups_at_catalog_ids}}'
|
236
|
+
multiple: [ old_backups_at_catalog_ids ]
|
237
|
+
remove_old_current_link:
|
238
|
+
type: shell_command
|
239
|
+
flags: [ delete_current_link ]
|
240
|
+
syntax: 'rm {{backups_folder_data_local}}/current'
|
241
|
+
onfail: continue
|
242
|
+
create_new_complet_folder:
|
243
|
+
type: shell_command
|
244
|
+
flags: [ new_complete_folder ]
|
245
|
+
syntax: 'mkdir -p {{backups_folder_data_local}}/{{complete_folder}}'
|
246
|
+
set_new_current_link:
|
247
|
+
type: shell_command
|
248
|
+
flags: [ new_complete_folder ]
|
249
|
+
syntax: 'cd {{backups_folder_data_local}} ; ln -sf {{complete_folder}} current'
|
250
|
+
launch_backup:
|
251
|
+
type: shell_command
|
252
|
+
syntax: "cd {{backups_folder_data_local}}; {{dar_program}} -w -m {{dar_compression}} -y -s {{dar_file_size}} -D -Q -R {{dar_root_backup}} -Z '{{exclude_to_compress}}' -P '{{exclude_folders}}' -X '*.dar' -J {{dar_encrypt_password}} -K {{dar_decrypt_password}} {{backup_files}}"
|
253
|
+
onfail: continue
|
254
|
+
onfail_callback: launch_backup_rescue
|
255
|
+
test_backup:
|
256
|
+
type: shell_command
|
257
|
+
syntax: "{{dar_program}} -Q -t {{backup_path}} -K {{dar_decrypt_password}}"
|
258
|
+
create_isolation_file:
|
259
|
+
type: shell_command
|
260
|
+
syntax: "{{dar_program}} -w -Q -C '{{backup_path}}_isolate' -A '{{backup_path}}' -J {{dar_decrypt_password}}"
|
261
|
+
identify_backups_in_catalog:
|
262
|
+
type: shell_command
|
263
|
+
flags: [ catalog_exists ]
|
264
|
+
syntax: '{{dar_manager_program}} -B {{catalog_path}} -l'
|
265
|
+
create_catalog:
|
266
|
+
type: shell_command
|
267
|
+
flags: [ '!catalog_exists' ]
|
268
|
+
syntax: '{{dar_manager_program}} -C {{catalog_path}}'
|
269
|
+
insert_in_catalog:
|
270
|
+
type: shell_command
|
271
|
+
syntax: "{{dar_manager_program}} -Q -B {{catalog_path}} -A '{{backup_path}}_isolate' '{{backup_path}}'"
|
272
|
+
list_backups_data:
|
273
|
+
type: ruby_method
|
274
|
+
delete_all_backups_at_catalog:
|
275
|
+
type: shell_command
|
276
|
+
flags: [ catalog_exists, catalog_is_not_empty ]
|
277
|
+
syntax: '{{dar_manager_program}} -B {{catalog_path}} -D {{catalog_entries}}'
|
278
|
+
multiple: [ catalog_entries ]
|
279
|
+
insert_all_backups_at_catalog:
|
280
|
+
type: shell_command
|
281
|
+
flags: [ catalog_exists ]
|
282
|
+
syntax: "{{dar_manager_program}} -Q -B {{catalog_path}} -A '{{backups_folder_data_local}}/{{backups_path_for_dar}}_isolate' '{{backups_folder_data_local}}/{{backups_path_for_dar}}'"
|
283
|
+
multiple: [ backups_path_for_dar ]
|
284
|
+
search_simple:
|
285
|
+
type: shell_command
|
286
|
+
flags: [ catalog_exists ]
|
287
|
+
syntax: "{{dar_manager_program}} -B {{catalog_path}} -f {{pattern_simple_for_search}}"
|
288
|
+
onfail: continue
|
289
|
+
show_nice_search:
|
290
|
+
type: ruby_method
|
291
|
+
show_backup_content:
|
292
|
+
type: shell_command
|
293
|
+
syntax: "{{dar_program}} -l {{backups_folder_data_local}}/{{show_backup_path}} -K {{dar_decrypt_password}}"
|
294
|
+
flags: [ exists_backup_file ]
|
295
|
+
output: true
|
296
|
+
restore_pattern:
|
297
|
+
type: shell_command
|
298
|
+
flags: [ exists_backup_file ]
|
299
|
+
syntax: "{{dar_program}} -x {{backups_folder_data_local}}/{{show_backup_path}} -R {{backups_folder_restore}} -K {{dar_decrypt_password}} -v -g '{{pattern_to_restore}}' -O"
|
300
|
+
output: true
|
301
|
+
delete_bad_backup:
|
302
|
+
type: shell_command
|
303
|
+
syntax: "rm -rf {{backup_path}}*.dar"
|
304
|
+
check_enough_space_for_backup:
|
305
|
+
type: ruby_method
|
306
|
+
onfail_message: 'System does not have enough space'
|
307
|
+
exit_if_i_am_running:
|
308
|
+
type: ruby_method
|
309
|
+
onfail_message: 'I am already running, I will exit now'
|
310
|
+
print_status:
|
311
|
+
type: ruby_method
|
312
|
+
|
313
|
+
operations:
|
314
|
+
do_backup:
|
315
|
+
description: 'Perform a Backup with DAR. Backups can be tuned by config'
|
316
|
+
users: [ root ]
|
317
|
+
programs: [ dar, dar_manager, mysql, mysqldump, gzip ]
|
318
|
+
arguments: [ ]
|
319
|
+
folders: [ backups_folder ]
|
320
|
+
helpers: [ exit_if_i_am_running, set_flag_mysql_dumps, set_flag_catalog_exists, get_all_backups, set_do_backup_variables ]
|
321
|
+
actions: [ delete_old_mysql_dumps, get_mysql_databases, do_mysql_dumps, compress_mysql_dumps,
|
322
|
+
remove_old_catalog_backups, remove_old_system_backups, remove_old_current_link,
|
323
|
+
check_enough_space_for_backup, create_new_complet_folder, set_new_current_link,
|
324
|
+
launch_backup, test_backup,
|
325
|
+
create_isolation_file, create_catalog, insert_in_catalog ]
|
326
|
+
outputs: [ ]
|
327
|
+
|
328
|
+
list_backups:
|
329
|
+
description: 'List avalaible backups at System && Catalog'
|
330
|
+
users: [ root ]
|
331
|
+
programs: [ dar_manager ]
|
332
|
+
arguments: [ ]
|
333
|
+
folders: [ backups_folder ]
|
334
|
+
helpers: [ set_flag_catalog_exists, get_all_backups ]
|
335
|
+
conditions: [ ]
|
336
|
+
actions: [ list_backups_data ]
|
337
|
+
onfail: [ ]
|
338
|
+
outputs: [ template ]
|
339
|
+
|
340
|
+
syncronize_backups:
|
341
|
+
description: 'Syncronize catalog with avalaible system backups'
|
342
|
+
users: [ root ]
|
343
|
+
programs: [ dar_manager ]
|
344
|
+
arguments: [ ]
|
345
|
+
folders: [ backups_folder ]
|
346
|
+
helpers: [ exit_if_i_am_running, set_flag_catalog_exists, get_all_backups, catalog_is_empty ]
|
347
|
+
conditions: [ ]
|
348
|
+
actions: [ delete_all_backups_at_catalog, insert_all_backups_at_catalog ]
|
349
|
+
|
350
|
+
search:
|
351
|
+
description: 'Search files to restore in backups'
|
352
|
+
users: [ root ]
|
353
|
+
programs: [ dar_manager ]
|
354
|
+
arguments: [ search_pattern ]
|
355
|
+
folders: [ backups_folder ]
|
356
|
+
helpers: [ set_flag_catalog_exists ]
|
357
|
+
outputs: [ template, yml ]
|
358
|
+
conditions: [ ]
|
359
|
+
actions: [ search_simple, show_nice_search ]
|
360
|
+
|
361
|
+
show_backup_content:
|
362
|
+
description: 'Show all the backup contents. Redirect to a file if your backup content has many information'
|
363
|
+
users: [ root ]
|
364
|
+
programs: [ dar ]
|
365
|
+
arguments: [ backup_dar_name ]
|
366
|
+
folders: [ backups_folder ]
|
367
|
+
helpers: [ exists_backup_file]
|
368
|
+
conditions: [ ]
|
369
|
+
actions: [ show_backup_content ]
|
370
|
+
|
371
|
+
restore:
|
372
|
+
description: 'Allow to restore files || directory from backups, files will be restored under <your backup folder>/restore'
|
373
|
+
users: [ root ]
|
374
|
+
programs: [ dar ]
|
375
|
+
arguments: [ pattern_to_restore, backup_dar_name ]
|
376
|
+
folders: [ backups_folder ]
|
377
|
+
helpers: [ exists_backup_file ]
|
378
|
+
conditions: [ ]
|
379
|
+
actions: [ restore_pattern ]
|
380
|
+
|
381
|
+
status:
|
382
|
+
description: 'Checks whether the backup script is running'
|
383
|
+
users: [ root ]
|
384
|
+
actions: [ print_status ]
|
385
|
+
|
386
|
+
|
387
|
+
|