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
data/lib/gat/logger.rb ADDED
@@ -0,0 +1,331 @@
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
+ class Logger
20
+
21
+ include Gat::Debug
22
+
23
+ attr_reader :gatget
24
+ attr_reader :global_types
25
+
26
+ attr_accessor :times
27
+ attr_accessor :entries
28
+
29
+ def initialize(gatget)
30
+ @global_types = { 'trace' => { 'description' => 'Traces debug logs', 'verbose' => 4 },
31
+ 'message' => { 'description' => 'Message by gat', 'verbose' => 3 },
32
+ 'warning' => { 'description' => 'Warnings', 'verbose' => 2 },
33
+ 'error' => { 'description' => 'Errors at Gatget', 'verbose' => 1 },
34
+ 'direct' => { 'description' => 'Direct Outputs', 'verbose' => 0 }
35
+ }
36
+
37
+ @gatget = gatget || raise(GatgetException.new("Logger needs a gatget object", "initialize_logger"))
38
+ @times = Hash.new
39
+ @times['init'] = Time.now
40
+ @entries = Array.new
41
+ end
42
+
43
+
44
+
45
+ # Log method
46
+ # Store logs entry into entries array instance attribute
47
+ def log(*args)
48
+ log_entry = LogEntry.new(self, *args)
49
+ direct_output?(log_entry)
50
+ @entries << log_entry
51
+ end
52
+
53
+
54
+ # Gatget Logger output
55
+ # When operation or whatever is finish, gatget logger throw the outputs
56
+ #
57
+ # 3 Standar types are defined
58
+ # - Template output: Template output works with ERB standard template rubye engine. Template is evalued at printed as direct log
59
+ # Template is searched at <gatget_path>/templates/<operation_name>.erb
60
+ #
61
+ # - Email output: Email output deliver log to default email config or raise Exception. Default email config must be stored at
62
+ # @gatget.config['email_config']. Multiple to address can be defined and smtp && sendmail deliver methods are avalaible
63
+ #
64
+ # - YML output: YML output consist in a dump of logger to a yml structure file, so, then, log can be easily interpreted. YML log must be stored
65
+ # at /var/log/gat/<gatget_name>_<operation_name>_<time>.yml, so, log folder must we writtable or exception will be launched.
66
+ #
67
+ # Gat is planned to have more custom outputs by yml config like
68
+ #
69
+ # At operation definition (gatget yml config)
70
+ #
71
+ # operations:
72
+ # example_operation:
73
+ # outputs: [ custom_template, custom_email]
74
+ #
75
+ # and then, at templates definition
76
+ #
77
+ # templates:
78
+ # custom_template:
79
+ # type: template
80
+ # config:
81
+ # path: <your custom template path>
82
+ # log_level: <direct|warning|whatever>
83
+ # custom_email:
84
+ # type: email
85
+ # config:
86
+ # <overwrite here default email config>
87
+ #
88
+ # But it is still on mind :D
89
+ #
90
+ def output(type)
91
+ case type
92
+ when 'template','email','yml'
93
+ send("output_#{ type }")
94
+ else
95
+ # Now, do nothing! :D
96
+ end
97
+ end
98
+
99
+ def to_yaml
100
+ entries_hash_array = []
101
+ @entries.each do |entry|
102
+ entries_hash_array << entry.to_hash
103
+ end
104
+ entries_hash_array.to_yaml
105
+ end
106
+
107
+ def human_sume
108
+ process_resume = "Process Resume:\n---------------\n\n"
109
+ process_resume << " - Times: \n * start: #{ self.gatget.times['init'] }\n * now: #{ Time.now }\n * secs: #{ Time.now - self.gatget.times['init']} \n * min: #{ (Time.now - self.gatget.times['init'])/60 } \n * hours: #{ ( Time.now - self.gatget.times['init'])/3600 } \n\n"
110
+ process_resume << " - Logger:\n * msgs: #{ self.entries.size }\n * warnings: #{ self.entries.select{|e| e.global_type == 'warning' }.size }\n * errors: #{ self.entries.select{|e| e.global_type == 'error' }.size }\n\n"
111
+ process_resume << " - Whole log: \n#{ self.entries.map{ |e| " * #{ e.inspect } \n" } }"
112
+ process_resume
113
+ end
114
+
115
+ private
116
+ # just output message if direct output is enabled by debug or by verbosity
117
+ def direct_output?(log_entry)
118
+ if @gatget.debug
119
+ print_debug_msg(log_entry.inspect)
120
+ else
121
+ $stdout.puts log_entry.output unless self.gatget.verbose < log_entry.verbose_level
122
+ end
123
+ end
124
+
125
+
126
+ # Standar template output
127
+ # See output for more information
128
+ def output_template
129
+ template_file = "#{ @gatget.path }/templates/#{ @gatget.operation.name }.erb"
130
+
131
+ # raise GatgetException if template not found
132
+ unless File.exists?(template_file)
133
+ raise GatgetException.new("Template for operation #{ @gatget.operation.name } not found at #{ template_file }", "run_outputs_template")
134
+ end
135
+
136
+ template_content = File.read(template_file)
137
+
138
+ # bind operation variable to template
139
+ operation = @gatget.operation
140
+ template = ERB.new(template_content, 0, "%<>")
141
+ @gatget.logger.log("direct", "operation_output_template", template.result(binding))
142
+ end
143
+
144
+ # Standar email output
145
+ # See output for more information
146
+ def output_email
147
+ # default email config is used
148
+ unless @gatget.config['email_config']
149
+ raise GatgetConfigException.new("Default email config is empty at @gatget.config['email_config']", "run_output_email")
150
+ end
151
+
152
+ if @gatget.operation.status == 'ok'
153
+ subject_prefix = 'OK'
154
+ elsif @gatget.operation.status == 'failed'
155
+ subject_prefix = 'ERROR'
156
+ else
157
+ subject_prefix = 'WARNING'
158
+ end
159
+
160
+ email_subject = "[GAT] [#{ @gatget.class }] [#{ @gatget.operation.name.camelize }] [#{ subject_prefix }]"
161
+
162
+ email_body = "#{ @gatget.logger.human_sume }"
163
+
164
+ @gatget.create_and_deliver_email(@gatget.config['email_config']['send_to'], { 'subject' => email_subject, 'body' => email_body }, @gatget.config['email_config'])
165
+ end
166
+
167
+ # Standar yml output
168
+ # See output for more information
169
+ def output_yml
170
+ yml_log = File.new("/var/log/gat/#{ self.gatget.name.underscore }_#{ self.gatget.operation.name }_#{ Time.now.strftime("%Y%m%d%H%M%S") }.yml", "w+")
171
+ yml_log.write(self.gatget.logger.to_yaml)
172
+ yml_log.close
173
+ end
174
+
175
+ end
176
+
177
+
178
+ class LogEntry
179
+
180
+ attr_reader :logger
181
+ attr_reader :global_type
182
+ attr_reader :category
183
+ attr_reader :message
184
+ attr_reader :options
185
+ attr_reader :verbose_level
186
+ attr_reader :time
187
+
188
+
189
+ def initialize(logger, global_type = "trace", category = "undefined", message = "Empty", *options)
190
+ @logger = logger
191
+ @time = Time.now
192
+ @global_type = global_type
193
+
194
+ unless logger.global_types.keys.include?(global_type)
195
+ raise GatgetException.new("Undefined log global_type #{ global_type }", "initialize_log_entry")
196
+ end
197
+
198
+ @category = category
199
+ @message = message
200
+ @options = options
201
+ @verbose_level = logger.global_types[global_type]['verbose']
202
+ end
203
+
204
+
205
+ def inspect
206
+ "#{ self.time.strftime("%Y-%m-%d %H:%M:%S") } | #{ self.global_type.ljust(20) } | #{ self.category.ljust(20) } => #{ self.message }"
207
+ end
208
+
209
+ def to_hash
210
+ { 'time' => self.time, 'global_type' => self.global_type, 'category' => self.category, 'message' => self.message, 'options' => self.options }
211
+ end
212
+
213
+ def output
214
+ self.message
215
+ end
216
+
217
+ end
218
+ end
219
+
220
+
221
+ =begin
222
+
223
+ module Logger
224
+
225
+
226
+ # This function must be as robust as possible, so we can not allow any exception here
227
+ def log(global_type = "trace", category = "undefined", message = "Empty", options = {})
228
+
229
+ # log goes always to gat::log
230
+
231
+ #gatget_object = self.class.name == 'Gat::Base' ? self : self.gatget
232
+ gatget_object = self
233
+
234
+ log_entry = Hash.new
235
+ log_entry['type'] = global_type
236
+ log_entry['category'] = category
237
+ log_entry['message'] = message
238
+ log_entry['position'] = @logger.size
239
+ gatget_object.logger << log_entry
240
+
241
+ # skip output on debug mode
242
+ if gatget_object.debug
243
+ log_to_debug(log_entry)
244
+ else
245
+
246
+ #gatget_stout_output = gatget_object.config['gatget_operations'][gatget_object.operation]['output'] || 'enabled'
247
+ #if gatget_stout_output == 'enabled'
248
+ # log_entry_level = get_debug_levels[log_entry['type']] || 5
249
+ # if self.verbose >= log_entry_level
250
+ # $stdout.puts format_output(log_entry)
251
+ # end
252
+ #end
253
+ end
254
+ end
255
+
256
+ def format_output(log_entry, format = nil)
257
+ gatget_format_output = format || self.config['gatget_operations'][self.operation]['output_format'] || 'template'
258
+
259
+ if gatget_format_output == 'template'
260
+
261
+ template_file = self.templates["stdout"] || GAT_ROOT + '/templates/stdout.template'
262
+ template = File.new(template_file, "r")
263
+ template_content = ""
264
+ while (line = template.gets)
265
+ template_content << line
266
+ end
267
+ template.close
268
+ ret = eval(template_content)
269
+ else
270
+ ret = " #{ log_entry['position'].to_s.ljust(3) } | #{ log_entry['type'].ljust(10).upcase } | #{ log_entry['category'].ljust(30).upcase } | #{ log_entry['message'] }\n"
271
+ end
272
+ ret
273
+ end
274
+
275
+
276
+ # debug purpuose method, just output all
277
+ def log_to_debug(log_entry)
278
+ print_debug_msg "#{ log_entry['position'] } ** #{ log_entry['category'] } » #{ log_entry['message'] } «"
279
+ end
280
+
281
+ def get_type_messages(type)
282
+ entries = []
283
+ @logger.map { |log_entry|
284
+ entries << log_entry if log_entry['type'] == type
285
+ }
286
+ entries
287
+ end
288
+
289
+
290
+
291
+ # construct a string with all the logger information
292
+ def build_whole_log(options = {})
293
+ whole_log = ''
294
+
295
+ if options['start_text']
296
+ whole_log << options['start_text']
297
+ end
298
+
299
+ if options['include_resume']
300
+ for entry_type in ['error', 'warning']
301
+ type_entries = get_type_messages(entry_type)
302
+
303
+ if type_entries and type_entries.any?
304
+ whole_log << "\n"
305
+ whole_log << "#{ entry_type }s at gatget (#{ type_entries.size })\n"
306
+ whole_log << "#{ '-' * entry_type.size }-------------#{ '-' * type_entries.size.to_s.size }-\n"
307
+ whole_log << "\n"
308
+
309
+ type_entries.each do |type_entry|
310
+ whole_log << format_output(type_entry, 'plain')
311
+ end
312
+ else
313
+ whole_log << "0 #{ entry_type }s at gatget"
314
+ end
315
+ end
316
+ end
317
+
318
+ # include all log
319
+ whole_log << "\n"
320
+ whole_log << "whole log\n"
321
+ whole_log << "---------\n"
322
+ self.logger.each do |log_entry|
323
+ whole_log << format_output(log_entry, 'plain')
324
+ whole_log << "\n"
325
+ end
326
+
327
+ whole_log
328
+ end
329
+ end
330
+ end
331
+ =end
@@ -0,0 +1,253 @@
1
+ =begin
2
+
3
+ :file => operation.rb
4
+ :author => (c) 2008-2009 A.C. Gnoxys info@gnoxys.net
5
+
6
+ ######################################################################################
7
+ ## This file is part of GAT: http://gat.rubyforge.org ##
8
+ ## ##
9
+ ## GAT (Gnoxys Administration Tools) is released under the GPL License 3 or higher. ##
10
+ ## You can get a copy of the license easily at http://www.gnu.org/licenses/gpl.html.##
11
+ ######################################################################################
12
+
13
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
14
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
17
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
18
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+
21
+ =end
22
+
23
+
24
+ module Gat
25
+
26
+ # Gat::Operation
27
+ #
28
+ # Operations are the pieces of a gatget. Operations means the whole procement when we want to make something
29
+ # Operations have the next config options at YML definition
30
+ #
31
+ # <operation_name> *must be uniq*
32
+ # description: <description text>
33
+ # Description of operation... It will be showed at gatget help
34
+ # users: [ <allowed users to run gat> ]
35
+ # Users that are allowed to run GatGet. If empty or missing, no restrictions are applied
36
+ # programs: [ <array of programs_names> ]
37
+ # Array of programs that are defined in YML config that operation will need
38
+ # arguments:[ <array of arguments_names> ]
39
+ # Array of arguments that are defined in YML config that operation will need
40
+ # folders:[ <array of folders_names> ]
41
+ # Array of folders that are defined in YML config that operation will need
42
+ # helpers:[ <array of helpers_names> ]
43
+ # Ruby methods that will be launched before actions starts
44
+ # actions:
45
+ # Array of actions that operation will launch
46
+ # outpus:
47
+ # Array of outputs that operation will print or make
48
+ # onfail:
49
+ # Ruby method that is launched if Operation fail_do_backup
50
+ #
51
+
52
+
53
+ class Operation
54
+
55
+ attr_reader :gatget
56
+
57
+ attr_reader :config
58
+ attr_reader :name
59
+ attr_reader :description
60
+
61
+ attr_reader :programs
62
+ attr_reader :arguments
63
+ attr_reader :folders
64
+
65
+ attr_reader :helpers
66
+
67
+ attr_reader :outputs
68
+ attr_reader :users
69
+
70
+ attr_accessor :actions
71
+ attr_accessor :status
72
+
73
+ def initialize(operation_name, operation_config, gatget)
74
+ @name = operation_name
75
+ @gatget = gatget
76
+ @description = operation_config['description'] || "#{ operation_name } at GatGet #{ self.class }"
77
+ @config = operation_config
78
+ @helpers = operation_config['helpers'] || []
79
+
80
+ @status = 'ok'
81
+
82
+ if operation_config['users'] and not valid_user(operation_config['users'])
83
+ raise GatgetException.new('Current user is not allowed to run gatget operation', 'valid_user')
84
+ end
85
+
86
+ for dependence in [ 'programs', 'arguments', 'folders' ]
87
+ self.instance_variable_set("@#{ dependence }", evalue_dependences(dependence))
88
+ end
89
+ end
90
+
91
+
92
+ def evalue_dependences(dependence_type)
93
+ # get named dependences
94
+ dependences = self.config[dependence_type] || []
95
+ evalued_dependences = Array.new
96
+ dependences.each do |dependence|
97
+ config = self.gatget.get_element_config(dependence_type, dependence)
98
+ dependence_object = Object.module_eval("Gat::Dependence::#{ dependence_type.gsub(/s$/,'').capitalize }").new(dependence, config, self)
99
+ dependence_object.evalue
100
+ evalued_dependences << dependence_object
101
+ end
102
+
103
+ evalued_dependences
104
+ end
105
+
106
+ # Execute operation.
107
+ # After set all dependences, operation is ready to run. Just do it
108
+ # By steps, operation will run:
109
+ #
110
+ # 1) Helpers
111
+ # 2) Actions
112
+ # 3) Outputs
113
+ #
114
+ # Each step, operation will check that state is ok, if not ok, operation is stopped
115
+ def execute
116
+ run_helpers if continue_operation('helpers')
117
+ ret = run_actions if continue_operation('actions')
118
+
119
+ self.gatget.logger.log("message", "operation", "Operation #{ self.name } Ended!")
120
+
121
+ run_outputs
122
+ ret
123
+ end
124
+
125
+
126
+ def get_action(action_name)
127
+ actions = self.actions.select { |a| a.name == action_name }
128
+ actions.first || raise(GatgetException.new("Action #{ action_name } not found at operation #{ self.name }", "get_actions"))
129
+ end
130
+
131
+ private
132
+ # Run Helpers
133
+ #
134
+ # Helpers are:
135
+ #
136
+ # - Ruby methods that are wrotten at controller gatget file and provides specific features to the gatget
137
+ # - Helpers can not stop or modify gatget operation status, only actions can do it
138
+ #
139
+ def run_helpers
140
+ self.helpers.each do |helper|
141
+ self.gatget.logger.log("trace", "helper", "Running helper #{ self.class } @#{ helper }")
142
+
143
+ self.gatget.send(helper)
144
+ end
145
+ end
146
+
147
+
148
+ def run_actions
149
+ action_result = nil
150
+ actions = self.config['actions'] || []
151
+
152
+ if actions.empty?
153
+ raise GatgetConfigException.new("Actions are empty for operation #{ self.name }", "run_actions")
154
+ end
155
+
156
+ self.actions = Array.new
157
+ actions.each do |action|
158
+ action_config = self.gatget.get_element_config('actions', action) || []
159
+
160
+ if not action_config['type'] or action_config['type'].empty?
161
+ raise GatgetConfigException.new("Action type missing or empty for operation #{ self.name }", "run_actions")
162
+ end
163
+
164
+ action_object = Object.module_eval("Gat::Action::#{ action_config['type'].camelize }").new(action, action_config, self)
165
+
166
+ action_result = action_object.execute
167
+ self.actions << action_object
168
+ end
169
+ action_result
170
+ end
171
+
172
+ def run_outputs
173
+ outputs = self.config['outputs'] || []
174
+
175
+ outputs.each do |output|
176
+ self.gatget.logger.output(output)
177
+ end
178
+ end
179
+
180
+
181
+ def valid_user(users)
182
+ users.empty? or users.include?(%x[ whoami ].strip)
183
+ end
184
+
185
+ def continue_operation(continue_with)
186
+ ret = true
187
+ if self.status == 'failed'
188
+ self.gatget.logger.log("message", "operation", "Operation #{ self.name } will not run #{ continue_with }. Status is #{ self.status }")
189
+ ret = false
190
+ end
191
+ ret
192
+ end
193
+
194
+
195
+ end
196
+
197
+ end
198
+
199
+
200
+
201
+ # gatget_name: Your underscore gatgetname
202
+
203
+ # gatget_description: Your Gatget Description
204
+
205
+ # gatget_config_variables: Variable configurations to be used accross the gatget
206
+
207
+ # gatget_arguments: Gatget needed Arguments, by stdin or pipe
208
+
209
+ # gatget_programs: Array of programs gatget will use
210
+
211
+ # gaget_outputs Outputs an operations will launch
212
+
213
+ # gatget_conditions Conditions to be checked
214
+ # < condition_name >
215
+ # description Condition description
216
+ # type Condition check Type
217
+ # onfail What happens when condition fail
218
+ # onfail_message Optional Message for onfail
219
+
220
+ # gatget_actions
221
+
222
+
223
+ # gatget_operations Operations gatget will suport
224
+ # < operation_name >
225
+ # description Operation description
226
+ # arguments Array of arguments
227
+ # stdout: Array of stdouts
228
+ # instructions Array of instructions to execute
229
+ # onfail On fail Method
230
+
231
+
232
+ =begin
233
+
234
+ Gatget instance methods
235
+ # log Array of logs entries RW
236
+
237
+ # config Gatget Structure config R
238
+ # times Gatget Process Times RW
239
+
240
+ # operation Gatget runned operations R
241
+
242
+ # dependences: All that is needed by the program to run.extrated from config
243
+ # programs: Array with all the programs... take by config['gatget_config']['programs ']
244
+ # folders Array of Hasesh with config['gatget_config'][¡folder_name'] => { 'path' => '<path>', 'tree' => [ <tree folder array> ] }
245
+ # static Hash of static variables to the script
246
+ # arguments Command Line Arguments by get || pipe
247
+ #
248
+
249
+ =end
250
+
251
+
252
+
253
+