gat 0.2.8 → 0.2.11

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,18 @@
1
+ == 0.2.11 2010-03-22
2
+ * Bugfix release
3
+ * Bug in reinterpreter_output_and_error was wrong and cutted up to last line whole ouput
4
+ * set_backups_to_delete crashed when no system backups must be deleted
5
+ * Fixed bug at program dependence. config['path'] return nil
6
+
7
+ == 0.2.10 2010-03-09
8
+ * Bugfix release
9
+ * Bug at dependence folder mount operation.
10
+
11
+ == 0.2.9 2010-03-05
12
+ * Improved DarBackup gatget
13
+ * Include SystemBackup to perform all related operations to search backups
14
+ * Removed Catalog from dar_backup operations. Running though dump backup content now. Less time, better performance
15
+
1
16
  == 0.2.8 2010-02-16
2
17
  * Bugfix release
3
18
  * ShellCommandChilds was only executing for the first child
data/PostInstall.txt CHANGED
@@ -1,22 +1,20 @@
1
- Gat Gem Post Install Doc
1
+ Gat Gem Post Install Doc
2
2
  ===============================================================================
3
3
 
4
- Gat provides several built in Gatgets. For now, it contains
4
+ Gat provides several built in Gatgets. For now, it contains
5
5
 
6
6
  - GatgetDarBackup => Performs and maintains a whole system of backups with
7
- dar (Disk Archiver for GNU/Linux)
7
+ dar (Disk Archiver for GNU/Linux)
8
8
 
9
9
 
10
- To use this, simply copy the file named launcher.rb to the gatget install
11
- folder (default by gem, /usr/lib/ruby/gems/ruby1.8/gat/gatgets/<gatget_name>)
12
- and place it under your local executable folder (for example: /usr/local/bin).
10
+ To use this, simply run $ gat command and follow instructions
13
11
 
14
12
 
15
- For more information on gat, see http://gat.rubyforge.org
13
+ For more information on gat, see http://gat.rubyforge.org
16
14
 
17
15
 
18
16
  ===============================================================================
19
- Copyright © 2007-2009 Gnoxys. http://www.gnoxys.net.
20
- Gat is released under GPL v3.0 or higther. See README for more information
17
+ Copyright © 2007-2009 Gnoxys. http://www.gnoxys.net.
18
+ Gat is released under GPL v3.0 or higther. See README for more information
21
19
 
22
20
 
data/Rakefile CHANGED
@@ -4,7 +4,9 @@ require 'rubygems'
4
4
  require 'hoe'
5
5
 
6
6
  Hoe.spec 'gat' do
7
- developer('gnoxys', 'soporte@gnoxys.net')
7
+ developer('gnoxys', 'soporte@gnoxys.net')
8
+ extra_deps << [ 'tmail', '>=1.2.3' ]
9
+ extra_deps << [ 'open4', '>=1.0' ]
8
10
 
9
11
  # self.rubyforge_name = 'blahx' # if different than 'blah'
10
12
  end
data/lib/gat.rb CHANGED
@@ -188,7 +188,7 @@ module Gat
188
188
  def get_flag(flag_name)
189
189
  ret = self.flags[flag_name]
190
190
  if ret == nil
191
- self.operation.gatget.logger.log("warning", "get_flag","Undefined flag #{flag_name}")
191
+ self.operation.gatget.logger.log("warning", "get_flag", "Undefined flag #{flag_name}")
192
192
  ret = false
193
193
  end
194
194
  ret
@@ -19,27 +19,28 @@ module Gat
19
19
 
20
20
  def run
21
21
  ret = nil
22
- # Shell Command can be multiple, that means the command will be execute over a foreach variable subtitutions.
23
- # That is usefull, for example, when you need to do the same actions with some variable subtition, like
24
- # a multiple files compression.
25
- @childs = (@config['multiple'] and @config['multiple'].any?) ? set_multiple_childs(@config['multiple']) : [ ]
26
-
27
- # If ShellCommand is multiple, then, we exec all of its childs
28
- # If not, we just execute ShellCommand instance
29
- if @childs.any?
30
- @childs.each { |child|
22
+ # Shell Command can be multiple, that means the command will be execute over a foreach variable subtitutions.
23
+ # That is usefull, for example, when you need to do the same actions with some variable subtition, like
24
+ # a multiple files compression.
25
+ @childs = (@config['multiple'] and @config['multiple'].any?) ? set_multiple_childs(@config['multiple']) : [ ]
26
+
27
+ # If ShellCommand is multiple, then, we exec all of its childs
28
+ # If not, we just execute ShellCommand instance
29
+ if @childs.any?
30
+ @childs.each { |child|
31
31
  if not child.exec
32
32
  ret = false
33
33
  end
34
34
  }
35
- else
36
- self.parsed_syntax = interpreter_parameters(self.syntax, self.operation.gatget)
37
- ret = exec(self.parsed_syntax)
38
- end
35
+ else
36
+ self.parsed_syntax = interpreter_parameters(self.syntax, self.operation.gatget)
39
37
 
40
- if self.config['output']
41
- self.operation.gatget.logger.log("direct", "action_output", self.output)
42
- end
38
+ ret = exec(self.parsed_syntax)
39
+ end
40
+
41
+ if self.config['output']
42
+ self.operation.gatget.logger.log("direct", "action_output", self.output)
43
+ end
43
44
  ret
44
45
  end
45
46
 
@@ -52,7 +53,7 @@ module Gat
52
53
  # Even it has some problems too. Open4 module has big problems when the stdout or the stderr comes
53
54
  # with tons of information. For example, with a mysqldump output.
54
55
  #
55
- # The solution presented here is a wapper through Process.fork. We create a new fork, making
56
+ # The solution presented here is a wrapper through Process.fork. We create a new fork, making
56
57
  # and the output is not managed by the ruby script itself but by the fork process.
57
58
  # IO.pipes are created to pass the stdout, stderr and stdin data through Gat proccess and Fork process
58
59
  #
data/lib/gat/boot.rb CHANGED
@@ -33,7 +33,7 @@ GAT_TEMPLATES = GAT_ROOT + '/templates'
33
33
  # External gems
34
34
  gems = [ 'ftools', 'rubygems', 'open4', 'yaml', 'erb', 'rdoc/usage', 'rdoc/code_objects',
35
35
  'rdoc/markup/simple_markup', 'rdoc/markup/simple_markup/to_flow', 'rdoc/ri/ri_formatter',
36
- 'rdoc/ri/ri_options', 'net/smtp', 'tmail', 'erb' ]
36
+ 'rdoc/ri/ri_options', 'net/smtp', 'tmail', 'erb', 'fileutils' ]
37
37
 
38
38
  # Gat Modules
39
39
  modules = [ 'debug', 'help', 'interpreter', 'extends', 'version', 'launcher', 'checks', 'email' ]
data/lib/gat/checks.rb CHANGED
@@ -103,8 +103,7 @@ module Gat
103
103
  r = FileUtils.mkdir(lockdir) rescue r = nil
104
104
  if not r.nil?
105
105
  # lock succeeded, install signal handlers and store the PID
106
- trap 0, proc { p "Trapped"
107
- FileUtils.rm_rf lockdir }
106
+ trap 0, proc { FileUtils.rm_rf lockdir }
108
107
  r = File.open(pidfile, 'w') {|f| f.write($$) }
109
108
  else
110
109
  # lock failed, now check if the other PID is alive
@@ -119,8 +118,7 @@ FileUtils.rm_rf lockdir }
119
118
  r = Process.kill(0, otherpid) rescue r = nil
120
119
  if r == nil
121
120
  # lock is stale, remove it and go on
122
- trap 0, proc { p "Trapped"
123
- FileUtils.rm_rf lockdir }
121
+ trap 0, proc { FileUtils.rm_rf lockdir }
124
122
  r = File.open(pidfile, 'w') {|f| f.write($$) } rescue r=nil
125
123
  return false
126
124
  else
@@ -0,0 +1,80 @@
1
+ =begin
2
+
3
+ :file => condition.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
+ module Gat
24
+
25
+ class Condition
26
+
27
+ include Gat::Checks
28
+ include Gat::Interpreter
29
+
30
+ attr_reader :operation
31
+ attr_reader :config
32
+ attr_reader :name
33
+ attr_reader :type
34
+ attr_reader :description
35
+
36
+ attr_reader :onfail
37
+ attr_reader :onfail_message
38
+
39
+ def initialize(name, config, operation)
40
+ operation.gatget.logger.log("trace", "condition", "Initialize condition #{ name }")
41
+ @operation = operation
42
+ @config = config
43
+ @name = name
44
+
45
+ @description = config['description'] || "Another Condition"
46
+
47
+ @type = config['type'] || 'check_true'
48
+ @onfail = config['onfail'] || 'abort'
49
+ @onfail_message = config['onfail_message'] || "Gatget Process fail at condition #{ self.name }"
50
+
51
+ end
52
+
53
+
54
+ def evalue
55
+ unless Gat::Checks.instance_methods.include?(self.type)
56
+ raise GatgetConfigException.new("Check condition method #{ self.type } not available at Gat::Checks", "evalue_condition")
57
+ end
58
+
59
+ condition_arguments = {}
60
+
61
+ self.config['arguments'].each_pair do |argument_name, argument_parameter|
62
+ condition_arguments[argument_name] = interpreter_parameter(argument_parameter, self.operation.gatget)
63
+ end
64
+
65
+ # Eval condition by send check_method
66
+ # if condition fail, onfail config will checked. unless it is different for 'abort' (default value)
67
+ # gat will stop the process thourgh GatgetProcessException
68
+ unless self.send(self.type, condition_arguments)
69
+ @@conditions_status = 'failed'
70
+ self.operation.gatget.logger.log('warning', 'condition_eval', "Condition #{ self.name } evalued at False")
71
+
72
+ if self.onfail == 'abort'
73
+ self.operation.gatget.logger.log('error', 'condition_eval', "Condition #{ self.name } abort Gatget")
74
+ self.operation.status = 'failed'
75
+ raise GatgetProcessException.new(self.onfail_message, "evalue_condition")
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -64,10 +64,8 @@ module Gat
64
64
  private
65
65
  # check if folder is mounted, if not, try it, if doesnt work, launch GatgetProcessException
66
66
  def mounted?
67
- unless already_mounted?
68
- unless mount_folder
69
- raise Gat::GatgetProcessException.new("Unable to mount folder #{ self.name } at #{ self.path }", "mounted")
70
- end
67
+ unless already_mounted? || mount_folder
68
+ raise Gat::GatgetProcessException.new("Unable to mount folder #{ self.name } at #{ self.path }", "mounted")
71
69
  end
72
70
  end
73
71
 
@@ -77,7 +75,7 @@ module Gat
77
75
  mounts_file = File.open('/proc/mounts', 'r')
78
76
  mounted = false
79
77
  mounts_file.each_line do |mount_line|
80
- mounted = true if mount_line.split(" ")[2].include?(self.path)
78
+ mounted = true if mount_line.split(" ")[1].include?(self.path)
81
79
  end
82
80
  mounted
83
81
  end
@@ -90,7 +88,7 @@ module Gat
90
88
 
91
89
  ignored, status_open4 = Process::waitpid2 pid_open4
92
90
 
93
- if status_open4.exitstatus == 0 # try to mount_folder
91
+ if status_open4.exitstatus == 0
94
92
  self.operation.gatget.logger.log("trace", "mount_folder", "Folder #{ self.name } nicely mounted ")
95
93
  ret = true
96
94
  else
@@ -11,7 +11,11 @@ module Gat
11
11
  end
12
12
 
13
13
  def evalue
14
- self.path || evalue_from_shell
14
+ evalue_from_path || evalue_from_shell
15
+ end
16
+
17
+ def evalue_from_path
18
+ self.value = self.path
15
19
  end
16
20
 
17
21
  # Program is evalued through 'which' shell command
@@ -33,4 +37,4 @@ module Gat
33
37
  end
34
38
  end
35
39
  end
36
- end
40
+ end
data/lib/gat/extends.rb CHANGED
@@ -46,21 +46,36 @@ end
46
46
  class File
47
47
  def self.nice_size(file)
48
48
  filesize = File.size(file)
49
-
50
- if filesize >= 1073741824
51
- filesize = "#{ filesize / 1073741824 } Gb."
52
- elsif filesize >= 1048576
53
- filesize = "#{ filesize / 1048576 } Mb."
54
- elsif filesize >= 1024
55
- filesize = "#{ filesize / 1024 } Kb."
56
- else
57
- filesize = "#{ filesize } bytes"
58
- end
59
-
60
- filesize
49
+ nice_file_size(filesize)
50
+ end
51
+ end
52
+
53
+ def nice_file_size(size)
54
+ if size >= 1073741824
55
+ filesize = "#{ (size.to_f / 1073741824.0).round_to(2) } Gb."
56
+ elsif size >= 1048576
57
+ filesize = "#{ (size.to_f / 1048576.0).round_to(2) } Mb."
58
+ elsif size >= 1024
59
+ filesize = "#{ (size.to_f / 1024.0).round_to(2) } Kb."
60
+ else
61
+ filesize = "#{ size } bytes"
61
62
  end
63
+ filesize
62
64
  end
63
65
 
66
+
67
+ # Float#round_to
68
+ # From: http://www.hans-eric.com/code-samples/ruby-floating-point-round-off/
69
+ # Source: --
70
+ # Just round a float number to x decimals
71
+ class Float
72
+ def round_to(x)
73
+ (self * 10**x).round.to_f / 10**x
74
+ end
75
+ end
76
+
77
+
78
+
64
79
  # Hash#deep_merge
65
80
  # From: http://pastie.textmate.org/pastes/30372, Elliott Hird
66
81
  # Source: http://gemjack.com/gems/tartan-0.1.1/classes/Hash.html
data/lib/gat/logger.rb CHANGED
@@ -141,12 +141,12 @@ module Gat
141
141
  @gatget.logger.log("direct", "operation_output_template", template.result(binding))
142
142
  end
143
143
 
144
- # Standar email output
144
+ # Standard email output
145
145
  # See output for more information
146
146
  def output_email
147
147
  # default email config is used
148
148
  unless @gatget.config['email_config']
149
- raise GatgetConfigException.new("Default email config is empty at @gatget.config['email_config']", "run_output_email")
149
+ raise GatgetConfigException.new("Default email config is empty at @gatget.config['email_config']", "logger:output_email")
150
150
  end
151
151
 
152
152
  if @gatget.operation.status == 'ok'
@@ -0,0 +1,195 @@
1
+
2
+ ###### Global variables, only accessible in yaml scripts via eval code
3
+
4
+ #### Identification, used in logs
5
+
6
+ subsystem_name: backup
7
+ subsystem_description: Irgat backup module
8
+ server_name: balrog
9
+ server_domain: gnoxys.net
10
+
11
+
12
+ ###### Logs definitions
13
+
14
+ script_log:
15
+
16
+ # Log to stdout, not the same as the debug output
17
+ stdout:
18
+ enable: false
19
+ level: 4 # 0.-No output, 1.-Errors, 2.-Warnings, 3.-Messages, 4.-Trace
20
+
21
+ # email log
22
+ mail:
23
+ enable: false
24
+ send_to: santi@gnoxys.net
25
+ smtp_mode: smtp # smtp or sendmail
26
+ level: 4 # see above
27
+ smtp_values: # smtp configuration
28
+ server: mail.gnoxys.net
29
+ port: 25
30
+ domain: gnoxys.net
31
+ user: santi@gnoxys.net
32
+ password:
33
+
34
+
35
+
36
+ ###### Script variables, used only in the yaml script
37
+ script_variables:
38
+
39
+ # User who should run the .rb script
40
+ run_as_user: gnoxys
41
+
42
+ # Path to the backups
43
+ working_path: /tmp/backups
44
+
45
+ # Array of folders to create inside working_path to store things that will be backed up
46
+ folders_tree:
47
+ - data
48
+ - data/local
49
+ - data/local/current # stores the '.dar' files
50
+ - data/local/old
51
+ - extras
52
+ - extras/mysql # stores the mysql dumps
53
+
54
+ # days in which a complete backup will be made (0 -> Sunday, 1 -> Monday, etc.)
55
+ # Put it into quotes!
56
+ complet_backup_days: "2"
57
+
58
+ # maximum complete backups to be stored in the system
59
+ max_stored_backups: 2
60
+
61
+ # Exclude folders from backup, absolute path without first slash
62
+ # for example var/tmp
63
+ # IMPORTANT: data and restore irgat::backup folders are by definition excluded.
64
+ # You don't need to write it here.
65
+ exclude_folders:
66
+ - boot
67
+ - dev
68
+ - var/tmp
69
+
70
+ # files ommited inside backup files, can contain wildcards
71
+ exclude_files:
72
+ - *.dar
73
+
74
+ # exclude types in the compress phase
75
+ exclude_to_compress:
76
+ - .gz
77
+ - .bz2
78
+ - .zip
79
+ - .png
80
+
81
+ # MySQL dump options
82
+ mysql_user:
83
+ mysql_pass:
84
+
85
+ # dar options
86
+ dar:
87
+ compression: 256 # enable compression. nil disable
88
+ file_size: 500M # size of division each file
89
+ enable_empty_folders: true # enable backup empty folders
90
+ root_backup: '/' # root folder from backup
91
+ encrypt_passwd: # password to encrypt backups
92
+ decrypt_passwd: # password to decrypt backups
93
+
94
+
95
+ ###### Script action definition
96
+ ###### Script actions consist of conditions and actions
97
+
98
+ sample_script_action:
99
+
100
+ # Script actions can be disabled. They are enabled by default
101
+ enabled: false
102
+ disabled: true # both of them work
103
+
104
+ # Conditions are checked before any subaction.
105
+ conditions: # Must be an array, hence the following hyphen
106
+ - sample_condition:
107
+
108
+ # Conditions can be disabled. They are enabled by default
109
+ enabled: false
110
+ disabled: true # both of them work
111
+
112
+ type: # Type of value to be checked:
113
+ # fixed: A literal value
114
+ # array: A literal array
115
+ # script_variable: one of the ones defined in the script_variables section
116
+ # script_array: one of the ones defined in the script_variables section
117
+ # eval: Ruby code to be evaluated
118
+ # dependence:
119
+ # folder/_a_folder
120
+ # programs/_a_program
121
+ value: # definition of the value to be checked
122
+
123
+ negated: false # conditions can be negated, defaults to false
124
+
125
+ onfail: fail # What to do if condition fails:
126
+ # skip .- skips this subaction
127
+ # continue .- skips this condition
128
+ # fail .- exits script
129
+ post_eval: code # code to be evaluated after getting the value (%).
130
+ # Example: if % print true else print false end
131
+
132
+ arguments: # conditions can have arguments
133
+ - sample_argument:
134
+ type: # same as condition
135
+ value: # same as condition
136
+
137
+
138
+ # Actions included in script actions are executed if all the conditions are met
139
+ actions:
140
+ # Actions can be disabled. They are enabled by default
141
+ enabled: false
142
+ disabled: true # both of them work
143
+
144
+ - sample_action: # Must be an array, hence the following hyphen
145
+ # Actions can be 'command' or 'set_variable'
146
+ - set_variable:
147
+ name: # Script variable name
148
+ type: # same as condition above
149
+ value: # same as condition above
150
+
151
+ - command:
152
+ type: shell | ruby | shell.foreach | ruby.foreach
153
+
154
+ syntax: # syntax of the command.
155
+ # % is a placeholder for arguments: cd %
156
+
157
+ arguments: # same as conditions
158
+
159
+ onfail: # same values as conditions
160
+
161
+ # For types shell.foreach and ruby.foreach:
162
+ source_action: # Name of the action that produced the array to be processed.
163
+ # Each element of the array is named 'line'
164
+
165
+
166
+ ###### Optional initialize script
167
+
168
+ initialize:
169
+ conditions:
170
+ - condition_1:
171
+ - condition_2:
172
+
173
+ actions:
174
+ - action_1:
175
+ - action_2:
176
+
177
+
178
+ ###### The actions of the script, not including the optional initalize action
179
+
180
+ script_actions:
181
+ - script_action_1:
182
+ - script_action_2:
183
+
184
+
185
+
186
+ ###### Known issues
187
+ #
188
+ # There are a number of problems with writing ruby expressions in yaml code
189
+ # 1.- String concatenation:
190
+ #
191
+ # 2.- Don't use return statements in eval code:
192
+ # return statements, besides returning a value, will end the calling irgat script function
193
+
194
+
195
+