emissary 1.3.18 → 1.3.19
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.
- metadata +6 -40
- data/LICENSE +0 -203
- data/VERSION.yml +0 -4
- data/etc/config.ini +0 -38
- data/etc/emissary/config.ini +0 -13
- data/etc/init.d/emissary +0 -51
- data/lib/emissary.rb +0 -226
- data/lib/emissary/agent.rb +0 -61
- data/lib/emissary/agent/emissary.rb +0 -163
- data/lib/emissary/agent/error.rb +0 -26
- data/lib/emissary/agent/file.rb +0 -26
- data/lib/emissary/agent/gem.rb +0 -42
- data/lib/emissary/agent/mysql.rb +0 -230
- data/lib/emissary/agent/ping.rb +0 -37
- data/lib/emissary/agent/proxy.rb +0 -26
- data/lib/emissary/agent/rabbitmq.rb +0 -233
- data/lib/emissary/agent/sshkeys.rb +0 -152
- data/lib/emissary/agent/stats.rb +0 -96
- data/lib/emissary/agent/test.rb +0 -40
- data/lib/emissary/config.rb +0 -231
- data/lib/emissary/core_ext/blank.rb +0 -60
- data/lib/emissary/core_ext/misc_object.rb +0 -21
- data/lib/emissary/core_ext/symbolize.rb +0 -33
- data/lib/emissary/daemon.rb +0 -404
- data/lib/emissary/errors.rb +0 -106
- data/lib/emissary/gem_helper.rb +0 -183
- data/lib/emissary/identity.rb +0 -183
- data/lib/emissary/identity/ec2.rb +0 -64
- data/lib/emissary/identity/unix.rb +0 -67
- data/lib/emissary/logger.rb +0 -130
- data/lib/emissary/message.rb +0 -217
- data/lib/emissary/operator.rb +0 -275
- data/lib/emissary/operator/amqp.rb +0 -205
- data/lib/emissary/server.rb +0 -98
- data/lib/emissary/servolux.rb +0 -75
data/lib/emissary/agent.rb
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
# Copyright 2010 The New York Times
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
module Emissary
|
|
17
|
-
class Agent
|
|
18
|
-
attr_reader :name, :message, :method, :config, :operator
|
|
19
|
-
attr_accessor :args
|
|
20
|
-
|
|
21
|
-
def initialize message, config, operator
|
|
22
|
-
@message = message
|
|
23
|
-
@operator = operator
|
|
24
|
-
@config = config
|
|
25
|
-
|
|
26
|
-
@method = message.method.to_sym rescue :__bad_method__
|
|
27
|
-
@args = message.args.clone
|
|
28
|
-
|
|
29
|
-
unless valid_methods.first == :any or valid_methods.include? @method
|
|
30
|
-
raise ArgumentError, "Invalid method '#{@method.to_s}' for agent '#{message.agent}'"
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
post_init
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def post_init(); end
|
|
37
|
-
|
|
38
|
-
def valid_methods
|
|
39
|
-
raise StandardError, 'Not implemented'
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def activate
|
|
43
|
-
catch(:skip_implicit_response) do
|
|
44
|
-
result = self.__send__(method, *args)
|
|
45
|
-
response = if not result.kind_of? ::Emissary::Message
|
|
46
|
-
response = message.response
|
|
47
|
-
response.status = [ :ok, (result == true || result.nil? ? 'Succeeded.' : result ) ]
|
|
48
|
-
response
|
|
49
|
-
else
|
|
50
|
-
result
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
send response
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def send message
|
|
58
|
-
operator.send message
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
# Copyright 2010 The New York Times
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
require 'tempfile'
|
|
17
|
-
require 'fileutils'
|
|
18
|
-
|
|
19
|
-
module Emissary
|
|
20
|
-
class Agent::Emissary < Agent
|
|
21
|
-
INIT_DATA = [
|
|
22
|
-
::Emissary.identity.name,
|
|
23
|
-
::Emissary.identity.public_ip,
|
|
24
|
-
::Emissary.identity.local_ip,
|
|
25
|
-
::Emissary.identity.instance_id,
|
|
26
|
-
::Emissary.identity.server_id,
|
|
27
|
-
::Emissary.identity.cluster_id,
|
|
28
|
-
::Emissary.identity.account_id,
|
|
29
|
-
::Emissary.identity.queue_name,
|
|
30
|
-
::Emissary.version
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
def valid_methods
|
|
34
|
-
[ :reconfig, :selfupdate, :startup, :shutdown, :initdata, :reinit ]
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def reconfig new_config
|
|
38
|
-
throw :skip_implicit_response if new_config.strip.empty?
|
|
39
|
-
|
|
40
|
-
if (test(?w, config[:agents][:emissary][:config_path]))
|
|
41
|
-
begin
|
|
42
|
-
((tmp = Tempfile.new('new_config')) << new_config).flush
|
|
43
|
-
Emissary::Daemon.get_config(tmp.path)
|
|
44
|
-
rescue Exception => e
|
|
45
|
-
resonse = message.response
|
|
46
|
-
response.status_type = :error
|
|
47
|
-
response.status_note = e.message
|
|
48
|
-
return response
|
|
49
|
-
else
|
|
50
|
-
FileUtils.mv tmp.path, config[:agents][:emissary][:config_path]
|
|
51
|
-
# signal a USR1 to our parent, which will cause it to kill the
|
|
52
|
-
# children and restart them after rereading it's configuration
|
|
53
|
-
Process.kill('HUP', config[:parent_pid])
|
|
54
|
-
ensure
|
|
55
|
-
tmp.close
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def selfupdate version = :latest
|
|
62
|
-
begin
|
|
63
|
-
emissary_gem = ::Emissary::GemHelper.new('emissary')
|
|
64
|
-
request_version, source_uri = emissary_gem.versions(version).flatten
|
|
65
|
-
current_version, _ = emissary_gem.versions(:current).flatten
|
|
66
|
-
|
|
67
|
-
unless not emissary_gem.installable? request_version
|
|
68
|
-
::Emissary.logger.debug "Emissary SelfUpdate to version '#{request_version.to_s}' requested."
|
|
69
|
-
new_version = emissary_gem.update(request_version, source_uri)
|
|
70
|
-
::Emissary.logger.debug "Emissary gem updated from '#{::Emissary.version}' to '#{new_version}'"
|
|
71
|
-
else
|
|
72
|
-
::Emissary.logger.debug " -- SELFUPDATE -- [ VERSION: #{version}]"
|
|
73
|
-
::Emissary.logger.debug " -- SELFUPDATE -- [ CURRENT_VERSION: #{current_version}]"
|
|
74
|
-
::Emissary.logger.debug " -- SELFUPDATE -- [ REQUEST_VERSION: #{request_version}]"
|
|
75
|
-
|
|
76
|
-
notice = 'Emissary selfupdate skipped - ' + case true
|
|
77
|
-
when request_version.nil?
|
|
78
|
-
if version == :latest
|
|
79
|
-
"already at latest version."
|
|
80
|
-
else
|
|
81
|
-
"non-existent version '#{version}'"
|
|
82
|
-
end
|
|
83
|
-
when current_version == request_version
|
|
84
|
-
"already at specified version #{version}."
|
|
85
|
-
when current_version > request_version
|
|
86
|
-
"downgrade to version #{request_version} not allowed."
|
|
87
|
-
else
|
|
88
|
-
"unable to update from #{::Emissary.version} to requested version #{request_version}."
|
|
89
|
-
end
|
|
90
|
-
::Emissary.logger.warn notice
|
|
91
|
-
response = message.response
|
|
92
|
-
response.status_note = notice
|
|
93
|
-
return response
|
|
94
|
-
end
|
|
95
|
-
rescue ::Gem::InstallError, ::Gem::GemNotFoundException => e
|
|
96
|
-
::Emissary.logger.error "Emissary selfupdate failed with reason: #{e.message}"
|
|
97
|
-
return message.error(e)
|
|
98
|
-
else
|
|
99
|
-
::Emissary.logger.debug "SelfUpdate: About to detach and run commands"
|
|
100
|
-
with_detached_process('emissary-selfupdate') do
|
|
101
|
-
%x{
|
|
102
|
-
emissary stop;
|
|
103
|
-
sleep 2;
|
|
104
|
-
ps uxa | grep -v grep | grep '(emissary|emop_)' | awk '{ print $2 }' | xargs kill -9;
|
|
105
|
-
sleep 1;
|
|
106
|
-
source /etc/cloudrc;
|
|
107
|
-
emissary start -d;
|
|
108
|
-
}
|
|
109
|
-
end
|
|
110
|
-
::Emissary.logger.debug "SelfUpdate: Child detached"
|
|
111
|
-
throw :skip_implicit_response
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def startup
|
|
116
|
-
message = initdata
|
|
117
|
-
message.recipient = config[:startup]
|
|
118
|
-
::Emissary.logger.notice "Sending Startup message with args: #{message.args.inspect}"
|
|
119
|
-
message
|
|
120
|
-
end
|
|
121
|
-
alias :reinit :startup
|
|
122
|
-
|
|
123
|
-
def initdata
|
|
124
|
-
response = message.response
|
|
125
|
-
response.args = INIT_DATA
|
|
126
|
-
response
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def shutdown
|
|
130
|
-
message.recipient = config[:shutdown]
|
|
131
|
-
message.args = [
|
|
132
|
-
::Emissary.identity.server_id,
|
|
133
|
-
::Emissary.identity.cluster_id,
|
|
134
|
-
::Emissary.identity.account_id,
|
|
135
|
-
::Emissary.identity.instance_id
|
|
136
|
-
]
|
|
137
|
-
::Emissary.logger.notice "Sending Shutdown message with args: #{message.args.inspect}"
|
|
138
|
-
message
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
private
|
|
142
|
-
|
|
143
|
-
def with_detached_process(name = nil)
|
|
144
|
-
raise Exception, 'Block missing for with_detached_process call' unless block_given?
|
|
145
|
-
|
|
146
|
-
# completely seperate from our parent process
|
|
147
|
-
pid = Kernel.fork do
|
|
148
|
-
Process.setsid
|
|
149
|
-
exit!(0) if fork
|
|
150
|
-
$0 = name unless name.nil?
|
|
151
|
-
Dir.chdir '/'
|
|
152
|
-
::Emissary.logger.debug "SelfUpdate: Detached and running update command block now..."
|
|
153
|
-
yield
|
|
154
|
-
::Emissary.logger.debug "SelfUpdate: Finished running update command block - exiting..."
|
|
155
|
-
exit!(0)
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
::Emissary.logger.debug "SelfUpdate: Detaching child process now."
|
|
159
|
-
#don't worry about the child anymore - it's on it's own
|
|
160
|
-
Process.detach(pid)
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
|
-
end
|
data/lib/emissary/agent/error.rb
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# Copyright 2010 The New York Times
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
module Emissary
|
|
17
|
-
class Agent::Error < Agent
|
|
18
|
-
def valid_methods
|
|
19
|
-
[ :any ]
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def activate
|
|
23
|
-
message
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
data/lib/emissary/agent/file.rb
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# Copyright 2010 The New York Times
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
module Emissary
|
|
17
|
-
class Agent::File < Agent
|
|
18
|
-
def valid_methods
|
|
19
|
-
[ :any ]
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def activate
|
|
23
|
-
throw :skip_implicit_response
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
data/lib/emissary/agent/gem.rb
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
# Copyright 2010 The New York Times
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
|
|
17
|
-
module Emissary
|
|
18
|
-
class Agent::Gem < Agent
|
|
19
|
-
def valid_methods
|
|
20
|
-
[ :update, :install, :remove, :uninstall, :version ]
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def version gem_name
|
|
24
|
-
::Emissary.GemHelper.new(gem_name).version
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Updates Emissary from the given source to the given version
|
|
28
|
-
def install gem_name, version = :latest, source_url = :default
|
|
29
|
-
::Emissary::GemHelper.new(gem_name).install(version, source_url)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def update gem_name, version = :latest, source_url = :default
|
|
33
|
-
::Emissary::GemHelper.new(gem_name).update(version, source_url)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def uninstall gem_name, version = :latest, ignore_dependencies = true, remove_executables = false
|
|
37
|
-
::Emissary::GemHelper.new(gem_name).uninstall(version, ignore_dependencies, remove_executables)
|
|
38
|
-
end
|
|
39
|
-
alias :remove :uninstall
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
end
|
data/lib/emissary/agent/mysql.rb
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
# Copyright 2010 The New York Times
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
require "mysql"
|
|
17
|
-
require "monitor"
|
|
18
|
-
require 'timeout'
|
|
19
|
-
|
|
20
|
-
module Emissary
|
|
21
|
-
class Agent::Mysql < Agent
|
|
22
|
-
DEFAULT_COORDINATES_FILE = '/var/nyt/mysql/master.coordinates'.freeze
|
|
23
|
-
|
|
24
|
-
def valid_methods
|
|
25
|
-
[ :lock, :unlock, :status ]
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
attr_accessor :coordinates_file
|
|
29
|
-
|
|
30
|
-
def lock(host, user, password, timeout = Agent::Mysql::Helper::DEFAULT_TIMEOUT, coordinates_file = nil)
|
|
31
|
-
@coordinates_file ||= coordinates_file
|
|
32
|
-
@coordinates_file ||= config[:agents][:mysql][:coordinates_file] rescue nil
|
|
33
|
-
@coordinates_file ||= DEFAULT_COORDINATES_FILE
|
|
34
|
-
|
|
35
|
-
locker = ::Emissary::Agent::Mysql::Helper.new(host, user, password, timeout)
|
|
36
|
-
locker.lock!
|
|
37
|
-
|
|
38
|
-
filename, position = locker.get_binlog_info
|
|
39
|
-
|
|
40
|
-
unless filename.nil?
|
|
41
|
-
write_lock_info(filename, position)
|
|
42
|
-
response = message.response
|
|
43
|
-
response.args = [ filename, position ]
|
|
44
|
-
response.status_note = 'Locked'
|
|
45
|
-
else
|
|
46
|
-
response = message.response
|
|
47
|
-
response.status_note = "No binlog information - can't lock."
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
response
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def unlock(host, user, password)
|
|
54
|
-
locker = ::Emissary::Agent::Mysql::Helper.new(host, user, password)
|
|
55
|
-
raise "The database was not locked! (Possibly timed out.)" unless locker.locked?
|
|
56
|
-
|
|
57
|
-
locker.unlock!
|
|
58
|
-
|
|
59
|
-
response = message.response
|
|
60
|
-
response.status_note = 'Unlocked'
|
|
61
|
-
response
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def status(host, user, password)
|
|
65
|
-
locker = ::Emissary::Agent::Mysql::Helper.new(host, user, password)
|
|
66
|
-
|
|
67
|
-
response = message.response
|
|
68
|
-
response.status_note = locker.locked? ? 'Locked' : 'Unlocked'
|
|
69
|
-
response
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
private
|
|
73
|
-
|
|
74
|
-
def write_lock_info(filename, position)
|
|
75
|
-
File.open(coordinates_file, "w") do |file|
|
|
76
|
-
file << "#{filename},#{position}"
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
class Agent::Mysql::Helper
|
|
83
|
-
DEFAULT_TIMEOUT = 30
|
|
84
|
-
|
|
85
|
-
@@class_monitor = Monitor.new
|
|
86
|
-
|
|
87
|
-
# only return one locker per host+user combination
|
|
88
|
-
def self.new(host, user, password, timeout = nil)
|
|
89
|
-
@@class_monitor.synchronize do
|
|
90
|
-
(@@lockers||={})["#{host}:#{user}"] ||= begin
|
|
91
|
-
allocate.instance_eval(<<-EOS, __FILE__, __LINE__)
|
|
92
|
-
initialize(host, user, password, timeout || DEFAULT_TIMEOUT)
|
|
93
|
-
self
|
|
94
|
-
EOS
|
|
95
|
-
end
|
|
96
|
-
@@lockers["#{host}:#{user}"].timeout = timeout unless timeout.nil?
|
|
97
|
-
@@lockers["#{host}:#{user}"]
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
@@locked_M = Mutex.new
|
|
102
|
-
def locked_M() @@locked_M; end
|
|
103
|
-
|
|
104
|
-
private
|
|
105
|
-
|
|
106
|
-
def initialize(host, user, password, timeout = DEFAULT_TIMEOUT)
|
|
107
|
-
@host = host
|
|
108
|
-
@user = user
|
|
109
|
-
@password = password
|
|
110
|
-
@timeout = timeout
|
|
111
|
-
|
|
112
|
-
@watcher = nil
|
|
113
|
-
@connection = nil
|
|
114
|
-
@locked = false
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
def connection
|
|
119
|
-
begin
|
|
120
|
-
@connection.ping() unless @connection.nil?
|
|
121
|
-
rescue ::Mysql::Error => e
|
|
122
|
-
if e.message =~ /server has gone away/
|
|
123
|
-
::Emissary.logger.notice "Agent::MySQL: MySQL server went away - reconnecting..."
|
|
124
|
-
@connection = nil
|
|
125
|
-
else
|
|
126
|
-
raise e
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
@connection ||= ::Mysql.real_connect(@host, @user, @password)
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
def disconnect
|
|
134
|
-
unless not connected?
|
|
135
|
-
::Emissary.logger.notice "Agent::MySQL: disconnecting from MySQL Server .."
|
|
136
|
-
@connection.close
|
|
137
|
-
@connection = nil
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
public
|
|
142
|
-
attr_accessor :timeout
|
|
143
|
-
|
|
144
|
-
def connected?
|
|
145
|
-
!!@connection
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
# Acquire a lock and, with that lock, run a block/closure.
|
|
149
|
-
def with_lock
|
|
150
|
-
begin
|
|
151
|
-
lock! && yield
|
|
152
|
-
ensure
|
|
153
|
-
unlock!
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
def locked?
|
|
158
|
-
!!@locked
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
def lock!
|
|
162
|
-
unless locked?
|
|
163
|
-
kill_watcher_thread! # make sure we have a new thread for watching
|
|
164
|
-
locked_M.synchronize { @locked = true }
|
|
165
|
-
connection.query("FLUSH TABLES WITH READ LOCK")
|
|
166
|
-
spawn_lockwatch_thread!
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
def unlock!
|
|
171
|
-
begin
|
|
172
|
-
unless not locked?
|
|
173
|
-
locked_M.synchronize {
|
|
174
|
-
connection.query("UNLOCK TABLES")
|
|
175
|
-
@locked = false
|
|
176
|
-
}
|
|
177
|
-
end
|
|
178
|
-
ensure
|
|
179
|
-
disconnect
|
|
180
|
-
kill_watcher_thread!
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
# Test whether our login info is valid by attempting a database
|
|
185
|
-
# connection.
|
|
186
|
-
def valid?
|
|
187
|
-
begin
|
|
188
|
-
!!connection
|
|
189
|
-
rescue => e
|
|
190
|
-
false # Don't throw an exception, just return false.
|
|
191
|
-
ensure
|
|
192
|
-
disconnect if connected?
|
|
193
|
-
end
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
# Returns [file, position]
|
|
197
|
-
def get_binlog_info
|
|
198
|
-
raise "get_binlog_info must be called from within a lock." unless locked?
|
|
199
|
-
(result = connection.query("SHOW MASTER STATUS")).fetch_row[0,2]
|
|
200
|
-
ensure
|
|
201
|
-
result.free unless result.nil?
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
def spawn_lockwatch_thread!
|
|
205
|
-
if @watcher.is_a?(Thread) and not @watcher.alive?
|
|
206
|
-
::Emissary.logger.notice "Agent::MySQL: Watcher is dead - restarting..."
|
|
207
|
-
@watcher = nil
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
@watcher ||= Thread.new {
|
|
211
|
-
begin
|
|
212
|
-
::Emissary.logger.debug "Agent::MySQL: Entering Watcher Loop"
|
|
213
|
-
Timeout.timeout(@timeout) do
|
|
214
|
-
loop { break unless locked? }
|
|
215
|
-
end
|
|
216
|
-
rescue Timeout::Error
|
|
217
|
-
ensure
|
|
218
|
-
unlock!
|
|
219
|
-
Thread.exit
|
|
220
|
-
end
|
|
221
|
-
}
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
def kill_watcher_thread!
|
|
225
|
-
@watcher.kill unless not @watcher.is_a?(Thread) or not @watcher.alive?
|
|
226
|
-
@watcher = nil
|
|
227
|
-
end
|
|
228
|
-
end
|
|
229
|
-
end
|
|
230
|
-
|