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.
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/checks.rb ADDED
@@ -0,0 +1,136 @@
1
+ =begin
2
+
3
+ :file => checks.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
+ # Gat::Checks Module
26
+ #
27
+ # Check methods return true or false through some arguments. Extend module if you want to add more checkable methods
28
+ #
29
+ # Check methods are hash based to better human arguments readeable. I mean, when you make a comparation beetwen two
30
+ # values, it is better to use arguments[:small] > arguments[:big] thatn arguments[0] > arguments[1]
31
+ #
32
+ # So, need_arguments method is avaible as public inside this module. This function will check the arguments hash
33
+ # and raise a GatgetConfixException if check_method miss one argument. For example
34
+ #
35
+ # def check_minor_than(arguments)
36
+ # need_arguments(['minor', 'major'], arguments)
37
+ # arguments['minor'] < arguments['major']
38
+ # end
39
+ #
40
+ # check_minor_than('minor' => 10, 'bigger' => 20) # => raise GatgetConfigException
41
+ # check_minor_than('minor' => 10, 'major' => 20) # => true
42
+ # check_minor_than('minor' => 20, 'major' => 10) # => false
43
+ module Checks
44
+
45
+ # Files checkers!!!!!!
46
+ # --------------------
47
+
48
+ # Check if file exist
49
+ def check_file_exists(arguments)
50
+ need_arguments(['file_url'], arguments)
51
+ File.exists?(arguments['file_url'])
52
+ end
53
+
54
+ # Check if file exist
55
+ def check_file_not_exists(arguments)
56
+ need_arguments(['file_url'], arguments)
57
+ !File.exists?(arguments['file_url'])
58
+ end
59
+
60
+ def check_enough_space(arguments)
61
+ need_arguments(['where', 'space_needed'], arguments)
62
+ # get space at where
63
+ space = %x[ df -B 1 #{ arguments['where'] }].split("\n").last.split(" ")[3].to_i
64
+ space > arguments['space_needed'].to_i
65
+ end
66
+
67
+ def check_true(arguments)
68
+ need_arguments(['true_expression'], arguments)
69
+ eval("#{ arguments['true_expression'] }")
70
+ end
71
+
72
+ def check_false(arguments)
73
+ need_arguments(['false_expression'], arguments)
74
+ !eval(arguments['false_expression'])
75
+ end
76
+
77
+
78
+
79
+ # need_arguments checks that all the needed arguments are in array
80
+ # raise GagetConfigException if someone is not avaliable
81
+ def need_arguments(needed, avalaible)
82
+ needed.each do |need|
83
+ unless avalaible.keys.include?(need)
84
+ raise GatgetConfigException.new("needed argument #{ need } not avalaible at #{ self.class.name }", "need_arguments")
85
+ end
86
+ end
87
+ end
88
+
89
+ def exit_if_i_am_running(myname = nil)
90
+ if check_i_am_running(myname)
91
+ exit 0
92
+ end
93
+ end
94
+
95
+ def check_i_am_running(myname = nil)
96
+ # lock dirs/files
97
+ myname ||= File.basename($0, ".rb")
98
+ lockdir="/tmp/#{myname}-lock"
99
+ pidfile="#{lockdir}/PID"
100
+
101
+ ### start locking attempt
102
+
103
+ r = FileUtils.mkdir(lockdir) rescue r = nil
104
+ if not r.nil?
105
+ # lock succeeded, install signal handlers and store the PID
106
+ trap 0, proc { p "Trapped"
107
+ FileUtils.rm_rf lockdir }
108
+ r = File.open(pidfile, 'w') {|f| f.write($$) }
109
+ else
110
+ # lock failed, now check if the other PID is alive
111
+ begin
112
+ f = File.open(pidfile, 'r')
113
+ otherpid = f.readline.to_i
114
+ rescue
115
+ # if it wasn't possible to read the file anymore, another instance probably is
116
+ # about to remove the lock -- exit, we're *still* locked
117
+ return true
118
+ end
119
+ r = Process.kill(0, otherpid) rescue r = nil
120
+ if r == nil
121
+ # lock is stale, remove it and go on
122
+ trap 0, proc { p "Trapped"
123
+ FileUtils.rm_rf lockdir }
124
+ r = File.open(pidfile, 'w') {|f| f.write($$) } rescue r=nil
125
+ return false
126
+ else
127
+ # lock is valid and otherpid is active - exit, we're locked!
128
+ return true
129
+ end
130
+ end
131
+ return false
132
+ end
133
+
134
+
135
+ end
136
+ end
data/lib/gat/debug.rb ADDED
@@ -0,0 +1,29 @@
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
+ module Debug
20
+
21
+ def print_debug_msg(message)
22
+ $stdout.puts "* debug *: #{ message } \n"
23
+ end
24
+
25
+ def get_debug_levels
26
+ { "trace" => 4, "message" => 3, "warning" => 2, "error" => 1, "direct_output" => 0 }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,62 @@
1
+ module Gat
2
+ module Dependence
3
+ class Argument < Base
4
+
5
+ attr_reader :position
6
+ attr_reader :optional
7
+ attr_reader :prefix
8
+ attr_reader :type
9
+
10
+ attr :value
11
+
12
+ def initialize(name, config, operation)
13
+
14
+ super(name, config, operation)
15
+ # by default, argument is command line
16
+ @type = @config['type'] || 'command_line'
17
+ @optional = @config['optional'] || false
18
+ @prefix = @config['prefix'] || nil
19
+
20
+ @@argument_position ||= 0
21
+ @position = ( @@argument_position += 1 )
22
+
23
+ end
24
+
25
+ # Argument must come
26
+ def evalue
27
+ # command line arguments
28
+ if self.type == 'command_line' and self.operation.gatget.arguments.any? and self.operation.gatget.arguments[self.position]
29
+
30
+ # ToDo => add prefix to arguments
31
+ # if self.position == 'prefix'
32
+ #prefix_position = self.operation.gatget.arguments.index(self.prefix)
33
+ #self.value = self.operation.gatget.arguments[
34
+ # else
35
+ self.value = self.operation.gatget.arguments[self.position]
36
+ # end
37
+
38
+ # get arguments
39
+ elsif self.type == 'get' or self.type == 'get_password'
40
+
41
+ # log direct question
42
+ get_question = self.config['get_question'] || "Gatget need a value for argument #{ self.name } (#{ self.description })"
43
+
44
+ self.operation.gatget.logger.log("direct", 'get_argument', get_question)
45
+
46
+ system "stty -echo" if self.type == 'get_password' # remove letter echo
47
+
48
+ self.value = $stdin.gets.chomp
49
+
50
+ system "stty echo" if self.type == 'get_password' # remove letter echo
51
+
52
+ # argument missing but not required
53
+ elsif self.optional
54
+ self.operation.gatget.logger.log("info", "missing argument #{ self.name } at operation #{ self.operation.name }. Argument is marked as optional")
55
+ else
56
+ raise GatgetArgumentException.new("Missing dependence argument #{ self.name } (@#{ self.type}) ", "evalue_program_dependence")
57
+ end
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,54 @@
1
+ =begin
2
+
3
+ :file => dependences.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
+ module Dependence
26
+ class Base
27
+
28
+ attr_reader :operation
29
+ attr_reader :config
30
+ attr_reader :name
31
+ attr_reader :type
32
+ attr_reader :description
33
+
34
+
35
+ attr_accessor :value
36
+
37
+
38
+ def initialize(name, config, operation)
39
+ operation.gatget.logger.log("trace", "dependence", "Initialize dependence #{ self.class } @#{ name }")
40
+ @operation = operation
41
+ @config = config
42
+ @name = name
43
+ @description = @config['description'] || "Another #{ self.class } dependence named #{ self.name }"
44
+ end
45
+
46
+
47
+ def evalue
48
+ raise GatgetException.new("Evalue method is not available at Gat::Dependece. Create your own at #{ self.class }", 'evalue_dependence_without_type')
49
+ end
50
+
51
+ end
52
+ end
53
+ end
54
+
@@ -0,0 +1,104 @@
1
+ module Gat
2
+ module Dependence
3
+ class Folder < Base
4
+
5
+ attr_reader :value
6
+ attr_reader :path
7
+ attr_reader :config
8
+ attr_reader :mode
9
+
10
+ attr :tree
11
+
12
+ def initialize(name, config, operation)
13
+ super(name, config, operation)
14
+ @type = config['type'] || 'normal'
15
+ @tree = { }
16
+ @path = config['path'] || ''
17
+ @mode = config['mode'] || 0700
18
+ end
19
+
20
+ # Folders
21
+ def evalue
22
+ if self.path.blank?
23
+ raise GatgetConfigException.new("folder #{ self.name } doesnt have a path attribute at config", 'evalue_folder_dependence')
24
+ end
25
+
26
+ # mount directory
27
+ mounted? if self.type == 'mount'
28
+
29
+ # main folder
30
+ unless File.exists?(self.path) and File.directory?(self.path)
31
+ FileUtils.mkdir_p(self.path, :mode => self.mode)
32
+ end
33
+
34
+ # tree
35
+ if self.config['tree'] and self.config['tree'].any?
36
+ self.config['tree'].each do |subfolder|
37
+ absolut_folder = "#{ self.path }/#{ subfolder }"
38
+ unless File.exists?(absolut_folder) and File.directory?(absolut_folder)
39
+ FileUtils.mkdir_p(absolut_folder, :mode => self.mode)
40
+ end
41
+ self.tree["#{ self.name }_#{ subfolder.gsub(/\//,'_') }"] = absolut_folder
42
+ end
43
+ end
44
+ end
45
+
46
+ # Folder dependence value is special, because it can be the root folder or one subfolder at tree
47
+ # so, we dont have a value attribute but method, and this method check by folder_name, which folder do we want
48
+ def value(folder_name)
49
+ ret = ''
50
+ if folder_name == self.name
51
+ ret = self.path
52
+ elsif self.tree.any?
53
+ self.tree.each_pair do |subfolder_name, subfolder_path|
54
+ ret = subfolder_path if subfolder_name == folder_name
55
+ end
56
+ end
57
+
58
+ if ret.blank?
59
+ raise GatgetException.new("Value for folder dependence #{ folder_name } doesnt return results", "value_folders_dependence")
60
+ end
61
+ ret
62
+ end
63
+
64
+ private
65
+ # check if folder is mounted, if not, try it, if doesnt work, launch GatgetProcessException
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
71
+ end
72
+ end
73
+
74
+
75
+ # Open Unix mounts folder and test that mounts table contents main folder
76
+ def already_mounted?
77
+ mounts_file = File.open('/proc/mounts', 'r')
78
+ mounted = false
79
+ mounts_file.each_line do |mount_line|
80
+ mounted = true if mount_line.split(" ")[2].include?(self.path)
81
+ end
82
+ mounted
83
+ end
84
+
85
+
86
+ def mount_folder
87
+ self.operation.gatget.logger.log("trace", "mount_folder", "Folder #{ self.name } is not mounted. Triying to mount")
88
+
89
+ pid_open4, stdin, stdout, stderr = Open4::popen4 "mount #{ self.path }"
90
+
91
+ ignored, status_open4 = Process::waitpid2 pid_open4
92
+
93
+ if status_open4.exitstatus == 0 # try to mount_folder
94
+ self.operation.gatget.logger.log("trace", "mount_folder", "Folder #{ self.name } nicely mounted ")
95
+ ret = true
96
+ else
97
+ self.operation.gatget.logger.log("error", "mount_folder", "#{ stderr.read }")
98
+ ret = false
99
+ end
100
+ ret
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,36 @@
1
+ module Gat
2
+ module Dependence
3
+ class Program < Base
4
+
5
+ attr_reader :path
6
+
7
+ def initialize(name, config, operation)
8
+ super(name, config, operation)
9
+ @type = @config['type'] || 'external'
10
+ @path = @config['path'] || false
11
+ end
12
+
13
+ def evalue
14
+ self.path || evalue_from_shell
15
+ end
16
+
17
+ # Program is evalued through 'which' shell command
18
+ def evalue_from_shell
19
+ errors = ''
20
+ output = ''
21
+ process_id = ''
22
+ status = Open4.popen4 "which #{ self.name }" do |pid, stdin, stdout, stderr|
23
+ process_id = pid
24
+ errors = stderr.readlines.join('')
25
+ output = stdout.readlines.join('')
26
+ end
27
+
28
+ if not output.blank? and errors.blank? and status.exitstatus == 0
29
+ self.value = output.strip
30
+ else
31
+ raise GatgetConfigException.new("Dependece program #{ self.name } not found", "evalue_program_dependence")
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
data/lib/gat/email.rb ADDED
@@ -0,0 +1,80 @@
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
+ module Email
20
+
21
+ # Create and deliver a email
22
+ def create_and_deliver_email(to, email_config, deliver_config)
23
+ email = new_email(to, deliver_config.merge(email_config))
24
+ send_email(email, deliver_config)
25
+ end
26
+
27
+
28
+ def send_email(email, smtp_config)
29
+
30
+ if !smtp_config or smtp_config.empty? or !smtp_config['send_by']
31
+ raise GatgetConfigException.new('email_config is empty or missing or send_by is not defined', 'send_email')
32
+ end
33
+
34
+ domain = self.config['server_domain'] || 'localhost'
35
+ email_from = smtp_config["send_from"] || "#{ self.class.name }@#{ domain }"
36
+
37
+
38
+ case smtp_config['send_by']
39
+ when 'smtp'
40
+ server = smtp_config['smtp_config']["server"] || 'localhost'
41
+ port = smtp_config['smtp_config']["port"] || 25
42
+ user = smtp_config['smtp_config']["user"] || ""
43
+ password = smtp_config['smtp_config']["password"] || ""
44
+
45
+ begin
46
+ Net::SMTP.start(server, port, server, user, password, :login) do |smtp|
47
+ smtp.send_mail email.encoded, email_from, email.destinations
48
+ end
49
+ rescue => error
50
+ raise GatgetConfigException.new(error, "send_email(smtp)",
51
+ { :message => "Error sending mail to '#{email.destinations}' on '#{server}:#{port}': #{error}" })
52
+ end
53
+
54
+ when 'sendmail'
55
+
56
+ Net::SMTP.start('localhost', 25) do |smtp|
57
+ smtp.send_mail email.encoded, email_from, email.destinations
58
+ end
59
+
60
+ else
61
+ raise GatgetConfigException.new("undefined send_mail method #{ smtp_config['send_by'] } at config", 'send_email')
62
+ end
63
+ end
64
+
65
+ def new_email(to, options = {})
66
+
67
+ options ||= Hash.new
68
+ mail = TMail::Mail.new
69
+ mail.date = Time.now
70
+ mail.to = to
71
+ mail.subject = options['subject'] || "#{ self.class.name } email report"
72
+ mail.from = options['send_from'] || "#{ self.class.name.underscore }@#{ self.config['server_name'] }"
73
+ mail.cc = options['cc'] if options['cc']
74
+ mail.bcc = options['bcc'] if options['bcc']
75
+
76
+ mail.body = options['body'] || "empty body"
77
+ mail
78
+ end
79
+ end
80
+ end