repctl 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/bin/repctl +13 -121
- data/config/servers.yml +4 -0
- data/lib/repctl/color.rb +61 -0
- data/lib/repctl/helpers.rb +146 -0
- data/lib/repctl/mysql_admin.rb +8 -33
- data/lib/repctl/servers.rb +13 -3
- data/lib/repctl/version.rb +1 -1
- data/lib/repctl.rb +5 -3
- data/repctl.gemspec +5 -0
- data/webserver/public/images/wait30.gif +0 -0
- data/webserver/sass/config.rb +24 -0
- data/webserver/sass/sass/ie.scss +5 -0
- data/webserver/sass/sass/print.scss +3 -0
- data/webserver/sass/sass/screen.scss +6 -0
- data/webserver/sass/stylesheets/ie.css +5 -0
- data/webserver/sass/stylesheets/print.css +3 -0
- data/webserver/sass/stylesheets/screen.css +68 -0
- data/webserver/views/layout.erb +80 -0
- data/webserver/views/main.erb +38 -0
- data/webserver/views/operation_complete.erb +5 -0
- data/webserver/views/status.erb +24 -0
- data/webserver/webserver.rb +108 -0
- metadata +67 -8
data/.gitignore
CHANGED
data/bin/repctl
CHANGED
@@ -5,34 +5,6 @@ require 'fileutils'
|
|
5
5
|
require 'repctl'
|
6
6
|
require 'thor'
|
7
7
|
|
8
|
-
module Repctl
|
9
|
-
module Helpers
|
10
|
-
def do_stop(instance)
|
11
|
-
do_admin(instance, "shutdown")
|
12
|
-
end
|
13
|
-
|
14
|
-
def do_reset(instance)
|
15
|
-
do_stop(instance)
|
16
|
-
do_config(instance)
|
17
|
-
do_start(instance)
|
18
|
-
do_secure_accounts(instance)
|
19
|
-
end
|
20
|
-
|
21
|
-
def do_start_slave(instance)
|
22
|
-
run_mysql_query(instance, "START SLAVE")
|
23
|
-
end
|
24
|
-
|
25
|
-
def do_stop_slave(instance)
|
26
|
-
run_mysql_query(instance, "STOP SLAVE")
|
27
|
-
end
|
28
|
-
|
29
|
-
def do_restart(instance)
|
30
|
-
do_admin(instance, "shutown")
|
31
|
-
do_start(instance)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
8
|
class RepctlCmds < Thor
|
37
9
|
|
38
10
|
include Thor::Actions
|
@@ -40,6 +12,7 @@ class RepctlCmds < Thor
|
|
40
12
|
include Repctl::Commands
|
41
13
|
include Repctl::Servers
|
42
14
|
include Repctl::Helpers
|
15
|
+
include Repctl::Color
|
43
16
|
|
44
17
|
desc "start [INSTANCES]", "Start one or more defined server instances."
|
45
18
|
method_option :all, :type => :boolean, :aliases => "-a",
|
@@ -200,49 +173,12 @@ class RepctlCmds < Thor
|
|
200
173
|
method_option :servers, :aliases => "-s", :type => :array,
|
201
174
|
:desc => "Only check the status of given servers."
|
202
175
|
def status
|
203
|
-
todos = options[:servers] || all_live_instances
|
204
|
-
unless todos.any?
|
205
|
-
say "No Running Servers. Are you running as the mysql user?", :blue
|
206
|
-
return
|
207
|
-
end
|
208
176
|
header = sprintf("%-5s%-27s%-27s%-27s%-8s\n",
|
209
177
|
"inst", "master", "received", "applied", "lag")
|
210
|
-
|
211
178
|
loop do
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
coordinates = get_coordinates(i)
|
216
|
-
master_file = coordinates[:file]
|
217
|
-
master_pos = coordinates[:position]
|
218
|
-
slave = is_slave?(i)
|
219
|
-
if slave
|
220
|
-
slave_status = get_slave_status(i)
|
221
|
-
recv_file = slave_status["Master_Log_File"]
|
222
|
-
recv_pos = slave_status["Read_Master_Log_Pos"]
|
223
|
-
apply_file = slave_status["Relay_Master_Log_File"]
|
224
|
-
apply_pos = slave_status["Exec_Master_Log_Pos"]
|
225
|
-
lag = slave_status["Seconds_Behind_Master"]
|
226
|
-
master_host = slave_status["Master_Host"]
|
227
|
-
master_port = slave_status["Master_Port"]
|
228
|
-
master_instance = instance_for(master_host, master_port)
|
229
|
-
end
|
230
|
-
|
231
|
-
if slave
|
232
|
-
if lag
|
233
|
-
lag = lag.to_s
|
234
|
-
else
|
235
|
-
lag = "-"
|
236
|
-
end
|
237
|
-
format = "%1d%-4s%16s:%-10d%16s:%-10d%16s:%-10d%-8s"
|
238
|
-
str = sprintf(format, i, "(#{master_instance.to_s})", master_file,
|
239
|
-
master_pos, recv_file, recv_pos, apply_file, apply_pos, lag)
|
240
|
-
else
|
241
|
-
format = "%-5d%16s:%-10d"
|
242
|
-
str = sprintf(format, i, master_file, master_pos)
|
243
|
-
end
|
244
|
-
|
245
|
-
say str + "\n", :yellow
|
179
|
+
output = formatted_status(options)
|
180
|
+
output.each do |line|
|
181
|
+
puts line
|
246
182
|
end
|
247
183
|
break unless options[:continuous]
|
248
184
|
sleep options[:continuous]
|
@@ -255,8 +191,7 @@ class RepctlCmds < Thor
|
|
255
191
|
coordinates = do_dump(instance, dumpfile)
|
256
192
|
file = coordinates[:file]
|
257
193
|
position = coordinates[:position]
|
258
|
-
|
259
|
-
[file, String(position)]
|
194
|
+
say "Dumped at coordinates (#{file}, #{position})", :green
|
260
195
|
end
|
261
196
|
|
262
197
|
desc "restore INSTANCE [DUMPFILE]", "Restore INSTANCE from a \'mysqldump\' file DUMPFILE."
|
@@ -269,25 +204,14 @@ class RepctlCmds < Thor
|
|
269
204
|
# master has existing data.
|
270
205
|
#
|
271
206
|
desc "add_slave MASTER SLAVE", "Master has some data that is used to initialize the slave."
|
272
|
-
method_option :populate, :type => :boolean, :default => false
|
273
207
|
def add_slave(master, slave)
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
invoke "utils:bench", [master, "/opt/MySQL/b2.properties"]
|
278
|
-
end
|
279
|
-
file, position = invoke "dump", [master]
|
280
|
-
|
281
|
-
# Slave is running, but it is not yet configured as a slave.
|
282
|
-
# Load slave from the dump file...
|
283
|
-
invoke "restore", [slave]
|
284
|
-
|
285
|
-
do_change_master(master, slave, :file => file, :position => position)
|
286
|
-
do_start_slave(slave)
|
287
|
-
|
288
|
-
do_cluster_user(slave)
|
289
|
-
do_repl_user(slave)
|
208
|
+
dumpfile = DEFAULT_DUMPFILE
|
209
|
+
do_add_slave(master, slave, dumpfile)
|
210
|
+
end
|
290
211
|
|
212
|
+
desc "remove_slave SLAVE", "Remove a slave from the replica set."
|
213
|
+
def remove_slave(slave)
|
214
|
+
do_remove_slave(slave)
|
291
215
|
end
|
292
216
|
|
293
217
|
DEFAULT_MASTER = 1
|
@@ -385,16 +309,7 @@ class RepctlCmds < Thor
|
|
385
309
|
"Set up a single master/slave replication pair from the very beginning."
|
386
310
|
def repl_pair(master, slave)
|
387
311
|
say "master is #{master}, slave is #{slave}", :green
|
388
|
-
|
389
|
-
do_reset(slave)
|
390
|
-
do_cluster_user(master)
|
391
|
-
do_repl_user(master)
|
392
|
-
coordinates = get_coordinates(master)
|
393
|
-
file = coordinates[:file]
|
394
|
-
position = coordinates[:position]
|
395
|
-
say "File is #{file}, Position is #{position}", :green
|
396
|
-
do_change_master(master, slave, :file => file, :position => position)
|
397
|
-
do_start_slave(slave)
|
312
|
+
do_repl_pair(master, slave)
|
398
313
|
end
|
399
314
|
|
400
315
|
desc "repl_trio MASTER SLAVE1 SLAVE2",
|
@@ -402,30 +317,7 @@ class RepctlCmds < Thor
|
|
402
317
|
method_option :reset, :type => :boolean, :default => true
|
403
318
|
def repl_trio(master, slave1, slave2)
|
404
319
|
say "master is #{master}, slaves are #{slave1} and #{slave2}", :green
|
405
|
-
|
406
|
-
do_reset(master)
|
407
|
-
do_reset(slave1)
|
408
|
-
do_reset(slave2)
|
409
|
-
else
|
410
|
-
do_restart(master)
|
411
|
-
do_restart(slave1)
|
412
|
-
do_restart(slave2)
|
413
|
-
end
|
414
|
-
# Set up the replication accounts for all servers, in case we
|
415
|
-
# decide to switch masters later.
|
416
|
-
[master, slave1, slave2].each do |s|
|
417
|
-
do_cluster_user(s)
|
418
|
-
do_repl_user(s)
|
419
|
-
end
|
420
|
-
|
421
|
-
coordinates = get_coordinates(master)
|
422
|
-
file = coordinates[:file]
|
423
|
-
position = coordinates[:position]
|
424
|
-
say "File is #{file}, Position is #{position}", :green
|
425
|
-
do_change_master(master, slave1, :file => file, :position => position)
|
426
|
-
do_start_slave(slave1)
|
427
|
-
do_change_master(master, slave2, :file => file, :position => position)
|
428
|
-
do_start_slave(slave2)
|
320
|
+
do_repl_trio(master, slave1, slave2, options)
|
429
321
|
end
|
430
322
|
|
431
323
|
desc "install_sample_configs DIRECTORY", "After initial install, use these "
|
data/config/servers.yml
CHANGED
@@ -9,6 +9,7 @@
|
|
9
9
|
innodb_data_home_dir: /opt/MySQL/instances/data1
|
10
10
|
innodb_log_group_home_dir: /opt/MySQL/instances/data1
|
11
11
|
pid-file: /opt/MySQL/instances/data1/deimos.pid
|
12
|
+
user: _mysql
|
12
13
|
|
13
14
|
- instance: 2
|
14
15
|
defaults-file: "/opt/projects/repctl/config/mysql.cnf"
|
@@ -20,6 +21,7 @@
|
|
20
21
|
innodb_data_home_dir: /opt/MySQL/instances/data2
|
21
22
|
innodb_log_group_home_dir: /opt/MySQL/instances/data2
|
22
23
|
pid-file: /opt/MySQL/instances/data2/deimos.pid
|
24
|
+
user: _mysql
|
23
25
|
|
24
26
|
- instance: 3
|
25
27
|
defaults-file: "/opt/projects/repctl/config/mysql.cnf"
|
@@ -31,6 +33,7 @@
|
|
31
33
|
innodb_data_home_dir: /opt/MySQL/instances/data3
|
32
34
|
innodb_log_group_home_dir: /opt/MySQL/instances/data3
|
33
35
|
pid-file: /opt/MySQL/instances/data3/deimos.pid
|
36
|
+
user: _mysql
|
34
37
|
|
35
38
|
- instance: 4
|
36
39
|
defaults-file: "/opt/projects/repctl/config/mysql.cnf"
|
@@ -42,4 +45,5 @@
|
|
42
45
|
innodb_data_home_dir: /opt/MySQL/instances/data4
|
43
46
|
innodb_log_group_home_dir: /opt/MySQL/instances/data4
|
44
47
|
pid-file: /opt/MySQL/instances/data4/deimos.pid
|
48
|
+
user: _mysql
|
45
49
|
|
data/lib/repctl/color.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
module Repctl
|
2
|
+
module Color
|
3
|
+
module Constants
|
4
|
+
|
5
|
+
# Embed in a String to clear all previous ANSI sequences.
|
6
|
+
CLEAR = "\e[0m"
|
7
|
+
# The start of an ANSI bold sequence.
|
8
|
+
BOLD = "\e[1m"
|
9
|
+
|
10
|
+
# Set the terminal's foreground ANSI color to black.
|
11
|
+
BLACK = "\e[30m"
|
12
|
+
# Set the terminal's foreground ANSI color to red.
|
13
|
+
RED = "\e[31m"
|
14
|
+
# Set the terminal's foreground ANSI color to green.
|
15
|
+
GREEN = "\e[32m"
|
16
|
+
# Set the terminal's foreground ANSI color to yellow.
|
17
|
+
YELLOW = "\e[33m"
|
18
|
+
# Set the terminal's foreground ANSI color to blue.
|
19
|
+
BLUE = "\e[34m"
|
20
|
+
# Set the terminal's foreground ANSI color to magenta.
|
21
|
+
MAGENTA = "\e[35m"
|
22
|
+
# Set the terminal's foreground ANSI color to cyan.
|
23
|
+
CYAN = "\e[36m"
|
24
|
+
# Set the terminal's foreground ANSI color to white.
|
25
|
+
WHITE = "\e[37m"
|
26
|
+
|
27
|
+
# Set the terminal's background ANSI color to black.
|
28
|
+
ON_BLACK = "\e[40m"
|
29
|
+
# Set the terminal's background ANSI color to red.
|
30
|
+
ON_RED = "\e[41m"
|
31
|
+
# Set the terminal's background ANSI color to green.
|
32
|
+
ON_GREEN = "\e[42m"
|
33
|
+
# Set the terminal's background ANSI color to yellow.
|
34
|
+
ON_YELLOW = "\e[43m"
|
35
|
+
# Set the terminal's background ANSI color to blue.
|
36
|
+
ON_BLUE = "\e[44m"
|
37
|
+
# Set the terminal's background ANSI color to magenta.
|
38
|
+
ON_MAGENTA = "\e[45m"
|
39
|
+
# Set the terminal's background ANSI color to cyan.
|
40
|
+
ON_CYAN = "\e[46m"
|
41
|
+
# Set the terminal's background ANSI color to white.
|
42
|
+
ON_WHITE = "\e[47m"
|
43
|
+
end
|
44
|
+
|
45
|
+
# Set color by using a string or one of the defined constants. If a third
|
46
|
+
# option is set to true, it also adds bold to the string. This is based
|
47
|
+
# on Highline implementation and it automatically appends CLEAR to the end
|
48
|
+
# of the returned String.
|
49
|
+
#
|
50
|
+
def colorize(color, bold = false)
|
51
|
+
color = Constants.const_get(color.to_s.upcase) if color.is_a?(Symbol)
|
52
|
+
bold = bold ? Constants::BOLD : ""
|
53
|
+
"#{bold}#{color}#{self.to_s}#{Constants::CLEAR}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
String.class_eval do
|
59
|
+
include Repctl::Color
|
60
|
+
end
|
61
|
+
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module Repctl
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
include Commands
|
5
|
+
include Servers
|
6
|
+
|
7
|
+
def do_stop(instance)
|
8
|
+
do_admin(instance, "shutdown")
|
9
|
+
end
|
10
|
+
|
11
|
+
def do_reset(instance)
|
12
|
+
do_stop(instance)
|
13
|
+
do_config(instance)
|
14
|
+
do_start(instance)
|
15
|
+
do_secure_accounts(instance)
|
16
|
+
end
|
17
|
+
|
18
|
+
def do_start_slave(instance)
|
19
|
+
run_mysql_query(instance, "START SLAVE")
|
20
|
+
end
|
21
|
+
|
22
|
+
def do_stop_slave(instance)
|
23
|
+
run_mysql_query(instance, "STOP SLAVE")
|
24
|
+
end
|
25
|
+
|
26
|
+
def do_restart(instance)
|
27
|
+
do_admin(instance, "shutown")
|
28
|
+
do_start(instance)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Generate an array of hashes, one hash per fabric-wide instance.
|
32
|
+
def repl_status(options = {})
|
33
|
+
todos = options[:servers] || all_live_instances
|
34
|
+
return [] unless todos.any?
|
35
|
+
status_array = []
|
36
|
+
todos.each do |i|
|
37
|
+
coordinates = get_coordinates(i)
|
38
|
+
next unless coordinates
|
39
|
+
master_file = coordinates[:file]
|
40
|
+
master_pos = coordinates[:position]
|
41
|
+
|
42
|
+
fields = {}
|
43
|
+
fields[:instance] = i.to_s
|
44
|
+
fields[:server] = "#{server_for_instance(i)['hostname']}:#{i}"
|
45
|
+
fields[:generated_binlog] = "#{master_file}:#{master_pos}"
|
46
|
+
if is_slave?(i)
|
47
|
+
slave_status = get_slave_status(i)
|
48
|
+
recv_file = slave_status["Master_Log_File"]
|
49
|
+
recv_pos = slave_status["Read_Master_Log_Pos"]
|
50
|
+
apply_file = slave_status["Relay_Master_Log_File"]
|
51
|
+
apply_pos = slave_status["Exec_Master_Log_Pos"]
|
52
|
+
lag = slave_status["Seconds_Behind_Master"]
|
53
|
+
master_host = slave_status["Master_Host"]
|
54
|
+
master_port = slave_status["Master_Port"]
|
55
|
+
master_instance = instance_for(master_host, master_port)
|
56
|
+
|
57
|
+
fields[:applied_binlog] = "#{apply_file}:#{apply_pos}"
|
58
|
+
fields[:received_binlog] = "#{recv_file}:#{recv_pos}"
|
59
|
+
fields[:master] = "#{master_host}:#{master_instance}"
|
60
|
+
fields[:lag] = lag
|
61
|
+
end
|
62
|
+
status_array << fields
|
63
|
+
end
|
64
|
+
status_array
|
65
|
+
end
|
66
|
+
|
67
|
+
def formatted_status(options = {})
|
68
|
+
output = []
|
69
|
+
header = sprintf("%-5s%-27s%-27s%-27s%-8s",
|
70
|
+
"inst", "master", "received", "applied", "lag")
|
71
|
+
output << header.colorize(:green)
|
72
|
+
todos = repl_status(options)
|
73
|
+
todos.each do |server|
|
74
|
+
instance = server[:instance]
|
75
|
+
gen_binlog = server[:generated_binlog]
|
76
|
+
if server[:master]
|
77
|
+
server[:master].match(/.*:(\d*)$/)
|
78
|
+
master_instance = $1
|
79
|
+
recv_binlog = server[:received_binlog]
|
80
|
+
app_binlog = server[:applied_binlog]
|
81
|
+
lag = server[:lag]
|
82
|
+
if lag == nil
|
83
|
+
lag = "-"
|
84
|
+
else
|
85
|
+
lag = lag.to_s
|
86
|
+
end
|
87
|
+
format = "%1d%-4s%-27s%-27s%-27s%-8s"
|
88
|
+
str = sprintf(format, instance, "(#{master_instance})",
|
89
|
+
gen_binlog, recv_binlog, app_binlog, lag)
|
90
|
+
else
|
91
|
+
format = "%-5d%-26s"
|
92
|
+
str = sprintf(format, instance, gen_binlog)
|
93
|
+
end
|
94
|
+
output << str.colorize(:yellow)
|
95
|
+
end
|
96
|
+
output
|
97
|
+
end
|
98
|
+
|
99
|
+
def do_add_slave(master, slave, dumpfile)
|
100
|
+
do_reset(slave)
|
101
|
+
coordinates = do_dump(master, dumpfile)
|
102
|
+
do_restore(slave, dumpfile)
|
103
|
+
do_change_master(master, slave, coordinates)
|
104
|
+
do_start_slave(slave)
|
105
|
+
do_cluster_user(slave)
|
106
|
+
do_repl_user(slave)
|
107
|
+
end
|
108
|
+
|
109
|
+
def do_repl_pair(master, slave)
|
110
|
+
do_reset(master)
|
111
|
+
do_reset(slave)
|
112
|
+
do_cluster_user(master)
|
113
|
+
do_repl_user(master)
|
114
|
+
coordinates = get_coordinates(master)
|
115
|
+
file = coordinates[:file]
|
116
|
+
position = coordinates[:position]
|
117
|
+
do_change_master(master, slave, :file => file, :position => position)
|
118
|
+
do_start_slave(slave)
|
119
|
+
end
|
120
|
+
|
121
|
+
def do_repl_trio(master, slave1, slave2, options = {})
|
122
|
+
if options[:reset]
|
123
|
+
do_reset(master)
|
124
|
+
do_reset(slave1)
|
125
|
+
do_reset(slave2)
|
126
|
+
else
|
127
|
+
do_restart(master)
|
128
|
+
do_restart(slave1)
|
129
|
+
do_restart(slave2)
|
130
|
+
end
|
131
|
+
# Set up the replication accounts for all servers, in case we
|
132
|
+
# decide to switch masters later.
|
133
|
+
[master, slave1, slave2].each do |s|
|
134
|
+
do_cluster_user(s)
|
135
|
+
do_repl_user(s)
|
136
|
+
end
|
137
|
+
coordinates = get_coordinates(master)
|
138
|
+
file = coordinates[:file]
|
139
|
+
position = coordinates[:position]
|
140
|
+
do_change_master(master, slave1, :file => file, :position => position)
|
141
|
+
do_start_slave(slave1)
|
142
|
+
do_change_master(master, slave2, :file => file, :position => position)
|
143
|
+
do_start_slave(slave2)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
data/lib/repctl/mysql_admin.rb
CHANGED
@@ -7,7 +7,6 @@ module Repctl
|
|
7
7
|
|
8
8
|
class Client < DelegateClass(Mysql2::Client)
|
9
9
|
include Servers
|
10
|
-
|
11
10
|
@@clients = {}
|
12
11
|
|
13
12
|
def initialize(instance, opts)
|
@@ -36,7 +35,6 @@ module Repctl
|
|
36
35
|
while timeout >= 0
|
37
36
|
begin
|
38
37
|
@@clients[instance] ||= Client.new(instance, opts)
|
39
|
-
# puts "Connected to instance #{instance}."
|
40
38
|
break
|
41
39
|
rescue Mysql2::Error => e
|
42
40
|
puts "#{e.message}, retrying connection to instance #{instance}..."
|
@@ -59,7 +57,6 @@ module Repctl
|
|
59
57
|
@@clients[@instance] = nil
|
60
58
|
Client.open(@instance)
|
61
59
|
end
|
62
|
-
|
63
60
|
end
|
64
61
|
|
65
62
|
module Commands
|
@@ -131,7 +128,7 @@ module Repctl
|
|
131
128
|
"--innodb_log_group_home_dir=#{server['innodb_log_group_home_dir']}",
|
132
129
|
"--relay-log=#{Socket.gethostname}-relay-bin",
|
133
130
|
"--socket=#{server['socket']}",
|
134
|
-
"--user
|
131
|
+
"--user=#{server['user']}")
|
135
132
|
end
|
136
133
|
end
|
137
134
|
end
|
@@ -415,14 +412,6 @@ EOT
|
|
415
412
|
client.close if client
|
416
413
|
end
|
417
414
|
|
418
|
-
# Return the process ID (pid) for an instance.
|
419
|
-
def get_mysqld_pid(instance)
|
420
|
-
server = server_for_instance(instance)
|
421
|
-
pidfile = server['pid-file']
|
422
|
-
return nil unless File.exist?(pidfile)
|
423
|
-
Integer(File.open(pidfile, &:readline).strip)
|
424
|
-
end
|
425
|
-
|
426
415
|
# 'master' is currently a slave that is to be the new master.
|
427
416
|
# 'slaves' contains the list of slaves, one of these may be the
|
428
417
|
# current master.
|
@@ -448,6 +437,13 @@ EOT
|
|
448
437
|
end
|
449
438
|
end
|
450
439
|
|
440
|
+
def do_remove_slave(instance)
|
441
|
+
stop_slave_io_thread(instance)
|
442
|
+
server = server_for_instance(instance)
|
443
|
+
datadir = server['datadir']
|
444
|
+
%x{ rm -f #{File.join(datadir, 'master.info')} }
|
445
|
+
end
|
446
|
+
|
451
447
|
private
|
452
448
|
|
453
449
|
# This is an example template to create commands to issue queries.
|
@@ -596,30 +592,9 @@ EOT
|
|
596
592
|
client.close
|
597
593
|
end
|
598
594
|
end
|
599
|
-
|
600
|
-
|
601
|
-
|
602
595
|
end
|
603
596
|
end
|
604
597
|
|
605
|
-
class RunExamples
|
606
|
-
include Repctl::Commands
|
607
|
-
|
608
|
-
def runtest
|
609
|
-
|
610
|
-
switch_master_to(3)
|
611
|
-
=begin
|
612
|
-
(1..4).each {|i| ensure_running(i)}
|
613
|
-
puts get_master_coordinates(1)
|
614
|
-
(2..4).each {|i| puts get_slave_coordinates(i)}
|
615
|
-
(1..4).each {|i| puts is_master?(i) }
|
616
|
-
puts "Master is #{find_master}"
|
617
|
-
drain_relay_log(2)
|
618
|
-
# sleep(10)
|
619
|
-
# (1..4).each {|i| crash(i)}
|
620
|
-
=end
|
621
|
-
end
|
622
|
-
end
|
623
598
|
|
624
599
|
|
625
600
|
|
data/lib/repctl/servers.rb
CHANGED
@@ -23,7 +23,13 @@ module Repctl
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def all_live_servers
|
26
|
-
all_servers.select
|
26
|
+
s = all_servers.select do |s|
|
27
|
+
if pid = get_mysqld_pid(s["instance"])
|
28
|
+
mysqld_running?(pid)
|
29
|
+
else
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
27
33
|
end
|
28
34
|
|
29
35
|
def all_live_instances
|
@@ -43,9 +49,13 @@ module Repctl
|
|
43
49
|
return nil
|
44
50
|
end
|
45
51
|
|
46
|
-
|
52
|
+
# See if a MySQL server with the given pid is running.
|
53
|
+
def mysqld_running?(pid)
|
54
|
+
pids = %x{ ps -e | grep mysqld}.split("\n").map { |row| row =~ /\s*(\d+)\s+/; $1.to_i}
|
55
|
+
pids.include?(pid)
|
56
|
+
end
|
47
57
|
|
48
|
-
# Return the process ID (pid) for an instance.
|
58
|
+
# Return the process ID (pid) for an instance. This only consults the PID file.
|
49
59
|
def get_mysqld_pid(instance)
|
50
60
|
server = server_for_instance(instance)
|
51
61
|
pidfile = server['pid-file']
|
data/lib/repctl/version.rb
CHANGED
data/lib/repctl.rb
CHANGED
@@ -4,9 +4,11 @@ config_dir = ENV["REPCTL_CONFIG_DIR"] ||
|
|
4
4
|
|
5
5
|
require File.join(config_dir, 'config')
|
6
6
|
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
7
|
+
require 'repctl/version'
|
8
|
+
require 'repctl/servers'
|
9
|
+
require 'repctl/mysql_admin'
|
10
|
+
require 'repctl/helpers'
|
11
|
+
require 'repctl/color'
|
10
12
|
|
11
13
|
module Repctl
|
12
14
|
# Your code goes here...
|
data/repctl.gemspec
CHANGED
@@ -20,6 +20,11 @@ Gem::Specification.new do |s|
|
|
20
20
|
|
21
21
|
# specify any dependencies here; for example:
|
22
22
|
s.add_development_dependency "rspec"
|
23
|
+
s.add_development_dependency "shotgun"
|
24
|
+
s.add_development_dependency "compass"
|
23
25
|
s.add_runtime_dependency "thor"
|
24
26
|
s.add_runtime_dependency "mysql2"
|
27
|
+
s.add_runtime_dependency "sinatra"
|
28
|
+
s.add_runtime_dependency "thin"
|
29
|
+
|
25
30
|
end
|
Binary file
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Require any additional compass plugins here.
|
2
|
+
|
3
|
+
# Set this to the root of your project when deployed:
|
4
|
+
http_path = "/"
|
5
|
+
css_dir = "stylesheets"
|
6
|
+
sass_dir = "sass"
|
7
|
+
images_dir = "images"
|
8
|
+
javascripts_dir = "javascripts"
|
9
|
+
|
10
|
+
# You can select your preferred output style here (can be overridden via the command line):
|
11
|
+
# output_style = :expanded or :nested or :compact or :compressed
|
12
|
+
|
13
|
+
# To enable relative paths to assets via compass helper functions. Uncomment:
|
14
|
+
# relative_assets = true
|
15
|
+
|
16
|
+
# To disable debugging comments that display the original location of your selectors. Uncomment:
|
17
|
+
# line_comments = false
|
18
|
+
|
19
|
+
|
20
|
+
# If you prefer the indented syntax, you might want to regenerate this
|
21
|
+
# project again passing --syntax sass, or you can uncomment this:
|
22
|
+
# preferred_syntax = :sass
|
23
|
+
# and then run:
|
24
|
+
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
|
@@ -0,0 +1,5 @@
|
|
1
|
+
/* Welcome to Compass. Use this file to write IE specific override styles.
|
2
|
+
* Import this file using the following HTML or equivalent:
|
3
|
+
* <!--[if IE]>
|
4
|
+
* <link href="/stylesheets/ie.css" media="screen, projection" rel="stylesheet" type="text/css" />
|
5
|
+
* <![endif]--> */
|
@@ -0,0 +1,6 @@
|
|
1
|
+
/* Welcome to Compass.
|
2
|
+
* In this file you should write your main styles. (or centralize your imports)
|
3
|
+
* Import this file using the following HTML or equivalent:
|
4
|
+
* <link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css" /> */
|
5
|
+
|
6
|
+
@import "compass/reset";
|
@@ -0,0 +1,5 @@
|
|
1
|
+
/* Welcome to Compass. Use this file to write IE specific override styles.
|
2
|
+
* Import this file using the following HTML or equivalent:
|
3
|
+
* <!--[if IE]>
|
4
|
+
* <link href="/stylesheets/ie.css" media="screen, projection" rel="stylesheet" type="text/css" />
|
5
|
+
* <![endif]--> */
|
@@ -0,0 +1,68 @@
|
|
1
|
+
/* Welcome to Compass.
|
2
|
+
* In this file you should write your main styles. (or centralize your imports)
|
3
|
+
* Import this file using the following HTML or equivalent:
|
4
|
+
* <link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css" /> */
|
5
|
+
/* line 17, ../../../../../../usr/local/rvm/gems/ruby-1.9.2-p290@rails-3.1/gems/compass-0.11.7/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
6
|
+
html, body, div, span, applet, object, iframe,
|
7
|
+
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
8
|
+
a, abbr, acronym, address, big, cite, code,
|
9
|
+
del, dfn, em, img, ins, kbd, q, s, samp,
|
10
|
+
small, strike, strong, sub, sup, tt, var,
|
11
|
+
b, u, i, center,
|
12
|
+
dl, dt, dd, ol, ul, li,
|
13
|
+
fieldset, form, label, legend,
|
14
|
+
table, caption, tbody, tfoot, thead, tr, th, td,
|
15
|
+
article, aside, canvas, details, embed,
|
16
|
+
figure, figcaption, footer, header, hgroup,
|
17
|
+
menu, nav, output, ruby, section, summary,
|
18
|
+
time, mark, audio, video {
|
19
|
+
margin: 0;
|
20
|
+
padding: 0;
|
21
|
+
border: 0;
|
22
|
+
font-size: 100%;
|
23
|
+
font: inherit;
|
24
|
+
vertical-align: baseline;
|
25
|
+
}
|
26
|
+
|
27
|
+
/* line 20, ../../../../../../usr/local/rvm/gems/ruby-1.9.2-p290@rails-3.1/gems/compass-0.11.7/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
28
|
+
body {
|
29
|
+
line-height: 1;
|
30
|
+
}
|
31
|
+
|
32
|
+
/* line 22, ../../../../../../usr/local/rvm/gems/ruby-1.9.2-p290@rails-3.1/gems/compass-0.11.7/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
33
|
+
ol, ul {
|
34
|
+
list-style: none;
|
35
|
+
}
|
36
|
+
|
37
|
+
/* line 24, ../../../../../../usr/local/rvm/gems/ruby-1.9.2-p290@rails-3.1/gems/compass-0.11.7/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
38
|
+
table {
|
39
|
+
border-collapse: collapse;
|
40
|
+
border-spacing: 0;
|
41
|
+
}
|
42
|
+
|
43
|
+
/* line 26, ../../../../../../usr/local/rvm/gems/ruby-1.9.2-p290@rails-3.1/gems/compass-0.11.7/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
44
|
+
caption, th, td {
|
45
|
+
text-align: left;
|
46
|
+
font-weight: normal;
|
47
|
+
vertical-align: middle;
|
48
|
+
}
|
49
|
+
|
50
|
+
/* line 28, ../../../../../../usr/local/rvm/gems/ruby-1.9.2-p290@rails-3.1/gems/compass-0.11.7/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
51
|
+
q, blockquote {
|
52
|
+
quotes: none;
|
53
|
+
}
|
54
|
+
/* line 101, ../../../../../../usr/local/rvm/gems/ruby-1.9.2-p290@rails-3.1/gems/compass-0.11.7/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
55
|
+
q:before, q:after, blockquote:before, blockquote:after {
|
56
|
+
content: "";
|
57
|
+
content: none;
|
58
|
+
}
|
59
|
+
|
60
|
+
/* line 30, ../../../../../../usr/local/rvm/gems/ruby-1.9.2-p290@rails-3.1/gems/compass-0.11.7/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
61
|
+
a img {
|
62
|
+
border: none;
|
63
|
+
}
|
64
|
+
|
65
|
+
/* line 114, ../../../../../../usr/local/rvm/gems/ruby-1.9.2-p290@rails-3.1/gems/compass-0.11.7/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
66
|
+
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary {
|
67
|
+
display: block;
|
68
|
+
}
|
@@ -0,0 +1,80 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8" />
|
5
|
+
<title>MySQL Replication Manager</title>
|
6
|
+
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js">
|
7
|
+
</script>
|
8
|
+
|
9
|
+
<script type="text/javascript">
|
10
|
+
/* Fix this. It should not be in the global namespace. */
|
11
|
+
function getUpdate() {
|
12
|
+
$('#status-table').load('/status');
|
13
|
+
setTimeout(getUpdate, 3000);
|
14
|
+
}
|
15
|
+
$(document).ready(function() {
|
16
|
+
getUpdate();
|
17
|
+
|
18
|
+
$('#switch-master').submit(function() {
|
19
|
+
$('.spinner').show();
|
20
|
+
$.post('/switch_master', $(this).serialize(), function(data) {
|
21
|
+
$('.spinner').hide();
|
22
|
+
$("#switch-master-result").html(data)
|
23
|
+
});
|
24
|
+
return false;
|
25
|
+
});
|
26
|
+
|
27
|
+
$('#repl-trio').submit(function() {
|
28
|
+
$('#repl-trio-spinner').show();
|
29
|
+
$.post('/repl_trio', $(this).serialize(), function(data) {
|
30
|
+
$('#repl-trio-spinner').hide();
|
31
|
+
$("#repl-trio-result").html(data)
|
32
|
+
});
|
33
|
+
return false;
|
34
|
+
});
|
35
|
+
|
36
|
+
});
|
37
|
+
</script>
|
38
|
+
|
39
|
+
<style type="text/css">
|
40
|
+
#banner {
|
41
|
+
text-align: center;
|
42
|
+
}
|
43
|
+
.spinner {
|
44
|
+
display:none;
|
45
|
+
}
|
46
|
+
.success {
|
47
|
+
color: green;
|
48
|
+
}
|
49
|
+
.failure {
|
50
|
+
color: red;
|
51
|
+
}
|
52
|
+
table.gridtable {
|
53
|
+
font-family: verdana,arial,sans-serif;
|
54
|
+
font-size:11px;
|
55
|
+
color:#333333;
|
56
|
+
border-width: 1px;
|
57
|
+
border-color: #666666;
|
58
|
+
border-collapse: collapse;
|
59
|
+
}
|
60
|
+
table.gridtable th {
|
61
|
+
border-width: 1px;
|
62
|
+
padding: 8px;
|
63
|
+
border-style: solid;
|
64
|
+
border-color: #666666;
|
65
|
+
background-color: #dedede;
|
66
|
+
}
|
67
|
+
table.gridtable td {
|
68
|
+
border-width: 1px;
|
69
|
+
padding: 8px;
|
70
|
+
border-style: solid;
|
71
|
+
border-color: #666666;
|
72
|
+
background-color: #ffffff;
|
73
|
+
}
|
74
|
+
</style>
|
75
|
+
</head>
|
76
|
+
|
77
|
+
<body>
|
78
|
+
<%= yield %>
|
79
|
+
</body>
|
80
|
+
</html>
|
@@ -0,0 +1,38 @@
|
|
1
|
+
<header id="banner">
|
2
|
+
<h1>MySQL Replication Manager</h1>
|
3
|
+
</header>
|
4
|
+
|
5
|
+
<section>
|
6
|
+
<header>
|
7
|
+
<h2>Status Summary</h2>
|
8
|
+
</header>
|
9
|
+
<div id="status-table">
|
10
|
+
</div>
|
11
|
+
</section>
|
12
|
+
|
13
|
+
<section>
|
14
|
+
<header><h2>Switch Master</h2></header>
|
15
|
+
<form id="switch-master" action="/switch_master" method="post">
|
16
|
+
<p>Master: <input type="text" name="switch[master]" size="20"/></p>
|
17
|
+
<p>Slaves: <input type="text" name="switch[slaves]" size="20"/></p>
|
18
|
+
<input type="submit" value="Switch Master">
|
19
|
+
</form>
|
20
|
+
<div>
|
21
|
+
<div style="float:left;" id="switch-master-result"></div>
|
22
|
+
<img style="float:left;" class='spinner' id="switch-master-spinner" src='images/wait30.gif' alt='spinner'></img>
|
23
|
+
</div>
|
24
|
+
</section>
|
25
|
+
|
26
|
+
<section>
|
27
|
+
<header><h2>Set up Replication Trio from Scratch</h2></header>
|
28
|
+
<form id="repl-trio" action="/repl_trio" method="post">
|
29
|
+
<p>Master: <input type="text" name="repl_trio[master]" size="20"/></p>
|
30
|
+
<p>Slaves: <input type="text" name="repl_trio[slaves]" size="20"/></p>
|
31
|
+
<input type="submit" value="Create Repliction Trio">
|
32
|
+
</form>
|
33
|
+
<div>
|
34
|
+
<div style="float:left;" id="repl-trio-result"></div>
|
35
|
+
<img style="float:left;" class="spinner" id='repl-trio-spinner' src='images/wait30.gif' alt='spinner'></img>
|
36
|
+
</div>
|
37
|
+
</section>
|
38
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<div>
|
2
|
+
Status as of <%= @timestamp %>
|
3
|
+
</div>
|
4
|
+
<table class="gridtable">
|
5
|
+
<tr>
|
6
|
+
<th>instance</th>
|
7
|
+
<th>master</th>
|
8
|
+
<th>generated binlog</th>
|
9
|
+
<th>received binlog</th>
|
10
|
+
<th>applied binlog</th>
|
11
|
+
<th>lag (secs)</th>
|
12
|
+
</tr>
|
13
|
+
<% @status_array.each do |s| %>
|
14
|
+
<tr>
|
15
|
+
<td><%= s[:server] %></td>
|
16
|
+
<td><%= s[:master] %></td>
|
17
|
+
<td><%= s[:generated_binlog] %></td>
|
18
|
+
<td><%= s[:received_binlog] %></td>
|
19
|
+
<td><%= s[:applied_binlog] %></td>
|
20
|
+
<td><%= s[:lag] %></td>
|
21
|
+
</tr>
|
22
|
+
<% end %>
|
23
|
+
</table>
|
24
|
+
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'repctl'
|
3
|
+
|
4
|
+
include Repctl::Config
|
5
|
+
include Repctl::Commands
|
6
|
+
include Repctl::Servers
|
7
|
+
include Repctl::Utils
|
8
|
+
include Repctl::Color
|
9
|
+
|
10
|
+
def time
|
11
|
+
start = Time.now
|
12
|
+
yield
|
13
|
+
Time.now - start
|
14
|
+
end
|
15
|
+
|
16
|
+
helpers do
|
17
|
+
def img(name)
|
18
|
+
"<img src='images/#{ name}' alt='#{ name}' />"
|
19
|
+
end
|
20
|
+
|
21
|
+
def master_slave_params(params)
|
22
|
+
param_error = false
|
23
|
+
@error_message = nil
|
24
|
+
if params.nil? || params["master"] == "" || params["master"].nil? ||
|
25
|
+
params["slaves"] == nil || params["slaves"] == ""
|
26
|
+
@error_message = "parameters missing"
|
27
|
+
else
|
28
|
+
begin
|
29
|
+
master = params["master"].to_i
|
30
|
+
slaves = params["slaves"].split("\s").map(&:to_i)
|
31
|
+
rescue Exception => e
|
32
|
+
@error_message = "invalid format for parameters"
|
33
|
+
else
|
34
|
+
if master == 0 || slaves.include?(0)
|
35
|
+
@error_message = "0 can not be an instance"
|
36
|
+
elsif slaves.include?(master)
|
37
|
+
@error_message = "master can not also be a slave"
|
38
|
+
elsif slaves.empty?
|
39
|
+
@error_message = "no slaves are specified"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
[@error_message, master, slaves]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
get '/' do
|
48
|
+
erb :main
|
49
|
+
end
|
50
|
+
|
51
|
+
# curl deimos:9393/switch_master --header "Accept: text/plain" \
|
52
|
+
# -d switch[slaves]="2 1 4" -d switch[master]=3
|
53
|
+
post '/switch_master' do
|
54
|
+
@message, master, slaves = master_slave_params(params["switch"])
|
55
|
+
if @message
|
56
|
+
@success = false
|
57
|
+
else
|
58
|
+
secs = time do
|
59
|
+
do_switch_master(master, slaves)
|
60
|
+
end
|
61
|
+
@message = "Switch master processed in #{secs} secs."
|
62
|
+
@success = true
|
63
|
+
end
|
64
|
+
if request.accept == ['text/plain']
|
65
|
+
if @success
|
66
|
+
"#{@message}\n".colorize(:green)
|
67
|
+
else
|
68
|
+
"#{@message}\n".colorize(:red)
|
69
|
+
end
|
70
|
+
else
|
71
|
+
erb :operation_complete, :layout => !request.xhr?
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
post '/repl_trio' do
|
76
|
+
@message, master, slaves = master_slave_params(params["repl_trio"])
|
77
|
+
if @message
|
78
|
+
@success = false
|
79
|
+
else
|
80
|
+
secs = time do
|
81
|
+
sleep 1
|
82
|
+
end
|
83
|
+
@message = "Create replication trio with master #{master} and slaves #{slaves} in #{secs} secs."
|
84
|
+
@success = true
|
85
|
+
end
|
86
|
+
if request.accept == ['text/plain']
|
87
|
+
if @success
|
88
|
+
"#{@message}\n".colorize(:green)
|
89
|
+
else
|
90
|
+
"#{@message}\n".colorize(:red)
|
91
|
+
end
|
92
|
+
else
|
93
|
+
erb :operation_complete, :layout => !request.xhr?
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# curl deimos:9393/status --header "Accept: text/plain"
|
98
|
+
get '/status' do
|
99
|
+
if request.accept == ['text/plain']
|
100
|
+
formatted_status.join("\n") + "\n"
|
101
|
+
else
|
102
|
+
@timestamp = Time.now.strftime("%I:%M:%S %p")
|
103
|
+
@status_array = repl_status
|
104
|
+
erb :status , :layout => !request.xhr?
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: repctl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-03-08 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &121456320 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,32 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *121456320
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: shotgun
|
27
|
+
requirement: &121455900 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *121455900
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: compass
|
38
|
+
requirement: &121455480 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *121455480
|
25
47
|
- !ruby/object:Gem::Dependency
|
26
48
|
name: thor
|
27
|
-
requirement: &
|
49
|
+
requirement: &121455060 !ruby/object:Gem::Requirement
|
28
50
|
none: false
|
29
51
|
requirements:
|
30
52
|
- - ! '>='
|
@@ -32,10 +54,32 @@ dependencies:
|
|
32
54
|
version: '0'
|
33
55
|
type: :runtime
|
34
56
|
prerelease: false
|
35
|
-
version_requirements: *
|
57
|
+
version_requirements: *121455060
|
36
58
|
- !ruby/object:Gem::Dependency
|
37
59
|
name: mysql2
|
38
|
-
requirement: &
|
60
|
+
requirement: &121454640 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *121454640
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sinatra
|
71
|
+
requirement: &121454220 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *121454220
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: thin
|
82
|
+
requirement: &121453800 !ruby/object:Gem::Requirement
|
39
83
|
none: false
|
40
84
|
requirements:
|
41
85
|
- - ! '>='
|
@@ -43,7 +87,7 @@ dependencies:
|
|
43
87
|
version: '0'
|
44
88
|
type: :runtime
|
45
89
|
prerelease: false
|
46
|
-
version_requirements: *
|
90
|
+
version_requirements: *121453800
|
47
91
|
description: Ruby gem with Thor script to manage MySQL and PostgreSQL replication
|
48
92
|
email:
|
49
93
|
- lydianblues@gmail.com
|
@@ -63,10 +107,25 @@ files:
|
|
63
107
|
- config/mysql.cnf
|
64
108
|
- config/servers.yml
|
65
109
|
- lib/repctl.rb
|
110
|
+
- lib/repctl/color.rb
|
111
|
+
- lib/repctl/helpers.rb
|
66
112
|
- lib/repctl/mysql_admin.rb
|
67
113
|
- lib/repctl/servers.rb
|
68
114
|
- lib/repctl/version.rb
|
69
115
|
- repctl.gemspec
|
116
|
+
- webserver/public/images/wait30.gif
|
117
|
+
- webserver/sass/config.rb
|
118
|
+
- webserver/sass/sass/ie.scss
|
119
|
+
- webserver/sass/sass/print.scss
|
120
|
+
- webserver/sass/sass/screen.scss
|
121
|
+
- webserver/sass/stylesheets/ie.css
|
122
|
+
- webserver/sass/stylesheets/print.css
|
123
|
+
- webserver/sass/stylesheets/screen.css
|
124
|
+
- webserver/views/layout.erb
|
125
|
+
- webserver/views/main.erb
|
126
|
+
- webserver/views/operation_complete.erb
|
127
|
+
- webserver/views/status.erb
|
128
|
+
- webserver/webserver.rb
|
70
129
|
homepage: ''
|
71
130
|
licenses: []
|
72
131
|
post_install_message:
|