tyrantmanager 1.0.9 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{HISTORY → HISTORY.rdoc} +6 -0
- data/{README → README.rdoc} +8 -4
- data/gemspec.rb +4 -2
- data/lib/tyrant_manager/cli.rb +9 -2
- data/lib/tyrant_manager/command.rb +1 -0
- data/lib/tyrant_manager/commands/replication_status.rb +92 -0
- data/lib/tyrant_manager/commands/stats.rb +1 -2
- data/lib/tyrant_manager/commands/status.rb +5 -1
- data/lib/tyrant_manager/tyrant_instance.rb +33 -0
- data/lib/tyrant_manager/version.rb +2 -2
- data/spec/tyrant_instance_spec.rb +23 -0
- data/tasks/config.rb +3 -3
- metadata +30 -8
data/{HISTORY → HISTORY.rdoc}
RENAMED
data/{README → README.rdoc}
RENAMED
@@ -1,9 +1,10 @@
|
|
1
1
|
== Tyrant Manager
|
2
2
|
|
3
|
-
* Homepage[http://copiousfreetime.rubyforge.org/
|
3
|
+
* Homepage[http://copiousfreetime.rubyforge.org/tyrantmanager]
|
4
4
|
* {Rubyforge project}[http://rubyforge.org/projects/copiousfreetime/]
|
5
5
|
* email jeremy at copiousfreetime dot org
|
6
|
-
*
|
6
|
+
* github[http://github.com/copiousfreetime/tyrantmanager]
|
7
|
+
* git clone git://github.com/copiousfreetime/tyrantmanager.git
|
7
8
|
|
8
9
|
== INSTALLATION
|
9
10
|
|
@@ -15,7 +16,10 @@
|
|
15
16
|
|
16
17
|
== DESCRIPTION
|
17
18
|
|
18
|
-
A command line tool for managing Tokyo Tyrant instances.
|
19
|
+
A command line tool for managing Tokyo Tyrant instances. It allows for the
|
20
|
+
creation, starting, stopping, listing, stating of many tokyo tyrant instances
|
21
|
+
all on the same machine. The commands can be applied to a single or multiple
|
22
|
+
instances.
|
19
23
|
|
20
24
|
=== Setup a manager home
|
21
25
|
|
@@ -252,7 +256,7 @@ You can also look at the server statistics of each running instance
|
|
252
256
|
|
253
257
|
== CREDITS
|
254
258
|
|
255
|
-
* Inspired by the {Light Cloud}[http://opensource.plurk.com/LightCloud/Tyrant_manager/
|
259
|
+
* Inspired by the {Light Cloud}[http://opensource.plurk.com/LightCloud/Tyrant_manager/] tyrant manager
|
256
260
|
* {Tokyo Tyrant}[http://tokyocabinet.sourceforge.net/tyrantdoc/]
|
257
261
|
|
258
262
|
== LICENSE
|
data/gemspec.rb
CHANGED
@@ -20,10 +20,12 @@ TyrantManager::GEM_SPEC = Gem::Specification.new do |spec|
|
|
20
20
|
spec.executables = pkg.files.bin.collect { |b| File.basename(b) }
|
21
21
|
|
22
22
|
# add dependencies here
|
23
|
-
# spec.add_dependency("rake", ">= 0.8.1")
|
24
23
|
spec.add_dependency( "loquacious", "~> 1.3.0")
|
25
24
|
spec.add_dependency( "rufus-tokyo", "~> 1.0.0")
|
26
|
-
|
25
|
+
spec.add_dependency( "logging", "~> 1.1.4" )
|
26
|
+
spec.add_dependency( "main", "~> 2.8.4" )
|
27
|
+
|
28
|
+
# development dependencies
|
27
29
|
spec.add_development_dependency("configuration", ">= 0.0.5")
|
28
30
|
spec.add_development_dependency( "rake", "~> 0.8.3")
|
29
31
|
|
data/lib/tyrant_manager/cli.rb
CHANGED
@@ -70,15 +70,22 @@ class TyrantManager
|
|
70
70
|
run { Cli.run_command_with_params( 'stop', params ) }
|
71
71
|
}
|
72
72
|
|
73
|
+
mode('replication-status') {
|
74
|
+
description "Describe the replication status of those servers using replication"
|
75
|
+
mixin :option_home
|
76
|
+
mixin :option_log_level
|
77
|
+
mixin :argument_instances
|
78
|
+
run { Cli.run_command_with_params( 'replication-status', params ) }
|
79
|
+
}
|
73
80
|
|
74
|
-
mode('status') {
|
81
|
+
mode('process-status') {
|
75
82
|
description "Check the running status of all the tyrants listed"
|
76
83
|
mixin :option_home
|
77
84
|
mixin :option_log_level
|
78
85
|
|
79
86
|
mixin :argument_instances
|
80
87
|
|
81
|
-
run { Cli.run_command_with_params( 'status', params ) }
|
88
|
+
run { Cli.run_command_with_params( 'process-status', params ) }
|
82
89
|
}
|
83
90
|
|
84
91
|
mode( 'stats' ) {
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'tyrant_manager/command'
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
class TyrantManager
|
5
|
+
module Commands
|
6
|
+
#
|
7
|
+
# Report on the replication status of the server(s)
|
8
|
+
#
|
9
|
+
class ReplicationStatus< Command
|
10
|
+
def self.command_name
|
11
|
+
'replication-status'
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
manager.each_instance do |instance|
|
16
|
+
ilist = options['instances']
|
17
|
+
if ilist == %w[ all ] or ilist.include?( instance.name ) then
|
18
|
+
if instance.running? and instance.is_slave? then
|
19
|
+
s_stat = instance.stat
|
20
|
+
logger.info "#{instance.name} is replicating from #{s_stat['mhost']}:#{s_stat['mport']}"
|
21
|
+
if m_conn = validate_master_connection( instance ) then
|
22
|
+
if validate_master_master( instance.connection, m_conn ) then
|
23
|
+
m_stat = m_conn.stat
|
24
|
+
m_name = "#{s_stat['mhost']}:#{s_stat['mport']}"
|
25
|
+
|
26
|
+
primary, failover = instance.connection, m_conn
|
27
|
+
|
28
|
+
if m_stat['delay'] > s_stat['delay'] then
|
29
|
+
primary, failover = m_conn, instance.connection
|
30
|
+
end
|
31
|
+
|
32
|
+
p_stat = primary.stat
|
33
|
+
p_name = "#{ip_of( primary.host )}:#{primary.port}"
|
34
|
+
|
35
|
+
f_stat = failover.stat
|
36
|
+
f_name = "#{ip_of( failover.host )}:#{failover.port}"
|
37
|
+
|
38
|
+
n_width = [ p_name.length, f_name.length ].max
|
39
|
+
|
40
|
+
logger.info " Primary master : #{p_name} -> #{p_stat['rnum']} records, primary since #{(Time.now - ( Float(primary.stat['delay']))).strftime("%Y-%m-%d %H:%M:%S")}"
|
41
|
+
logger.info " Failover master : #{f_name} -> #{f_stat['rnum']} records, last replicated #{failover.stat['delay']} seconds ago"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
logger.info ""
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def validate_master_master( slave, master )
|
53
|
+
m_stat = master.stat
|
54
|
+
s_stat = slave.stat
|
55
|
+
|
56
|
+
if ( m_stat['mhost'] and m_stat['mport'] ) then
|
57
|
+
logger.info " #{s_stat['mhost']}:#{s_stat['mport']} is replicating from #{m_stat['mhost']}:#{m_stat['mport']}"
|
58
|
+
mm_ip = ip_of( m_stat['mhost'] )
|
59
|
+
s_ip = ip_of( slave.host )
|
60
|
+
if ( s_ip == mm_ip ) and ( slave.port == m_stat['mport'].to_i ) then
|
61
|
+
#logger.info " - this is a good master-master relationship"
|
62
|
+
return true
|
63
|
+
else
|
64
|
+
logger.error " Unsupported replication configuration!!!"
|
65
|
+
logger.error " (original hostnames) #{slave.host}:#{slave.port} -> #{(master.host)}:#{master.port} -> #{m_stat['mhost']}:#{m_stat['mport']}"
|
66
|
+
logger.error " (hostnames resolved) #{s_ip}:#{slave.port} -> #{ip_of(master.host)}:#{master.port} -> #{ip_of(m_stat['mhost'])}:#{m_stat['mport']}"
|
67
|
+
return false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def ip_of( hostname )
|
73
|
+
hostname = Socket.gethostname if %w[ localhost 0.0.0.0 ].include?( hostname )
|
74
|
+
addr_info = Socket.getaddrinfo( hostname, 1978, "AF_INET" )
|
75
|
+
return addr_info.first[3]
|
76
|
+
end
|
77
|
+
|
78
|
+
def validate_master_connection( slave )
|
79
|
+
begin
|
80
|
+
m_conn = slave.master_connection
|
81
|
+
m_stat = m_conn.stat
|
82
|
+
return m_conn
|
83
|
+
rescue => e
|
84
|
+
logger.error e
|
85
|
+
s_stat = slave.stat
|
86
|
+
logger.error "Master server #{s_stat["mhost"]}:#{s_stat['mport']} appears to be down."
|
87
|
+
end
|
88
|
+
return nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -10,8 +10,7 @@ class TyrantManager
|
|
10
10
|
ilist = options['instances']
|
11
11
|
if ilist == %w[ all ] or ilist.include?( instance.name ) then
|
12
12
|
puts "Instance #{instance.name} at #{instance.home_dir}"
|
13
|
-
|
14
|
-
stats = conn.stat
|
13
|
+
stats = instance.stat
|
15
14
|
stats.keys.sort.each do |k|
|
16
15
|
lhs = k.ljust(10, ".")
|
17
16
|
puts " #{lhs} #{stats[k]}"
|
@@ -4,7 +4,11 @@ class TyrantManager
|
|
4
4
|
#
|
5
5
|
# Report the status of one ore more tyrant intances
|
6
6
|
#
|
7
|
-
class
|
7
|
+
class ProcessStatus < Command
|
8
|
+
def self.command_name
|
9
|
+
'process-status'
|
10
|
+
end
|
11
|
+
|
8
12
|
def run
|
9
13
|
manager.each_instance do |instance|
|
10
14
|
ilist = options['instances']
|
@@ -308,13 +308,46 @@ class TyrantManager
|
|
308
308
|
end
|
309
309
|
end
|
310
310
|
|
311
|
+
#
|
312
|
+
# return the stats for this instance
|
313
|
+
#
|
314
|
+
def stat
|
315
|
+
connection.stat
|
316
|
+
end
|
317
|
+
|
311
318
|
#
|
312
319
|
# return a network connection to this instance
|
313
320
|
#
|
314
321
|
def connection
|
322
|
+
host = configuration.host
|
323
|
+
|
324
|
+
# you cannot connect to 0.0.0.0
|
325
|
+
if host == "0.0.0.0" then
|
326
|
+
host = "localhost"
|
327
|
+
end
|
315
328
|
Rufus::Tokyo::Tyrant.new( configuration.host, configuration.port.to_i )
|
316
329
|
end
|
317
330
|
|
331
|
+
#
|
332
|
+
# Is this instance a slave of another server? This means it could be in a
|
333
|
+
# master-slave or master-master relationship
|
334
|
+
#
|
335
|
+
def is_slave?
|
336
|
+
s = connection.stat
|
337
|
+
return (s['mhost'] and s['mport'])
|
338
|
+
end
|
339
|
+
|
340
|
+
#
|
341
|
+
# return a network connection to the master server of this instance
|
342
|
+
#
|
343
|
+
def master_connection
|
344
|
+
if is_slave? then
|
345
|
+
s = self.stat
|
346
|
+
return Rufus::Tokyo::Tyrant.new( s['mhost'], s['mport'].to_i )
|
347
|
+
end
|
348
|
+
return nil
|
349
|
+
end
|
350
|
+
|
318
351
|
|
319
352
|
private
|
320
353
|
|
@@ -51,6 +51,29 @@ describe TyrantManager::TyrantInstance do
|
|
51
51
|
@tyrant.data_dir.should == File.join( @tdir, "instances", "test", "data" )
|
52
52
|
end
|
53
53
|
|
54
|
+
describe "against running instances" do
|
55
|
+
before( :each ) do
|
56
|
+
@tyrant.start
|
57
|
+
start = Time.now
|
58
|
+
loop do
|
59
|
+
break if @tyrant.running?
|
60
|
+
sleep 0.1
|
61
|
+
break if (Time.now - start) > 2
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
after( :each ) do
|
66
|
+
@tyrant.stop
|
67
|
+
end
|
68
|
+
|
69
|
+
it "#is_slave?" do
|
70
|
+
@tyrant.running?.should == true
|
71
|
+
@tyrant.should_not be_is_slave
|
72
|
+
@tyrant.stop
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
54
77
|
|
55
78
|
describe "database types" do
|
56
79
|
{ 'memory-hash' => "*",
|
data/tasks/config.rb
CHANGED
@@ -12,11 +12,11 @@ Configuration.for('project') {
|
|
12
12
|
author "Jeremy Hinegardner"
|
13
13
|
email "jeremy@copiousfreetime.org"
|
14
14
|
homepage "http://copiousfreetime.rubyforge.org/tyrantmanager/"
|
15
|
-
description Utils.section_of("README", "description")
|
15
|
+
description Utils.section_of("README.rdoc", "description")
|
16
16
|
summary description.split(".").first
|
17
|
-
history "HISTORY"
|
17
|
+
history "HISTORY.rdoc"
|
18
18
|
license FileList["LICENSE"]
|
19
|
-
readme "README"
|
19
|
+
readme "README.rdoc"
|
20
20
|
}
|
21
21
|
|
22
22
|
#-----------------------------------------------------------------------
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tyrantmanager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Hinegardner
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-08-
|
12
|
+
date: 2009-08-10 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -32,6 +32,26 @@ dependencies:
|
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 1.0.0
|
34
34
|
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: logging
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.1.4
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: main
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.8.4
|
54
|
+
version:
|
35
55
|
- !ruby/object:Gem::Dependency
|
36
56
|
name: configuration
|
37
57
|
type: :development
|
@@ -52,20 +72,21 @@ dependencies:
|
|
52
72
|
- !ruby/object:Gem::Version
|
53
73
|
version: 0.8.3
|
54
74
|
version:
|
55
|
-
description: A command line tool for managing Tokyo Tyrant instances.
|
75
|
+
description: A command line tool for managing Tokyo Tyrant instances. It allows for the creation, starting, stopping, listing, stating of many tokyo tyrant instances all on the same machine. The commands can be applied to a single or multiple instances.
|
56
76
|
email: jeremy@copiousfreetime.org
|
57
77
|
executables:
|
58
78
|
- tyrantmanager
|
59
79
|
extensions: []
|
60
80
|
|
61
81
|
extra_rdoc_files:
|
62
|
-
- README
|
63
|
-
- HISTORY
|
82
|
+
- README.rdoc
|
83
|
+
- HISTORY.rdoc
|
64
84
|
- LICENSE
|
65
85
|
- lib/tyrant_manager/cli.rb
|
66
86
|
- lib/tyrant_manager/command.rb
|
67
87
|
- lib/tyrant_manager/commands/create_instance.rb
|
68
88
|
- lib/tyrant_manager/commands/list.rb
|
89
|
+
- lib/tyrant_manager/commands/replication_status.rb
|
69
90
|
- lib/tyrant_manager/commands/start.rb
|
70
91
|
- lib/tyrant_manager/commands/stats.rb
|
71
92
|
- lib/tyrant_manager/commands/status.rb
|
@@ -83,6 +104,7 @@ files:
|
|
83
104
|
- lib/tyrant_manager/command.rb
|
84
105
|
- lib/tyrant_manager/commands/create_instance.rb
|
85
106
|
- lib/tyrant_manager/commands/list.rb
|
107
|
+
- lib/tyrant_manager/commands/replication_status.rb
|
86
108
|
- lib/tyrant_manager/commands/start.rb
|
87
109
|
- lib/tyrant_manager/commands/stats.rb
|
88
110
|
- lib/tyrant_manager/commands/status.rb
|
@@ -102,8 +124,8 @@ files:
|
|
102
124
|
- spec/version_spec.rb
|
103
125
|
- data/config.rb
|
104
126
|
- data/default_instance_config.rb
|
105
|
-
- README
|
106
|
-
- HISTORY
|
127
|
+
- README.rdoc
|
128
|
+
- HISTORY.rdoc
|
107
129
|
- LICENSE
|
108
130
|
- tasks/announce.rake
|
109
131
|
- tasks/distribution.rake
|
@@ -118,7 +140,7 @@ homepage: http://tyrant-manager.rubyforge.org/
|
|
118
140
|
post_install_message:
|
119
141
|
rdoc_options:
|
120
142
|
- --main
|
121
|
-
- README
|
143
|
+
- README.rdoc
|
122
144
|
require_paths:
|
123
145
|
- lib
|
124
146
|
required_ruby_version: !ruby/object:Gem::Requirement
|