gat 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|