ipvs_litmus 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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 +4 -0
- data/ipvs_litmus.gemspec +25 -0
- data/lib/facts/loadaverage.rb +6 -0
- data/lib/ipvs_litmus/app.rb +48 -0
- data/lib/ipvs_litmus/cli/admin.rb +86 -0
- data/lib/ipvs_litmus/cli/server.rb +62 -0
- data/lib/ipvs_litmus/configuration.rb +20 -0
- data/lib/ipvs_litmus/dependency/http.rb +27 -0
- data/lib/ipvs_litmus/forced_health.rb +18 -0
- data/lib/ipvs_litmus/health.rb +35 -0
- data/lib/ipvs_litmus/metric/available_memory.rb +32 -0
- data/lib/ipvs_litmus/metric/cpu_load.rb +22 -0
- data/lib/ipvs_litmus/service.rb +51 -0
- data/lib/ipvs_litmus/status_file.rb +26 -0
- data/lib/ipvs_litmus/version.rb +3 -0
- data/lib/ipvs_litmus.rb +44 -0
- data/spec/ipvs_litmus/app_spec.rb +215 -0
- data/spec/ipvs_litmus/cli/admin_spec.rb +58 -0
- data/spec/ipvs_litmus/cli/server_spec.rb +16 -0
- data/spec/ipvs_litmus/configuration_spec.rb +11 -0
- data/spec/ipvs_litmus/dependency/http_spec.rb +42 -0
- data/spec/ipvs_litmus/health_spec.rb +71 -0
- data/spec/ipvs_litmus/metric/available_memory_spec.rb +33 -0
- data/spec/ipvs_litmus/metric/cpu_load_spec.rb +39 -0
- data/spec/ipvs_litmus/service_spec.rb +65 -0
- data/spec/ipvs_litmus/status_file_spec.rb +39 -0
- data/spec/ipvs_litmus_spec.rb +22 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/support/always_available_dependency.rb +5 -0
- data/spec/support/constant_metric.rb +9 -0
- data/spec/support/never_available_dependency.rb +5 -0
- data/spec/support/stub_facter.rb +9 -0
- data/spec/support/test.config +11 -0
- metadata +219 -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@ipvs_litmus --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
|
+
[![Build Status](https://secure.travis-ci.org/braintree/ipvs_litmus.png)](http://travis-ci.org/braintree/ipvs_litmus)
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'ipvs_litmus'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install ipvs_litmus
|
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
data/ipvs_litmus.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/ipvs_litmus/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Braintreeps"]
|
6
|
+
gem.email = ["code@getbraintree.com"]
|
7
|
+
gem.description = %q{Backend health tester for HA Services}
|
8
|
+
gem.summary = %q{Backend health tester for HA Services}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "ipvs_litmus"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = IPVSLitmus::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency "sinatra", "~> 1.3.2"
|
19
|
+
gem.add_dependency "facter", "~> 1.6.7"
|
20
|
+
|
21
|
+
gem.add_development_dependency "rspec", "2.9.0"
|
22
|
+
gem.add_development_dependency "rack-test", "0.6.1"
|
23
|
+
gem.add_development_dependency "rake"
|
24
|
+
gem.add_development_dependency "rake_commit", "0.13"
|
25
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module IPVSLitmus
|
2
|
+
class App < Sinatra::Base
|
3
|
+
post "/force/*" do
|
4
|
+
path = *status_file_path(params[:splat])
|
5
|
+
statusfile = StatusFile.new(*path)
|
6
|
+
statusfile.create(params[:reason])
|
7
|
+
|
8
|
+
text 201, "File created"
|
9
|
+
end
|
10
|
+
|
11
|
+
delete "/force/*" do
|
12
|
+
path = *status_file_path(params[:splat])
|
13
|
+
statusfile = StatusFile.new(*path)
|
14
|
+
if statusfile.exists?
|
15
|
+
statusfile.delete
|
16
|
+
text 200, "File deleted"
|
17
|
+
else
|
18
|
+
text 404, "NOT FOUND"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
get "/:service/status" do
|
23
|
+
service = IPVSLitmus.services[params[:service]]
|
24
|
+
if service.nil?
|
25
|
+
text 404, "NOT FOUND"
|
26
|
+
else
|
27
|
+
health = service.current_health
|
28
|
+
response_code = health.ok? ? 200 : 503
|
29
|
+
body = "Health: #{health.value}\n"
|
30
|
+
body << health.summary
|
31
|
+
text response_code, body
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def text(response_code, body)
|
36
|
+
[response_code, { "Content-Type" => "text/plain" }, body]
|
37
|
+
end
|
38
|
+
|
39
|
+
def status_file_path(splat)
|
40
|
+
path = splat.first.split("/")
|
41
|
+
if path.size == 1
|
42
|
+
["global_#{path.first}"]
|
43
|
+
else
|
44
|
+
path
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module IPVSLitmus
|
2
|
+
module CLI
|
3
|
+
class Admin
|
4
|
+
def run(argv = ARGV)
|
5
|
+
command = argv.shift
|
6
|
+
send(command, argv)
|
7
|
+
end
|
8
|
+
|
9
|
+
def force(args)
|
10
|
+
options = _default_options
|
11
|
+
opt_parser = _extend_default_parser(options) do |opts|
|
12
|
+
opts.banner = "Usage: litmusctl force <up|down> [service] [options]"
|
13
|
+
opts.on("-d", "--delete", "Remove status file") do
|
14
|
+
options[:delete] = true
|
15
|
+
end
|
16
|
+
opts.on("-r", "--reason=reason", String, "Reason for status file") do |reason|
|
17
|
+
options[:reason] = reason
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
opt_parser.parse! args
|
22
|
+
direction, service = args
|
23
|
+
|
24
|
+
if options[:delete]
|
25
|
+
request = Net::HTTP::Delete.new("/force/#{direction}/#{service}")
|
26
|
+
else
|
27
|
+
if !options.has_key?(:reason)
|
28
|
+
print "Reason? "
|
29
|
+
options[:reason] = gets.chomp
|
30
|
+
end
|
31
|
+
request = Net::HTTP::Post.new("/force/#{direction}/#{service}")
|
32
|
+
request.set_form_data('reason' => options[:reason])
|
33
|
+
end
|
34
|
+
|
35
|
+
_litmus_request(options[:host], options[:port], request)
|
36
|
+
end
|
37
|
+
|
38
|
+
def status(args)
|
39
|
+
options = _default_options
|
40
|
+
opt_parser = _extend_default_parser(options) do |opts|
|
41
|
+
opts.banner = "Usage: litmusctl status <service> [options]"
|
42
|
+
end
|
43
|
+
|
44
|
+
opt_parser.parse! args
|
45
|
+
service = args.shift
|
46
|
+
|
47
|
+
_litmus_request(options[:host], options[:port], Net::HTTP::Get.new("/#{service}/status"))
|
48
|
+
end
|
49
|
+
|
50
|
+
def _default_options
|
51
|
+
options = { :port => 9292, :host => 'localhost' }
|
52
|
+
end
|
53
|
+
|
54
|
+
def _extend_default_parser(options, &block)
|
55
|
+
OptionParser.new do |opts|
|
56
|
+
block.call(opts)
|
57
|
+
|
58
|
+
opts.on("-p", "--port=port", Integer, "Port litmus is running on", "Default: 9292") do |port|
|
59
|
+
options[:port] = port
|
60
|
+
end
|
61
|
+
opts.on("-h", "--host=ip", String, ":Host litmus is running on", "Default: localhost") do |host|
|
62
|
+
options[:host] = host
|
63
|
+
end
|
64
|
+
opts.on("--help", "Show this help message.") { puts opts; exit }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def _litmus_request(host, port, request)
|
69
|
+
begin
|
70
|
+
http = Net::HTTP.start(host, port)
|
71
|
+
response = http.request(request)
|
72
|
+
|
73
|
+
puts response.body
|
74
|
+
case response
|
75
|
+
when Net::HTTPSuccess then exit 0
|
76
|
+
when Net::HTTPClientError then exit 2
|
77
|
+
else exit 1
|
78
|
+
end
|
79
|
+
rescue Errno::ECONNREFUSED => e
|
80
|
+
puts "Unable to connect to litmus on #{host}:#{port}: #{e.message}"
|
81
|
+
exit 1
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module IPVSLitmus
|
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
|
+
IPVSLitmus.configure(options[:litmus_config])
|
50
|
+
IPVSLitmus.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,20 @@
|
|
1
|
+
module IPVSLitmus
|
2
|
+
class Configuration
|
3
|
+
def initialize(config_file_path)
|
4
|
+
@config_file_path = config_file_path
|
5
|
+
end
|
6
|
+
|
7
|
+
def evaluate
|
8
|
+
config_contents = File.read(@config_file_path)
|
9
|
+
@services = {}
|
10
|
+
instance_eval(config_contents)
|
11
|
+
@services
|
12
|
+
end
|
13
|
+
|
14
|
+
def service(name, &block)
|
15
|
+
service = Service.new(name.to_s)
|
16
|
+
block.call(service)
|
17
|
+
@services[name.to_s] = service
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module IPVSLitmus
|
2
|
+
module Dependency
|
3
|
+
class HTTP
|
4
|
+
def initialize(uri, options = {})
|
5
|
+
@uri = uri
|
6
|
+
@expected_content = Regexp.new(options.fetch(:contnet, '.*'))
|
7
|
+
end
|
8
|
+
|
9
|
+
def available?
|
10
|
+
begin
|
11
|
+
response = Net::HTTP.get_response(URI.parse(@uri))
|
12
|
+
_successful_response?(response) && _body_matches?(response)
|
13
|
+
rescue Exception => e
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def _successful_response?(response)
|
19
|
+
response.is_a? Net::HTTPSuccess
|
20
|
+
end
|
21
|
+
|
22
|
+
def _body_matches?(response)
|
23
|
+
response.body =~ @expected_content
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module IPVSLitmus
|
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.class}: #{health}\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
def ensure(dependency)
|
29
|
+
available = dependency.available?
|
30
|
+
|
31
|
+
@dependencies_available &&= available
|
32
|
+
@summary << "#{dependency.class}: #{available ? 'OK' : 'FAIL'}\n"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module IPVSLitmus
|
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
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module IPVSLitmus
|
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
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module IPVSLitmus
|
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 = IPVSLitmus::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, IPVSLitmus::StatusFile.new('down', @name)],
|
39
|
+
[100, IPVSLitmus::StatusFile.new('up', @name)],
|
40
|
+
[0, IPVSLitmus::StatusFile.new('global_down')],
|
41
|
+
[100, IPVSLitmus::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 IPVSLitmus
|
2
|
+
class StatusFile
|
3
|
+
def initialize(*filenames)
|
4
|
+
@path = File.join(IPVSLitmus.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
|
data/lib/ipvs_litmus.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'net/http'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
require 'bundler/setup'
|
6
|
+
require 'sinatra/base'
|
7
|
+
|
8
|
+
require 'facter'
|
9
|
+
require 'facts/loadaverage'
|
10
|
+
|
11
|
+
require 'ipvs_litmus/app'
|
12
|
+
require 'ipvs_litmus/configuration'
|
13
|
+
require 'ipvs_litmus/dependency/http'
|
14
|
+
require 'ipvs_litmus/health'
|
15
|
+
require 'ipvs_litmus/forced_health'
|
16
|
+
require 'ipvs_litmus/metric/available_memory'
|
17
|
+
require 'ipvs_litmus/metric/cpu_load'
|
18
|
+
require 'ipvs_litmus/service'
|
19
|
+
require 'ipvs_litmus/status_file'
|
20
|
+
|
21
|
+
module IPVSLitmus
|
22
|
+
class << self
|
23
|
+
attr_reader :services, :config_dir
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.configure(filename)
|
27
|
+
@config_file = filename
|
28
|
+
@services = IPVSLitmus::Configuration.new(filename).evaluate
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.config_dir=(path)
|
32
|
+
@config_dir = Pathname.new(path)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.reload
|
36
|
+
configure(@config_file)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.reset
|
40
|
+
@services = {}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Signal.trap("HUP") { IPVSLitmus.reload }
|