gat 0.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/History.txt +84 -0
  2. data/PostInstall.txt +22 -0
  3. data/README.txt +49 -0
  4. data/Rakefile +12 -0
  5. data/bin/gat +15 -0
  6. data/lib/gat.rb +323 -0
  7. data/lib/gat/action/base.rb +197 -0
  8. data/lib/gat/action/ruby_method.rb +35 -0
  9. data/lib/gat/action/shell_command.rb +185 -0
  10. data/lib/gat/boot.rb +63 -0
  11. data/lib/gat/checks.rb +136 -0
  12. data/lib/gat/debug.rb +29 -0
  13. data/lib/gat/dependence/argument.rb +62 -0
  14. data/lib/gat/dependence/base.rb +54 -0
  15. data/lib/gat/dependence/folder.rb +104 -0
  16. data/lib/gat/dependence/program.rb +36 -0
  17. data/lib/gat/email.rb +80 -0
  18. data/lib/gat/exceptions.rb +163 -0
  19. data/lib/gat/extends.rb +102 -0
  20. data/lib/gat/help.rb +79 -0
  21. data/lib/gat/interpreter.rb +93 -0
  22. data/lib/gat/launcher.rb +100 -0
  23. data/lib/gat/logger.rb +331 -0
  24. data/lib/gat/operation.rb +253 -0
  25. data/lib/gat/version.rb +20 -0
  26. data/lib/gatgets/dar_backup/dar_backup.rb +367 -0
  27. data/lib/gatgets/dar_backup/dar_backup.yml +387 -0
  28. data/lib/gatgets/dar_backup/launcher.rb +44 -0
  29. data/lib/gatgets/dar_backup/templates/list_backups.erb +31 -0
  30. data/lib/gatgets/dar_backup/templates/search.erb +33 -0
  31. data/lib/gatgets/gatgets_manager/gatgets_manager.rb +65 -0
  32. data/lib/gatgets/gatgets_manager/gatgets_manager.yml +71 -0
  33. data/lib/gatgets/gatgets_manager/templates/list.erb +9 -0
  34. data/lib/gatgets/synchronization/README +26 -0
  35. data/lib/gatgets/synchronization/launcher.rb +20 -0
  36. data/lib/gatgets/synchronization/launcher_cron.sh +69 -0
  37. data/lib/gatgets/synchronization/synchronization.rb +123 -0
  38. data/lib/gatgets/synchronization/synchronization.yml +144 -0
  39. data/test/test_gat.rb +36 -0
  40. data/test/test_helper.rb +3 -0
  41. metadata +131 -0
@@ -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
+