reptile 0.0.1 → 0.0.4
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/README.rdoc +47 -1
- data/Rakefile +4 -3
- data/bin/replication_status +33 -10
- data/lib/reptile/databases.rb +4 -4
- data/lib/reptile/delta_monitor.rb +17 -12
- data/lib/reptile/heartbeat.rb +14 -20
- data/lib/reptile/replication_monitor.rb +37 -12
- data/lib/reptile/runner.rb +1 -1
- data/lib/reptile/status.rb +6 -7
- data/lib/reptile/users.rb +2 -0
- data/lib/reptile.rb +1 -1
- metadata +10 -8
data/README.rdoc
CHANGED
@@ -6,6 +6,52 @@ Reptile is an easy to use utility that will monitor your MySQL replication, so y
|
|
6
6
|
|
7
7
|
A mysql replication setup.
|
8
8
|
|
9
|
+
== SYNOPSIS
|
10
|
+
|
11
|
+
Put a config file at /etc/reptile.yml, /etc/reptile/reptile.yml, ./reptile.yml, or specify one on the command line.
|
12
|
+
|
13
|
+
|
14
|
+
[nick@s34 ~]$ replication_status -h
|
15
|
+
Usage: replication_status [path_to_config_file]
|
16
|
+
-h, --help Displays this help info
|
17
|
+
-s, --status Displays the slave status
|
18
|
+
-d, --diff Checks the row count difference between master and slave
|
19
|
+
-r, --report Sends a report email
|
20
|
+
-b, --heartbeat Checks the heartbeat timestamp difference between master and slave
|
21
|
+
[nick@s34 ~]$ replication_status -s
|
22
|
+
* a_database slave is up and running
|
23
|
+
* b_database slave is up and running
|
24
|
+
* c_database slave is up and running
|
25
|
+
|
26
|
+
=== Super simple crontab setup
|
27
|
+
|
28
|
+
[nick@s34 ~]$ sudo crontab -l
|
29
|
+
Password:
|
30
|
+
MAILTO="user@example.com"
|
31
|
+
# Use the '-e' arg to only spit out errors, which will be sent out by crontab
|
32
|
+
*/15 * * * * replication_status -e
|
33
|
+
|
34
|
+
=== Setup SQL
|
35
|
+
|
36
|
+
Run this SQL to setup the DBs/perms for Reptile. Using different users, since each user requires significantly different permissions.
|
37
|
+
|
38
|
+
GRANT REPLICATION SLAVE, REPLICATION CLIENT, SUPER ON *.* TO 'repl'@"localhost" IDENTIFIED BY 'repl_user_pass';
|
39
|
+
GRANT REPLICATION SLAVE, REPLICATION CLIENT, SUPER ON *.* TO 'repl'@"MONITOR_HOST_IP" IDENTIFIED BY 'repl_user_pass';
|
40
|
+
|
41
|
+
GRANT SELECT, REPLICATION CLIENT ON *.* TO 'ro_user'@"localhost" IDENTIFIED BY 'ro_user_pass';
|
42
|
+
GRANT SELECT, REPLICATION CLIENT ON *.* TO 'ro_user'@"MONITOR_HOST_IP" IDENTIFIED BY 'ro_user_pass';
|
43
|
+
|
44
|
+
CREATE DATABASE replication_monitor;
|
45
|
+
|
46
|
+
GRANT SELECT, INSERT, UPDATE, ALTER ON replication_monitor.* TO 'heartbeat_user'@"localhost" IDENTIFIED BY 'heartbeat_user_pass';
|
47
|
+
GRANT SELECT, INSERT, UPDATE, ALTER ON replication_monitor.* TO 'heartbeat_user'@"MONITOR_HOST_IP" IDENTIFIED BY 'heartbeat_user_pass';
|
48
|
+
|
49
|
+
CREATE TABLE replication_monitor.heartbeats (
|
50
|
+
unix_time INTEGER NOT NULL,
|
51
|
+
db_time TIMESTAMP NOT NULL,
|
52
|
+
INDEX time_idx(unix_time)
|
53
|
+
)
|
54
|
+
|
9
55
|
== INSTALL:
|
10
56
|
|
11
57
|
sudo gem install reptile
|
@@ -33,4 +79,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
33
79
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
34
80
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
35
81
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
36
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
82
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -5,11 +5,12 @@ require File.dirname(__FILE__) + '/lib/reptile'
|
|
5
5
|
# Generate all the Rake tasks
|
6
6
|
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
7
7
|
$hoe = Hoe.new('reptile', Reptile::VERSION) do |p|
|
8
|
-
p.developer('
|
8
|
+
p.developer('Nick Stielau', 'nick.stielau@gmail.com')
|
9
9
|
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
10
10
|
p.post_install_message = 'PostInstall.txt'
|
11
11
|
p.rubyforge_name = p.name
|
12
12
|
p.bin_files = ["bin/replication_status"]
|
13
|
+
p.summary = "Cold-blooded MySQL replication monitoring."
|
13
14
|
p.extra_dev_deps = [
|
14
15
|
['newgem', ">= #{::Newgem::VERSION}"]
|
15
16
|
]
|
@@ -22,13 +23,13 @@ end
|
|
22
23
|
|
23
24
|
desc "Upload current documentation to Rubyforge"
|
24
25
|
task :upload_docs => [:redocs] do
|
25
|
-
sh "scp -r doc/* nstielau@rubyforge.org:/var/www/gforge-projects/reptile/doc
|
26
|
+
sh "scp -r doc/* nstielau@rubyforge.org:/var/www/gforge-projects/reptile/doc"
|
26
27
|
end
|
27
28
|
|
28
29
|
desc "Upload current documentation to Rubyforge"
|
29
30
|
task :upload_site do
|
30
31
|
#webgen && scp -r output/* nstielau@rubyforge.org:/var/www/gforge-projects/reptile/
|
31
|
-
sh "scp -r
|
32
|
+
sh "scp -r webgen_site/* nstielau@rubyforge.org:/var/www/gforge-projects/reptile/"
|
32
33
|
end
|
33
34
|
|
34
35
|
require 'newgem/tasks' # load /tasks/*.rake
|
data/bin/replication_status
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
require 'rubygems'
|
3
4
|
require 'optparse'
|
4
5
|
require 'reptile'
|
5
6
|
|
@@ -36,6 +37,10 @@ OptionParser.new do |opts|
|
|
36
37
|
opts.on("-g", "--start_slaves", "Starts all slaves") do
|
37
38
|
commands << 'start_slaves'
|
38
39
|
end
|
40
|
+
|
41
|
+
opts.on("-e", "--errors", "Show only errors.") do
|
42
|
+
commands << 'errors'
|
43
|
+
end
|
39
44
|
|
40
45
|
begin
|
41
46
|
opts.parse!(ARGV)
|
@@ -46,19 +51,37 @@ OptionParser.new do |opts|
|
|
46
51
|
end
|
47
52
|
end
|
48
53
|
|
49
|
-
|
54
|
+
if !ARGV.empty? && ARGV.length > 1
|
55
|
+
abort "Too many arguments; please specify only the directory containing the 'reptile.yml' file, or a yml config file itself."
|
56
|
+
end
|
50
57
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
58
|
+
config_file_name = "reptile.yml"
|
59
|
+
config_file_locations = ["/etc/#{config_file_name}", "/etc/reptile/#{config_file_name}", "./#{config_file_name}"]
|
60
|
+
config_location_param = ARGV.first
|
61
|
+
|
62
|
+
config_file = nil
|
63
|
+
if config_location_param
|
64
|
+
if File.directory?(config_location_param) && File.exist?(File.join(config_location_param, config_file_name))
|
65
|
+
config_file = File.join(config_location_param, config_file_name)
|
66
|
+
elsif File.exist?(config_location_param) && !File.directory?(config_location_param)
|
67
|
+
config_file = config_location_param
|
68
|
+
else
|
69
|
+
abort "Please specify the directory containing the '#{config_file_name}' file, or the config file itself."
|
70
|
+
end
|
71
|
+
else
|
72
|
+
config_file_locations.each do |f|
|
73
|
+
if File.exist?(f)
|
74
|
+
config_file = f
|
75
|
+
break
|
76
|
+
end
|
77
|
+
end
|
78
|
+
if config_file.nil?
|
79
|
+
abort "Couldn't find a config file at #{config_file_locations.join(', ')}"
|
80
|
+
end
|
59
81
|
end
|
60
82
|
|
61
|
-
|
83
|
+
|
84
|
+
Reptile::ReplicationMonitor.load_config_file(config_file)
|
62
85
|
|
63
86
|
if (commands.include?('start_slaves') || commands.include?('stop_slaves'))
|
64
87
|
Reptile::Runner.send(commands[0])
|
data/lib/reptile/databases.rb
CHANGED
@@ -22,15 +22,15 @@ private
|
|
22
22
|
|
23
23
|
def get_masters
|
24
24
|
masters = databases.dup
|
25
|
-
masters.each_key{|
|
26
|
-
masters.each_key{|
|
25
|
+
masters.each_key{|name| masters.delete(name) if masters[name]['master'].nil? }
|
26
|
+
masters.each_key{|name| masters[name] = masters[name]['master'] }
|
27
27
|
masters
|
28
28
|
end
|
29
29
|
|
30
30
|
# TODO: make private
|
31
31
|
def get_slaves
|
32
32
|
dbs = databases.dup
|
33
|
-
dbs.each_key{|name| dbs.delete(
|
33
|
+
dbs.each_key{|name| dbs.delete(name) if dbs[name]['slave'].nil? }
|
34
34
|
dbs.each_key{|name| dbs[name] = dbs[name]['slave'] }
|
35
35
|
slaves = dbs
|
36
36
|
end
|
@@ -44,7 +44,7 @@ private
|
|
44
44
|
puts "****"
|
45
45
|
puts "Error connecting to database: #{e}"
|
46
46
|
puts "****"
|
47
|
-
puts
|
47
|
+
puts configs.inspect
|
48
48
|
exit 1
|
49
49
|
end
|
50
50
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
1
3
|
module Reptile
|
2
4
|
# This monitor compares the row counts for each table for each master and slave.
|
3
5
|
class DeltaMonitor
|
@@ -12,15 +14,12 @@ module Reptile
|
|
12
14
|
@user
|
13
15
|
end
|
14
16
|
|
15
|
-
def self.
|
16
|
-
|
17
|
-
@logFileObj = File.open(logFile, "a")
|
17
|
+
def self.logger=(new_logger)
|
18
|
+
@logger = new_logger
|
18
19
|
end
|
19
|
-
|
20
|
-
def self.
|
21
|
-
|
22
|
-
puts msg
|
23
|
-
@logFileObj.puts msg
|
20
|
+
|
21
|
+
def self.get_logger
|
22
|
+
@logger ||= Logger.new(STDOUT)
|
24
23
|
end
|
25
24
|
|
26
25
|
# Retrieve the active database connection. Nil of none exists.
|
@@ -46,18 +45,24 @@ module Reptile
|
|
46
45
|
print_deltas(db_name, deltas, master_configs)
|
47
46
|
|
48
47
|
deltas
|
48
|
+
rescue Exception => e
|
49
|
+
get_logger.error "Error: Caught #{e}"
|
50
|
+
get_logger.error "DB Name: #{db_name}"
|
51
|
+
get_logger.error "Master Configs: #{master_configs.inspect}"
|
52
|
+
get_logger.error "Slave Configs: #{slave_configs.inspect}"
|
53
|
+
raise e
|
49
54
|
end
|
50
55
|
|
51
56
|
# Prints stats about the differences in number of rows between the master and slave
|
52
57
|
def self.print_deltas(db_name, deltas, configs)
|
53
58
|
non_zero_deltas = deltas.select{|table, delta| not delta.zero?}
|
54
59
|
if non_zero_deltas.size.zero?
|
55
|
-
|
60
|
+
get_logger.info "Replication counts A-OK for #{db_name} on #{configs['host']} @ #{Time.now}"
|
56
61
|
else
|
57
|
-
|
58
|
-
|
62
|
+
get_logger.info "Replication Row Count Deltas for #{db_name} on #{configs['host']} @ #{Time.now}"
|
63
|
+
get_logger.info "There #{non_zero_deltas.size > 1 ? 'are' : 'is'} #{non_zero_deltas.size} #{non_zero_deltas.size > 1 ? 'deltas' : 'delta'}"
|
59
64
|
non_zero_deltas.each do |table, delta|
|
60
|
-
|
65
|
+
get_logger.info " #{table} table: #{delta}" unless delta.zero?
|
61
66
|
end
|
62
67
|
end
|
63
68
|
end
|
data/lib/reptile/heartbeat.rb
CHANGED
@@ -28,23 +28,22 @@ module Reptile
|
|
28
28
|
def self.user
|
29
29
|
@user ||= {}
|
30
30
|
end
|
31
|
-
|
32
|
-
# Merge the connection settings in the configs parameter with HeartBeat defaults.
|
31
|
+
|
33
32
|
def self.connect(configs)
|
34
|
-
|
33
|
+
Databases.connect(configs.merge(user).merge("database" => 'replication_monitor'))
|
35
34
|
end
|
36
35
|
|
37
36
|
# Write a heartbeat.
|
38
37
|
# Thump thump.
|
39
38
|
def self.write(name, configs)
|
40
|
-
connect(configs)
|
39
|
+
self.connect(configs)
|
41
40
|
heartbeat = Heartbeat.create(:unix_time => Time.now.to_i, :db_time => "NOW()")
|
42
|
-
|
41
|
+
get_logger.info "Wrote heartbeat to #{name} at #{Time.at(heartbeat.unix_time)}"
|
43
42
|
end
|
44
43
|
|
45
44
|
# Read the most recent heartbeat and return the delay in seconds, or nil if no heartbeat are found.
|
46
45
|
def self.read(name, configs)
|
47
|
-
connect(configs)
|
46
|
+
self.connect(configs)
|
48
47
|
|
49
48
|
current_time = Time.now
|
50
49
|
|
@@ -53,7 +52,7 @@ module Reptile
|
|
53
52
|
|
54
53
|
# No heartbeats at all!
|
55
54
|
if heartbeat.nil?
|
56
|
-
|
55
|
+
get_logger.info "No heartbeats found on #{name} at #{Time.now}"
|
57
56
|
return nil;
|
58
57
|
end
|
59
58
|
|
@@ -62,26 +61,21 @@ module Reptile
|
|
62
61
|
delay = (Time.now - Time.at(heartbeat.unix_time)).round
|
63
62
|
#delay = (Time.now - heartbeat.db_time)
|
64
63
|
|
65
|
-
|
64
|
+
get_logger.info "Read heartbeat from #{name} at #{Time.at(heartbeat.unix_time)}. The delay is #{strfdelay(delay)}"
|
66
65
|
|
67
66
|
delay
|
68
67
|
end
|
69
68
|
|
70
|
-
|
71
|
-
|
72
|
-
# Open the 'heartbeat.log' file.
|
73
|
-
def self.open_log
|
74
|
-
logFile = 'heartbeat.log'
|
75
|
-
@logFileObj = File.open(logFile, "a")
|
69
|
+
def self.logger=(new_logger)
|
70
|
+
@logger = new_logger
|
76
71
|
end
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
open_log if @logFileObj.nil?
|
81
|
-
puts msg
|
82
|
-
@logFileObj.puts msg
|
72
|
+
|
73
|
+
def self.get_logger
|
74
|
+
@logger ||= Logger.new(STDOUT)
|
83
75
|
end
|
84
76
|
|
77
|
+
private
|
78
|
+
|
85
79
|
# Format the delay (in seconds) as a human-readable string.
|
86
80
|
def self.strfdelay(delay)
|
87
81
|
seconds = delay % 60
|
@@ -1,7 +1,10 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
1
3
|
module Reptile
|
2
4
|
class ReplicationMonitor
|
5
|
+
|
3
6
|
# Attempts to load the replication.yml configuration file.
|
4
|
-
def self.load_config_file(databases_file)
|
7
|
+
def self.load_config_file(databases_file)
|
5
8
|
@databases_file = databases_file
|
6
9
|
yaml = YAML::load(File.read(@databases_file))
|
7
10
|
@configs = yaml.delete('config')
|
@@ -14,8 +17,8 @@ module Reptile
|
|
14
17
|
DeltaMonitor.user = users.ro_user
|
15
18
|
Runner.databases = databases
|
16
19
|
|
17
|
-
raise "Please specify a delay
|
18
|
-
raise "Please specify a row delta
|
20
|
+
raise "Please specify a delay threshold 'delay_threshold_secs: 360'" if @configs['delay_threshold_secs'].nil?
|
21
|
+
raise "Please specify a row delta threshold 'row_difference_threshold: 10'" if @configs['row_difference_threshold'].nil?
|
19
22
|
|
20
23
|
rescue Errno::EACCES => e
|
21
24
|
puts "Unable to open config file: Permission Denied"
|
@@ -35,17 +38,25 @@ module Reptile
|
|
35
38
|
def self.users
|
36
39
|
@users
|
37
40
|
end
|
41
|
+
|
42
|
+
def self.errors
|
43
|
+
get_logger.sev_threshold = Logger::ERROR
|
44
|
+
check_slaves
|
45
|
+
heartbeat
|
46
|
+
diff_tables
|
47
|
+
end
|
38
48
|
|
39
49
|
def self.diff_tables
|
40
50
|
unsynced_dbs = 0
|
51
|
+
DeltaMonitor.logger = get_logger
|
41
52
|
|
42
|
-
databases.each_pair do |name, roles|
|
53
|
+
databases.databases.each_pair do |name, roles|
|
43
54
|
master, slave = roles['master'], roles['slave']
|
44
55
|
deltas = DeltaMonitor.diff(name, master, slave)
|
45
56
|
|
46
57
|
egregious_deltas = deltas.select{|table, delta| delta > configs['row_difference_threshold'] }
|
47
58
|
if egregious_deltas.size > 0
|
48
|
-
queue_replication_warning :host => master[
|
59
|
+
queue_replication_warning :host => master["host"], :database => master["database"], :deltas => egregious_deltas, :noticed_at => Time.now
|
49
60
|
unsynced_dbs += 1
|
50
61
|
end
|
51
62
|
end
|
@@ -54,14 +65,15 @@ module Reptile
|
|
54
65
|
end
|
55
66
|
|
56
67
|
def self.heartbeat
|
57
|
-
|
58
|
-
|
68
|
+
Heartbeat.logger = get_logger
|
69
|
+
|
70
|
+
databases.masters.each_pair do |name, configs|
|
71
|
+
Heartbeat.write(name, configs)
|
59
72
|
end
|
60
73
|
|
61
74
|
overdue_slaves = 0
|
62
75
|
|
63
|
-
databases.
|
64
|
-
db_configs = databases[name]['slave']
|
76
|
+
databases.slaves.each_pair do |name, db_configs|
|
65
77
|
delay = Heartbeat.read(name, db_configs)
|
66
78
|
if delay.nil?
|
67
79
|
queue_replication_warning :host => name,
|
@@ -85,8 +97,9 @@ module Reptile
|
|
85
97
|
def self.check_slaves
|
86
98
|
databases.slaves.each do |slave_name, slave_configs|
|
87
99
|
status = Status.check_slave_status(slave_name, slave_configs)
|
100
|
+
get_logger.info "'#{slave_name}' is '#{status}'"
|
88
101
|
if status != Status.const_get(:RUNNING)
|
89
|
-
queue_replication_warning :host =>
|
102
|
+
queue_replication_warning :host => slave_name,
|
90
103
|
:database => configs[:database],
|
91
104
|
:status_error => Status.get_error_message(status),
|
92
105
|
:noticed_at => Time.now
|
@@ -101,7 +114,7 @@ module Reptile
|
|
101
114
|
email.body = ''
|
102
115
|
|
103
116
|
if options[:delay]
|
104
|
-
email.body += "There was a #{delay} second replication latency, which is greater than the allowed latency of #{configs['delay_threshold_secs']} seconds"
|
117
|
+
email.body += "There was a #{options[:delay]} second replication latency, which is greater than the allowed latency of #{configs['delay_threshold_secs']} seconds"
|
105
118
|
elsif options[:deltas]
|
106
119
|
email.body += "The following tables have master/slave row count difference greater than the allowed #{configs['row_difference_threshold']}\n\n"
|
107
120
|
options[:deltas].each do |table, delta|
|
@@ -115,8 +128,11 @@ module Reptile
|
|
115
128
|
|
116
129
|
email.body += "\n"
|
117
130
|
email.body += " Server: #{options[:host]}\n"
|
118
|
-
email.body += "
|
131
|
+
email.body += " Database: #{options[:database]}\n" unless options[:database].blank?
|
119
132
|
|
133
|
+
# Print out email body to STDOUT
|
134
|
+
get_logger.error email.body
|
135
|
+
|
120
136
|
send_email(email)
|
121
137
|
end
|
122
138
|
|
@@ -189,6 +205,9 @@ module Reptile
|
|
189
205
|
end
|
190
206
|
|
191
207
|
def self.send_email(email)
|
208
|
+
return unless configs['email_server'] && configs['email_port'] && configs['email_domain'] &&
|
209
|
+
configs['email_password'] && configs['email_auth_type']
|
210
|
+
|
192
211
|
# TODO: could do Net::SMTP.respond_to?(enable_tls) ? enable_TLS : puts "Install TLS gem to use SSL/TLS"
|
193
212
|
Net::SMTP.enable_tls(OpenSSL::SSL::VERIFY_NONE)
|
194
213
|
Net::SMTP.start(configs['email_server'],
|
@@ -220,5 +239,11 @@ module Reptile
|
|
220
239
|
# end
|
221
240
|
end
|
222
241
|
|
242
|
+
private
|
243
|
+
|
244
|
+
def self.get_logger
|
245
|
+
@@logger ||= Logger.new(STDOUT)
|
246
|
+
end
|
247
|
+
|
223
248
|
end
|
224
249
|
end
|
data/lib/reptile/runner.rb
CHANGED
@@ -29,7 +29,7 @@ module Reptile
|
|
29
29
|
configs.delete('port')
|
30
30
|
configs.delete('host')
|
31
31
|
# With activeRecord, you have to connect to some DB, even if you are acting on the server...
|
32
|
-
configs['database'] = 'information_schema'
|
32
|
+
configs['database'] = 'information_schema' unless configs['database']
|
33
33
|
# TODO: Delete these somewhere else
|
34
34
|
configs.delete('heartbeat')
|
35
35
|
configs.delete('replication_user')
|
data/lib/reptile/status.rb
CHANGED
@@ -29,8 +29,7 @@ module Reptile
|
|
29
29
|
|
30
30
|
# The user settings for a user that has global select privilidgess
|
31
31
|
def self.user
|
32
|
-
|
33
|
-
@user
|
32
|
+
@user ||= {}
|
34
33
|
end
|
35
34
|
|
36
35
|
# Checks the value of the MySQL command "SHOW SLAVE STATUS".
|
@@ -38,13 +37,13 @@ module Reptile
|
|
38
37
|
def self.check_slave_status(name, configs)
|
39
38
|
# TODO: Do this in Databases
|
40
39
|
configs.delete("port")
|
41
|
-
configs
|
42
|
-
|
43
|
-
if
|
40
|
+
Databases.connect(configs.merge(user).merge('database' => 'information_schema')).execute('SHOW SLAVE STATUS').each_hash do |hash|
|
41
|
+
|
42
|
+
if hash['Slave_SQL_Running'] == "No"
|
44
43
|
return SQL_THREAD_DOWN
|
45
|
-
elsif
|
44
|
+
elsif hash['Slave_IO_Running'] == "No"
|
46
45
|
return IO_THREAD_DOWN
|
47
|
-
elsif
|
46
|
+
elsif hash['Slave_Running'] == "No"
|
48
47
|
return SLAVE_DOWN
|
49
48
|
else
|
50
49
|
return RUNNING
|
data/lib/reptile/users.rb
CHANGED
data/lib/reptile.rb
CHANGED
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reptile
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Nick Stielau
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
13
|
-
default_executable:
|
12
|
+
date: 2009-08-13 00:00:00 -07:00
|
13
|
+
default_executable: replication_status
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: newgem
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
version:
|
35
35
|
description: ""
|
36
36
|
email:
|
37
|
-
-
|
37
|
+
- nick.stielau@gmail.com
|
38
38
|
executables:
|
39
39
|
- replication_status
|
40
40
|
extensions: []
|
@@ -66,7 +66,9 @@ files:
|
|
66
66
|
- test/test_helper.rb
|
67
67
|
- test/test_reptile.rb
|
68
68
|
has_rdoc: true
|
69
|
-
homepage:
|
69
|
+
homepage: http://reptile.rubyforge.org/
|
70
|
+
licenses: []
|
71
|
+
|
70
72
|
post_install_message: PostInstall.txt
|
71
73
|
rdoc_options:
|
72
74
|
- --main
|
@@ -88,10 +90,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
90
|
requirements: []
|
89
91
|
|
90
92
|
rubyforge_project: reptile
|
91
|
-
rubygems_version: 1.3.
|
93
|
+
rubygems_version: 1.3.5
|
92
94
|
signing_key:
|
93
95
|
specification_version: 2
|
94
|
-
summary:
|
96
|
+
summary: Cold-blooded MySQL replication monitoring.
|
95
97
|
test_files:
|
96
98
|
- test/test_helper.rb
|
97
99
|
- test/test_reptile.rb
|