litmus_paper 0.0.3
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/.gitignore +17 -0
- data/.rake_commit +1 -0
- data/.rvmrc +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +31 -0
- data/Rakefile +6 -0
- data/bin/litmus +6 -0
- data/bin/litmusctl +7 -0
- data/config.ru +5 -0
- data/lib/facts/loadaverage.rb +6 -0
- data/lib/litmus_paper/app.rb +63 -0
- data/lib/litmus_paper/cli/admin.rb +97 -0
- data/lib/litmus_paper/cli/server.rb +62 -0
- data/lib/litmus_paper/configuration.rb +27 -0
- data/lib/litmus_paper/dependency/http.rb +40 -0
- data/lib/litmus_paper/dependency/tcp.rb +24 -0
- data/lib/litmus_paper/forced_health.rb +18 -0
- data/lib/litmus_paper/health.rb +35 -0
- data/lib/litmus_paper/logger.rb +15 -0
- data/lib/litmus_paper/metric/available_memory.rb +36 -0
- data/lib/litmus_paper/metric/cpu_load.rb +26 -0
- data/lib/litmus_paper/service.rb +51 -0
- data/lib/litmus_paper/status_file.rb +26 -0
- data/lib/litmus_paper/version.rb +3 -0
- data/lib/litmus_paper.rb +51 -0
- data/litmus_paper.gemspec +26 -0
- data/spec/litmus_paper/app_spec.rb +246 -0
- data/spec/litmus_paper/cli/admin_spec.rb +64 -0
- data/spec/litmus_paper/cli/server_spec.rb +16 -0
- data/spec/litmus_paper/configuration_spec.rb +19 -0
- data/spec/litmus_paper/dependency/http_spec.rb +69 -0
- data/spec/litmus_paper/dependency/tcp_spec.rb +35 -0
- data/spec/litmus_paper/health_spec.rb +71 -0
- data/spec/litmus_paper/metric/available_memory_spec.rb +40 -0
- data/spec/litmus_paper/metric/cpu_load_spec.rb +46 -0
- data/spec/litmus_paper/service_spec.rb +65 -0
- data/spec/litmus_paper/status_file_spec.rb +39 -0
- data/spec/litmus_paper_spec.rb +39 -0
- data/spec/spec_helper.rb +46 -0
- data/spec/support/always_available_dependency.rb +9 -0
- data/spec/support/config.d/passing_test.config +6 -0
- data/spec/support/config.d/test.config +8 -0
- data/spec/support/constant_metric.rb +13 -0
- data/spec/support/http_test_server.rb +25 -0
- data/spec/support/http_test_server_config.ru +3 -0
- data/spec/support/never_available_dependency.rb +9 -0
- data/spec/support/stub_facter.rb +9 -0
- data/spec/support/test.config +13 -0
- data/spec/support/test.d.config +3 -0
- metadata +249 -0
data/.gitignore
ADDED
data/.rake_commit
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--without-prompt feature
|
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use ruby-1.8.7-p249@litmus_paper --create
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Braintree Payment Solutions LLC
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# IpvsLitmus
|
2
|
+
|
3
|
+
Backend health tester for HA Services
|
4
|
+
|
5
|
+
[](http://travis-ci.org/braintree/litmus_paper)
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'litmus_paper'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install litmus_paper
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
TODO: Write usage instructions here
|
24
|
+
|
25
|
+
## Contributing
|
26
|
+
|
27
|
+
1. Fork it
|
28
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
29
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
30
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
31
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/litmus
ADDED
data/bin/litmusctl
ADDED
data/config.ru
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
module LitmusPaper
|
2
|
+
class App < Sinatra::Base
|
3
|
+
get "/" do
|
4
|
+
output = "Services monitored:\n"
|
5
|
+
output += LitmusPaper.services.keys.join("\n")
|
6
|
+
|
7
|
+
text 200, output
|
8
|
+
end
|
9
|
+
|
10
|
+
post "/force/*" do
|
11
|
+
path = *status_file_path(params[:splat])
|
12
|
+
statusfile = StatusFile.new(*path)
|
13
|
+
statusfile.create(params[:reason])
|
14
|
+
|
15
|
+
text 201, "File created"
|
16
|
+
end
|
17
|
+
|
18
|
+
delete "/force/*" do
|
19
|
+
path = *status_file_path(params[:splat])
|
20
|
+
statusfile = StatusFile.new(*path)
|
21
|
+
if statusfile.exists?
|
22
|
+
statusfile.delete
|
23
|
+
text 200, "File deleted"
|
24
|
+
else
|
25
|
+
text 404, "NOT FOUND"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
get "/:service/status" do
|
30
|
+
service = LitmusPaper.services[params[:service]]
|
31
|
+
if service.nil?
|
32
|
+
text 404, "NOT FOUND", { "X-Health" => "0" }
|
33
|
+
else
|
34
|
+
health = service.current_health
|
35
|
+
response_code = health.ok? ? 200 : 503
|
36
|
+
body = "Health: #{health.value}\n"
|
37
|
+
body << health.summary
|
38
|
+
text response_code, body, { "X-Health" => health.value.to_s }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
get "/test/error" do
|
43
|
+
raise "an error"
|
44
|
+
end
|
45
|
+
|
46
|
+
error do
|
47
|
+
text 500, "Server Error"
|
48
|
+
end
|
49
|
+
|
50
|
+
def text(response_code, body, headers ={})
|
51
|
+
[response_code, { "Content-Type" => "text/plain" }.merge(headers), body]
|
52
|
+
end
|
53
|
+
|
54
|
+
def status_file_path(splat)
|
55
|
+
path = splat.first.split("/")
|
56
|
+
if path.size == 1
|
57
|
+
["global_#{path.first}"]
|
58
|
+
else
|
59
|
+
path
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module LitmusPaper
|
2
|
+
module CLI
|
3
|
+
class Admin
|
4
|
+
def run(argv = ARGV)
|
5
|
+
command = argv.shift
|
6
|
+
send(command, argv)
|
7
|
+
end
|
8
|
+
|
9
|
+
def list(args)
|
10
|
+
options = _default_options
|
11
|
+
opt_parser = _extend_default_parser(options) do |opts|
|
12
|
+
opts.banner = "Usage: litmusctl list [options]"
|
13
|
+
end
|
14
|
+
opt_parser.parse! args
|
15
|
+
|
16
|
+
request = Net::HTTP::Get.new("/")
|
17
|
+
_litmus_request(options[:host], options[:port], request)
|
18
|
+
end
|
19
|
+
|
20
|
+
def force(args)
|
21
|
+
options = _default_options
|
22
|
+
opt_parser = _extend_default_parser(options) do |opts|
|
23
|
+
opts.banner = "Usage: litmusctl force <up|down> [service] [options]"
|
24
|
+
opts.on("-d", "--delete", "Remove status file") do
|
25
|
+
options[:delete] = true
|
26
|
+
end
|
27
|
+
opts.on("-r", "--reason=reason", String, "Reason for status file") do |reason|
|
28
|
+
options[:reason] = reason
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
opt_parser.parse! args
|
33
|
+
direction, service = args
|
34
|
+
|
35
|
+
if options[:delete]
|
36
|
+
request = Net::HTTP::Delete.new("/force/#{direction}/#{service}")
|
37
|
+
else
|
38
|
+
if !options.has_key?(:reason)
|
39
|
+
print "Reason? "
|
40
|
+
options[:reason] = gets.chomp
|
41
|
+
end
|
42
|
+
request = Net::HTTP::Post.new("/force/#{direction}/#{service}")
|
43
|
+
request.set_form_data('reason' => options[:reason])
|
44
|
+
end
|
45
|
+
|
46
|
+
_litmus_request(options[:host], options[:port], request)
|
47
|
+
end
|
48
|
+
|
49
|
+
def status(args)
|
50
|
+
options = _default_options
|
51
|
+
opt_parser = _extend_default_parser(options) do |opts|
|
52
|
+
opts.banner = "Usage: litmusctl status <service> [options]"
|
53
|
+
end
|
54
|
+
|
55
|
+
opt_parser.parse! args
|
56
|
+
service = args.shift
|
57
|
+
|
58
|
+
_litmus_request(options[:host], options[:port], Net::HTTP::Get.new("/#{service}/status"))
|
59
|
+
end
|
60
|
+
|
61
|
+
def _default_options
|
62
|
+
options = { :port => 9292, :host => 'localhost' }
|
63
|
+
end
|
64
|
+
|
65
|
+
def _extend_default_parser(options, &block)
|
66
|
+
OptionParser.new do |opts|
|
67
|
+
block.call(opts)
|
68
|
+
|
69
|
+
opts.on("-p", "--port=port", Integer, "Port litmus is running on", "Default: 9292") do |port|
|
70
|
+
options[:port] = port
|
71
|
+
end
|
72
|
+
opts.on("-h", "--host=ip", String, ":Host litmus is running on", "Default: localhost") do |host|
|
73
|
+
options[:host] = host
|
74
|
+
end
|
75
|
+
opts.on("--help", "Show this help message.") { puts opts; exit }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def _litmus_request(host, port, request)
|
80
|
+
begin
|
81
|
+
http = Net::HTTP.start(host, port)
|
82
|
+
response = http.request(request)
|
83
|
+
|
84
|
+
puts response.body
|
85
|
+
case response
|
86
|
+
when Net::HTTPSuccess then exit 0
|
87
|
+
when Net::HTTPClientError then exit 2
|
88
|
+
else exit 1
|
89
|
+
end
|
90
|
+
rescue Errno::ECONNREFUSED => e
|
91
|
+
puts "Unable to connect to litmus on #{host}:#{port}: #{e.message}"
|
92
|
+
exit 1
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module LitmusPaper
|
2
|
+
module CLI
|
3
|
+
class Server < Rack::Server
|
4
|
+
class Options
|
5
|
+
def parse!(args)
|
6
|
+
args, options = args.dup, {}
|
7
|
+
|
8
|
+
opt_parser = OptionParser.new do |opts|
|
9
|
+
opts.banner = "Usage: litmus [mongrel, thin, etc] [options]"
|
10
|
+
opts.on("-c", "--config=file", String,
|
11
|
+
"Litmus configuration file", "Default: /etc/litmus.conf") { |v| options[:litmus_config] = v }
|
12
|
+
opts.on("-D", "--data-dir=path", String,
|
13
|
+
"Litmus data directory", "Default: /etc/litmus") { |v| options[:config_dir] = v }
|
14
|
+
|
15
|
+
opts.separator ""
|
16
|
+
|
17
|
+
opts.on("-p", "--port=port", Integer,
|
18
|
+
"Runs Litmus on the specified port.", "Default: 9292") { |v| options[:Port] = v }
|
19
|
+
opts.on("-b", "--binding=ip", String,
|
20
|
+
"Binds Litmus to the specified ip.", "Default: 0.0.0.0") { |v| options[:Host] = v }
|
21
|
+
opts.on("-d", "--daemon", "Make server run as a Daemon.") { options[:daemonize] = true }
|
22
|
+
opts.on("-P","--pid=pid",String,
|
23
|
+
"Specifies the PID file.",
|
24
|
+
"Default: rack.pid") { |v| options[:pid] = v }
|
25
|
+
|
26
|
+
opts.separator ""
|
27
|
+
|
28
|
+
opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
|
29
|
+
end
|
30
|
+
|
31
|
+
opt_parser.parse! args
|
32
|
+
|
33
|
+
options[:config] = File.expand_path("../../../config.ru", File.dirname(__FILE__))
|
34
|
+
options[:server] = args.shift
|
35
|
+
options
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def opt_parser
|
40
|
+
Options.new
|
41
|
+
end
|
42
|
+
|
43
|
+
def start
|
44
|
+
if !File.exists?(options[:litmus_config])
|
45
|
+
puts "Could not find #{options[:litmus_config]}. Specify correct location with -c file"
|
46
|
+
exit 1
|
47
|
+
end
|
48
|
+
|
49
|
+
LitmusPaper.configure(options[:litmus_config])
|
50
|
+
LitmusPaper.config_dir = options[:config_dir]
|
51
|
+
super
|
52
|
+
end
|
53
|
+
|
54
|
+
def default_options
|
55
|
+
super.merge(
|
56
|
+
:litmus_config => '/etc/litmus.conf',
|
57
|
+
:config_dir => '/etc/litmus'
|
58
|
+
)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module LitmusPaper
|
2
|
+
class Configuration
|
3
|
+
def initialize(config_file_path)
|
4
|
+
@config_file_path = config_file_path
|
5
|
+
@services = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def evaluate(file = @config_file_path)
|
9
|
+
config_contents = File.read(file)
|
10
|
+
instance_eval(config_contents)
|
11
|
+
@services
|
12
|
+
end
|
13
|
+
|
14
|
+
def include_files(glob_pattern)
|
15
|
+
full_glob_pattern = File.expand_path(glob_pattern, File.dirname(@config_file_path))
|
16
|
+
Dir.glob(full_glob_pattern).each do |file|
|
17
|
+
evaluate(file)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def service(name, &block)
|
22
|
+
service = Service.new(name.to_s)
|
23
|
+
block.call(service)
|
24
|
+
@services[name.to_s] = service
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module LitmusPaper
|
2
|
+
module Dependency
|
3
|
+
class HTTP
|
4
|
+
def initialize(uri, options = {})
|
5
|
+
@uri = uri
|
6
|
+
@expected_content = Regexp.new(options.fetch(:content, '.*'))
|
7
|
+
@method = options.fetch(:method, 'GET')
|
8
|
+
end
|
9
|
+
|
10
|
+
def available?
|
11
|
+
response = _make_request
|
12
|
+
_successful_response?(response) && _body_matches?(response)
|
13
|
+
rescue Exception
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
def _make_request
|
18
|
+
uri = URI.parse(@uri)
|
19
|
+
request = Net::HTTP.const_get(@method.capitalize).new(uri.normalize.path)
|
20
|
+
request.set_form_data({})
|
21
|
+
|
22
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
23
|
+
http.request(request)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def _successful_response?(response)
|
28
|
+
response.is_a? Net::HTTPSuccess
|
29
|
+
end
|
30
|
+
|
31
|
+
def _body_matches?(response)
|
32
|
+
(response.body =~ @expected_content) ? true : false
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
"Dependency::HTTP(#{@uri})"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module LitmusPaper
|
2
|
+
module Dependency
|
3
|
+
class TCP
|
4
|
+
def initialize(ip, port)
|
5
|
+
@ip, @port = ip, port
|
6
|
+
end
|
7
|
+
|
8
|
+
def available?
|
9
|
+
Timeout.timeout(5) do
|
10
|
+
socket = TCPSocket.new(@ip, @port)
|
11
|
+
socket.close
|
12
|
+
end
|
13
|
+
true
|
14
|
+
rescue Exception
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
"Dependency::TCP(tcp://#{@ip}:#{@port})"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module LitmusPaper
|
2
|
+
class Health
|
3
|
+
|
4
|
+
attr_reader :summary
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@value = 0
|
8
|
+
@dependencies_available = true
|
9
|
+
@summary = ""
|
10
|
+
end
|
11
|
+
|
12
|
+
def ok?
|
13
|
+
value > 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def value
|
17
|
+
return 0 unless @dependencies_available
|
18
|
+
@value
|
19
|
+
end
|
20
|
+
|
21
|
+
def perform(metric)
|
22
|
+
health = metric.current_health
|
23
|
+
|
24
|
+
@value += health
|
25
|
+
@summary << "#{metric}: #{health}\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
def ensure(dependency)
|
29
|
+
available = dependency.available?
|
30
|
+
|
31
|
+
@dependencies_available &&= available
|
32
|
+
@summary << "#{dependency}: #{available ? 'OK' : 'FAIL'}\n"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module LitmusPaper
|
2
|
+
module Metric
|
3
|
+
class AvailableMemory
|
4
|
+
MULTIPLIER = {
|
5
|
+
"GB" => 1024*1024*1024,
|
6
|
+
"MB" => 1024*1024,
|
7
|
+
"KB" => 1024
|
8
|
+
}
|
9
|
+
|
10
|
+
def initialize(weight, facter = Facter)
|
11
|
+
@weight = weight
|
12
|
+
@facter = facter
|
13
|
+
end
|
14
|
+
|
15
|
+
def current_health
|
16
|
+
@weight * memory_free / memory_total
|
17
|
+
end
|
18
|
+
|
19
|
+
def memory_total
|
20
|
+
return @memory_total unless @memory_total.nil?
|
21
|
+
|
22
|
+
size, scale = @facter.value('memorytotal').split(' ')
|
23
|
+
@memory_total = size.to_i * MULTIPLIER[scale]
|
24
|
+
end
|
25
|
+
|
26
|
+
def memory_free
|
27
|
+
size, scale = @facter.value('memoryfree').split(' ')
|
28
|
+
size.to_i * MULTIPLIER[scale]
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
"Metric::AvailableMemory(#{@weight})"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module LitmusPaper
|
2
|
+
module Metric
|
3
|
+
class CPULoad
|
4
|
+
def initialize(weight, facter = Facter)
|
5
|
+
@weight = weight
|
6
|
+
@facter = facter
|
7
|
+
end
|
8
|
+
|
9
|
+
def current_health
|
10
|
+
[@weight - (@weight * load_average / processor_count), 0].max
|
11
|
+
end
|
12
|
+
|
13
|
+
def processor_count
|
14
|
+
@processor_count ||= @facter.value('processorcount').to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
def load_average
|
18
|
+
@facter.value('loadaverage').split(' ').first.to_f
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"Metric::CPULoad(#{@weight})"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module LitmusPaper
|
2
|
+
class Service
|
3
|
+
def initialize(name, dependencies = [], checks = [])
|
4
|
+
@name = name
|
5
|
+
@dependencies = dependencies
|
6
|
+
@checks = checks
|
7
|
+
end
|
8
|
+
|
9
|
+
def success?
|
10
|
+
health > 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def current_health
|
14
|
+
forced_health = _determine_forced_health
|
15
|
+
return forced_health unless forced_health.nil?
|
16
|
+
|
17
|
+
health = LitmusPaper::Health.new
|
18
|
+
@dependencies.each do |dependency|
|
19
|
+
health.ensure(dependency)
|
20
|
+
end
|
21
|
+
|
22
|
+
@checks.each do |check|
|
23
|
+
health.perform(check)
|
24
|
+
end
|
25
|
+
health
|
26
|
+
end
|
27
|
+
|
28
|
+
def measure_health(metric_class, options)
|
29
|
+
@checks << metric_class.new(options[:weight])
|
30
|
+
end
|
31
|
+
|
32
|
+
def depends(dependency_class, *args)
|
33
|
+
@dependencies << dependency_class.new(*args)
|
34
|
+
end
|
35
|
+
|
36
|
+
def _health_files
|
37
|
+
@health_files ||= [
|
38
|
+
[0, LitmusPaper::StatusFile.new('down', @name)],
|
39
|
+
[100, LitmusPaper::StatusFile.new('up', @name)],
|
40
|
+
[0, LitmusPaper::StatusFile.new('global_down')],
|
41
|
+
[100, LitmusPaper::StatusFile.new('global_up')]
|
42
|
+
]
|
43
|
+
end
|
44
|
+
|
45
|
+
def _determine_forced_health
|
46
|
+
_health_files.map do |health, status_file|
|
47
|
+
ForcedHealth.new(health, status_file.content) if status_file.exists?
|
48
|
+
end.compact.first
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module LitmusPaper
|
2
|
+
class StatusFile
|
3
|
+
def initialize(*filenames)
|
4
|
+
@path = File.join(LitmusPaper.config_dir, *filenames)
|
5
|
+
end
|
6
|
+
|
7
|
+
def content
|
8
|
+
File.read(@path).chomp
|
9
|
+
end
|
10
|
+
|
11
|
+
def create(reason)
|
12
|
+
FileUtils.mkdir_p(File.dirname(@path))
|
13
|
+
File.open(@path, 'w') do |file|
|
14
|
+
file.puts(reason)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def delete
|
19
|
+
FileUtils.rm(@path)
|
20
|
+
end
|
21
|
+
|
22
|
+
def exists?
|
23
|
+
File.exists?(@path)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|