litmus_paper 0.9.6 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +2 -2
- data/bin/litmus-agent-check +0 -1
- data/config.ru +1 -0
- data/lib/litmus_paper/agent_check_handler.rb +28 -0
- data/lib/litmus_paper/agent_check_server.rb +97 -0
- data/lib/litmus_paper/app.rb +3 -0
- data/lib/litmus_paper/cli/agent_check.rb +46 -31
- data/lib/litmus_paper/dependency/script.rb +19 -13
- data/lib/litmus_paper/metric/cpu_load.rb +10 -4
- data/lib/litmus_paper/metric/script.rb +20 -14
- data/lib/litmus_paper/terminal_output.rb +2 -0
- data/lib/litmus_paper/version.rb +1 -1
- data/lib/litmus_paper.rb +4 -18
- data/litmus-agent-check.init.sh +130 -0
- data/litmus_paper.gemspec +0 -2
- data/spec/litmus_paper/{cli/agent_check_spec.rb → agent_check_handler_spec.rb} +12 -19
- data/spec/litmus_paper/agent_check_server_spec.rb +57 -0
- data/spec/litmus_paper/app_spec.rb +0 -16
- data/spec/litmus_paper/cli/admin_spec.rb +3 -3
- data/spec/litmus_paper/dependency/script_spec.rb +21 -1
- data/spec/litmus_paper/metric/cpu_load_spec.rb +18 -5
- data/spec/litmus_paper/metric/script_spec.rb +20 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/config.d/passing_test.config +0 -1
- data/spec/support/config.d/test.config +0 -1
- data/spec/support/test.config +1 -2
- data/spec/support/test.reload.config +0 -2
- metadata +9 -43
- data/lib/facts/loadaverage.rb +0 -6
- data/lib/litmus_paper/metric/available_memory.rb +0 -36
- data/spec/litmus_paper/metric/available_memory_spec.rb +0 -58
- data/spec/support/stub_facter.rb +0 -9
- data/xinetd.conf +0 -13
data/README.md
CHANGED
@@ -20,8 +20,8 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
Use the sample config to run it under unicorn. Or
|
24
|
-
agent-check for HAProxy
|
23
|
+
Use the sample config to run it under unicorn. Or execute litmus-agent-check to
|
24
|
+
use it as an agent-check for HAProxy.
|
25
25
|
|
26
26
|
## Contributing
|
27
27
|
|
data/bin/litmus-agent-check
CHANGED
data/config.ru
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
module LitmusPaper
|
2
|
+
class AgentCheckHandler
|
3
|
+
def self.handle(service)
|
4
|
+
output = []
|
5
|
+
health = LitmusPaper.check_service(service)
|
6
|
+
if health.nil?
|
7
|
+
output << "failed#NOT_FOUND"
|
8
|
+
else
|
9
|
+
case health.direction
|
10
|
+
when :up, :health
|
11
|
+
output << "ready" # administrative state
|
12
|
+
output << "up" # operational state
|
13
|
+
when :down
|
14
|
+
output << "drain" # administrative state
|
15
|
+
when :none
|
16
|
+
if health.ok?
|
17
|
+
output << "ready" # administrative state
|
18
|
+
output << "up" # operational state
|
19
|
+
else
|
20
|
+
output << "down" # operational state
|
21
|
+
end
|
22
|
+
end
|
23
|
+
output << "#{health.value.to_s}%"
|
24
|
+
end
|
25
|
+
output.join("\t")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# Preforking TCP server, mostly stolen from Jesse Storimer's Book Working with
|
2
|
+
# TCP Sockets
|
3
|
+
|
4
|
+
require 'socket'
|
5
|
+
require 'litmus_paper/agent_check_handler'
|
6
|
+
|
7
|
+
module LitmusPaper
|
8
|
+
class AgentCheckServer
|
9
|
+
CRLF = "\r\n"
|
10
|
+
|
11
|
+
def initialize(litmus_paper_config, services, workers, pid_file, daemonize)
|
12
|
+
LitmusPaper.configure(litmus_paper_config)
|
13
|
+
@services = services
|
14
|
+
@workers = workers
|
15
|
+
@pid_file = pid_file
|
16
|
+
@daemonize = daemonize
|
17
|
+
@control_sockets = @services.keys.map do |port|
|
18
|
+
TCPServer.new(port)
|
19
|
+
end
|
20
|
+
trap(:INT) { exit }
|
21
|
+
trap(:TERM) { exit }
|
22
|
+
end
|
23
|
+
|
24
|
+
# Stolen pattern from ruby Socket, modified to return the service based on
|
25
|
+
# the accepting port
|
26
|
+
def accept_loop(sockets)
|
27
|
+
if sockets.empty?
|
28
|
+
raise ArgumentError, "no sockets"
|
29
|
+
end
|
30
|
+
loop {
|
31
|
+
readable, _, _ = IO.select(sockets)
|
32
|
+
readable.each { |r|
|
33
|
+
begin
|
34
|
+
sock, addr = r.accept_nonblock
|
35
|
+
service = @services[r.local_address.ip_port]
|
36
|
+
rescue IO::WaitReadable
|
37
|
+
next
|
38
|
+
end
|
39
|
+
yield sock, service
|
40
|
+
}
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def respond(sock, message)
|
45
|
+
sock.write(message)
|
46
|
+
sock.write(CRLF)
|
47
|
+
end
|
48
|
+
|
49
|
+
def write_pid(pid_file)
|
50
|
+
File.open(pid_file, 'w') do |f|
|
51
|
+
f.write(Process.pid)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def run
|
56
|
+
if @daemonize
|
57
|
+
Process.daemon
|
58
|
+
end
|
59
|
+
write_pid(@pid_file)
|
60
|
+
child_pids = []
|
61
|
+
|
62
|
+
@workers.times do
|
63
|
+
child_pids << spawn_child
|
64
|
+
end
|
65
|
+
|
66
|
+
kill_children = Proc.new { |signo|
|
67
|
+
child_pids.each do |cpid|
|
68
|
+
begin
|
69
|
+
Process.kill(:INT, cpid)
|
70
|
+
rescue Errno::ESRCH
|
71
|
+
end
|
72
|
+
end
|
73
|
+
File.delete(@pid_file) if File.exists?(@pid_file)
|
74
|
+
exit
|
75
|
+
}
|
76
|
+
|
77
|
+
trap(:INT, &kill_children)
|
78
|
+
trap(:TERM, &kill_children)
|
79
|
+
|
80
|
+
loop do
|
81
|
+
pid = Process.wait
|
82
|
+
LitmusPaper.logger.error("Process #{pid} quit unexpectedly")
|
83
|
+
child_pids.delete(pid)
|
84
|
+
child_pids << spawn_child
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def spawn_child
|
89
|
+
fork do
|
90
|
+
accept_loop(@control_sockets) do |sock, service|
|
91
|
+
respond(sock, AgentCheckHandler.handle(service))
|
92
|
+
sock.close
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/litmus_paper/app.rb
CHANGED
@@ -1,15 +1,28 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'litmus_paper/agent_check_server'
|
3
|
+
|
1
4
|
module LitmusPaper
|
2
5
|
module CLI
|
3
6
|
class AgentCheck
|
4
7
|
|
5
8
|
def parse_args(args)
|
6
9
|
options = {}
|
10
|
+
options[:pid_file] = '/tmp/litmus-agent-check.pid'
|
7
11
|
optparser = OptionParser.new do |opts|
|
8
|
-
opts.on("-s", "--service SERVICE", "
|
9
|
-
options[:
|
12
|
+
opts.on("-s", "--service SERVICE:PORT,...", Array, "agent-check service to port mappings") do |s|
|
13
|
+
options[:services] = s
|
14
|
+
end
|
15
|
+
opts.on("-c", "--config CONFIG", "Path to litmus paper config file") do |c|
|
16
|
+
options[:litmus_paper_config] = c
|
17
|
+
end
|
18
|
+
opts.on("-p", "--pid-file PID_FILE", String, "Where to write the pid") do |p|
|
19
|
+
options[:pid_file] = p
|
10
20
|
end
|
11
|
-
opts.on("-
|
12
|
-
options[:
|
21
|
+
opts.on("-w", "--workers WORKERS", Integer, "Number of worker processes") do |w|
|
22
|
+
options[:workers] = w
|
23
|
+
end
|
24
|
+
opts.on("-D", "--daemonize", "Daemonize the process") do |d|
|
25
|
+
options[:daemonize] = d
|
13
26
|
end
|
14
27
|
opts.on("-h", "--help", "Help text") do |h|
|
15
28
|
options[:help] = h
|
@@ -29,43 +42,45 @@ module LitmusPaper
|
|
29
42
|
exit 0
|
30
43
|
end
|
31
44
|
|
32
|
-
if !options.has_key?(:
|
33
|
-
puts "Error: `-s SERVICE
|
45
|
+
if !options.has_key?(:services)
|
46
|
+
puts "Error: `-s SERVICE:PORT,...` required"
|
34
47
|
puts optparser
|
35
48
|
exit 1
|
36
49
|
end
|
37
|
-
options
|
38
|
-
end
|
39
50
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
output << "down" # operational state
|
58
|
-
end
|
51
|
+
if !options.has_key?(:workers) || options[:workers] <= 0
|
52
|
+
puts "Error: `-w WORKERS` required, and must be greater than 0"
|
53
|
+
puts " Use a value equal to the number of expected concurrent"
|
54
|
+
puts " agent checks from HAProxy"
|
55
|
+
puts optparser
|
56
|
+
exit 1
|
57
|
+
end
|
58
|
+
|
59
|
+
options[:services] = options[:services].reduce({}) do |memo, service|
|
60
|
+
if service.split(':').length == 2
|
61
|
+
service, port = service.split(':')
|
62
|
+
memo[port.to_i] = service
|
63
|
+
memo
|
64
|
+
else
|
65
|
+
puts "Error: Incorrect service port arg `-s SERVICE:PORT,...`"
|
66
|
+
puts optparser
|
67
|
+
exit 1
|
59
68
|
end
|
60
|
-
output << "#{health.value.to_s}%"
|
61
69
|
end
|
62
|
-
|
70
|
+
|
71
|
+
options
|
63
72
|
end
|
64
73
|
|
65
74
|
def run(args)
|
66
75
|
options = parse_args(args)
|
67
|
-
LitmusPaper.
|
68
|
-
|
76
|
+
agent_check_server = LitmusPaper::AgentCheckServer.new(
|
77
|
+
options[:litmus_paper_config],
|
78
|
+
options[:services],
|
79
|
+
options[:workers],
|
80
|
+
options[:pid_file],
|
81
|
+
options[:daemonize],
|
82
|
+
)
|
83
|
+
agent_check_server.run
|
69
84
|
end
|
70
85
|
|
71
86
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
1
3
|
module LitmusPaper
|
2
4
|
module Dependency
|
3
5
|
class Script
|
@@ -9,23 +11,27 @@ module LitmusPaper
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def available?
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
LitmusPaper.logger.info("Available check to #{@command} failed with status #{$CHILD_STATUS.exitstatus}")
|
21
|
-
LitmusPaper.logger.info("Failed stdout: #{script_stdout}")
|
22
|
-
LitmusPaper.logger.info("Failed stderr: #{script_stderr}")
|
14
|
+
script_status = script_stdout = script_stderr = nil
|
15
|
+
Open3.popen3(@command, :pgroup=>true) do |stdin, stdout, stderr, wait_thr|
|
16
|
+
@script_pid = wait_thr.pid
|
17
|
+
thstderr = Thread.new { stderr.read }
|
18
|
+
thstdout = Thread.new { stdout.read }
|
19
|
+
if !wait_thr.join(@timeout) # wait thread does not end within timeout
|
20
|
+
kill_and_reap_script(-@script_pid) # kill the process group
|
21
|
+
raise Timeout::Error
|
23
22
|
end
|
24
|
-
|
23
|
+
script_stderr = thstderr.value
|
24
|
+
script_stdout = thstdout.value
|
25
|
+
script_status = wait_thr.value
|
26
|
+
end
|
27
|
+
unless script_status.success?
|
28
|
+
LitmusPaper.logger.info("Available check to #{@command} failed with status #{script_status.exitstatus}")
|
29
|
+
LitmusPaper.logger.info("Failed stdout: #{script_stdout}")
|
30
|
+
LitmusPaper.logger.info("Failed stderr: #{script_stderr}")
|
25
31
|
end
|
32
|
+
script_status.success?
|
26
33
|
rescue Timeout::Error
|
27
34
|
LitmusPaper.logger.info("Timeout running command: '#{@command}'")
|
28
|
-
kill_and_reap_script(@script_pid)
|
29
35
|
false
|
30
36
|
rescue => e
|
31
37
|
LitmusPaper.logger.info("Available check to #{@uri} failed with #{e.message}")
|
@@ -1,9 +1,8 @@
|
|
1
1
|
module LitmusPaper
|
2
2
|
module Metric
|
3
3
|
class CPULoad
|
4
|
-
def initialize(weight
|
4
|
+
def initialize(weight)
|
5
5
|
@weight = weight
|
6
|
-
@facter = facter
|
7
6
|
end
|
8
7
|
|
9
8
|
def current_health
|
@@ -11,11 +10,18 @@ module LitmusPaper
|
|
11
10
|
end
|
12
11
|
|
13
12
|
def processor_count
|
14
|
-
@processor_count ||=
|
13
|
+
@processor_count ||= File.readlines('/proc/cpuinfo').reduce(0) do |memo, line|
|
14
|
+
if line =~ /^processor/
|
15
|
+
memo + 1
|
16
|
+
else
|
17
|
+
memo
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
15
21
|
end
|
16
22
|
|
17
23
|
def load_average
|
18
|
-
|
24
|
+
File.read('/proc/loadavg').split(' ').first.to_f
|
19
25
|
end
|
20
26
|
|
21
27
|
def to_s
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
1
3
|
module LitmusPaper
|
2
4
|
module Metric
|
3
5
|
class Script
|
@@ -15,24 +17,28 @@ module LitmusPaper
|
|
15
17
|
|
16
18
|
def result
|
17
19
|
value = 0
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
LitmusPaper.logger.info("Available check to #{@command} failed with status #{$CHILD_STATUS.exitstatus}")
|
27
|
-
LitmusPaper.logger.info("Failed stdout: #{script_stdout}")
|
28
|
-
LitmusPaper.logger.info("Failed stderr: #{script_stderr}")
|
20
|
+
script_status = script_stdout = script_stderr = nil
|
21
|
+
Open3.popen3(@command, :pgroup=>true) do |stdin, stdout, stderr, wait_thr|
|
22
|
+
@script_pid = wait_thr.pid
|
23
|
+
thstderr = Thread.new { stderr.read }
|
24
|
+
thstdout = Thread.new { stdout.read }
|
25
|
+
if !wait_thr.join(@timeout) # wait thread does not end within timeout
|
26
|
+
kill_and_reap_script(-@script_pid) # kill the process group
|
27
|
+
raise Timeout::Error
|
29
28
|
end
|
30
|
-
|
31
|
-
value
|
29
|
+
script_stderr = thstderr.value
|
30
|
+
script_stdout = thstdout.value
|
31
|
+
value = script_stdout.strip
|
32
|
+
script_status = wait_thr.value
|
33
|
+
end
|
34
|
+
unless script_status.success?
|
35
|
+
LitmusPaper.logger.info("Available check to #{@command} failed with status #{script_status.exitstatus}")
|
36
|
+
LitmusPaper.logger.info("Failed stdout: #{script_stdout}")
|
37
|
+
LitmusPaper.logger.info("Failed stderr: #{script_stderr}")
|
32
38
|
end
|
39
|
+
value.to_f
|
33
40
|
rescue Timeout::Error
|
34
41
|
LitmusPaper.logger.info("Available check to '#{@command}' timed out")
|
35
|
-
kill_and_reap_script(@script_pid)
|
36
42
|
0
|
37
43
|
end
|
38
44
|
|
data/lib/litmus_paper/version.rb
CHANGED
data/lib/litmus_paper.rb
CHANGED
@@ -1,11 +1,3 @@
|
|
1
|
-
require 'pathname'
|
2
|
-
require 'net/http'
|
3
|
-
require 'net/https'
|
4
|
-
require 'uri'
|
5
|
-
require 'forwardable'
|
6
|
-
require 'English'
|
7
|
-
require 'colorize'
|
8
|
-
|
9
1
|
# Ruby's stock DNS resolution, by default, blocks the entire Ruby VM from
|
10
2
|
# processing while the lookup is happening, because it calls out to the native
|
11
3
|
# libc resolver code. A slow DNS server can cause your entire Ruby process to
|
@@ -15,15 +7,13 @@ require 'colorize'
|
|
15
7
|
# 'resolv-replace' monkeypatches the various Ruby Socket objects to use resolv
|
16
8
|
#
|
17
9
|
require 'resolv-replace'
|
10
|
+
require 'net/http'
|
11
|
+
require 'net/https'
|
12
|
+
require 'uri'
|
13
|
+
require 'forwardable'
|
18
14
|
|
19
|
-
require 'popen4'
|
20
|
-
require 'sinatra/base'
|
21
|
-
require 'facter'
|
22
15
|
require 'remote_syslog_logger'
|
23
16
|
|
24
|
-
require 'facts/loadaverage'
|
25
|
-
|
26
|
-
require 'litmus_paper/app'
|
27
17
|
require 'litmus_paper/configuration'
|
28
18
|
require 'litmus_paper/configuration_file'
|
29
19
|
require 'litmus_paper/dependency/file_contents'
|
@@ -33,7 +23,6 @@ require 'litmus_paper/dependency/script'
|
|
33
23
|
require 'litmus_paper/dependency/tcp'
|
34
24
|
require 'litmus_paper/health'
|
35
25
|
require 'litmus_paper/logger'
|
36
|
-
require 'litmus_paper/metric/available_memory'
|
37
26
|
require 'litmus_paper/metric/big_brother_service'
|
38
27
|
require 'litmus_paper/metric/constant_metric'
|
39
28
|
require 'litmus_paper/metric/cpu_load'
|
@@ -41,7 +30,6 @@ require 'litmus_paper/metric/internet_health'
|
|
41
30
|
require 'litmus_paper/metric/script'
|
42
31
|
require 'litmus_paper/service'
|
43
32
|
require 'litmus_paper/status_file'
|
44
|
-
require 'litmus_paper/terminal_output'
|
45
33
|
require 'litmus_paper/version'
|
46
34
|
|
47
35
|
module LitmusPaper
|
@@ -54,8 +42,6 @@ module LitmusPaper
|
|
54
42
|
self.logger = Logger.new
|
55
43
|
|
56
44
|
def self.check_service(service_name)
|
57
|
-
Facter.flush
|
58
|
-
|
59
45
|
if service = services[service_name]
|
60
46
|
service.current_health
|
61
47
|
else
|
@@ -0,0 +1,130 @@
|
|
1
|
+
#! /bin/sh
|
2
|
+
### BEGIN INIT INFO
|
3
|
+
# Provides: litmus-agent-check
|
4
|
+
# Required-Start: $remote_fs $syslog
|
5
|
+
# Required-Stop: $remote_fs $syslog
|
6
|
+
# Default-Start: 2 3 4 5
|
7
|
+
# Default-Stop: 0 1 6
|
8
|
+
# Short-Description: Litmus agent-check for HAProxy
|
9
|
+
# Description: Provide an agent-check server for HAProxy
|
10
|
+
### END INIT INFO
|
11
|
+
|
12
|
+
# Author: Braintreeps <code@getbraintree.com>
|
13
|
+
|
14
|
+
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
15
|
+
DESC="Litmus HAProxy agent-check server"
|
16
|
+
NAME=litmus-agent-check
|
17
|
+
DAEMON=/usr/bin/$NAME
|
18
|
+
PIDFILE=/var/run/litmus-agent-check/pid
|
19
|
+
DAEMON_ARGS="-D -p ${PIDFILE}"
|
20
|
+
SCRIPTNAME=/etc/init.d/$NAME
|
21
|
+
|
22
|
+
# Exit if the package is not installed
|
23
|
+
[ -x "$DAEMON" ] || exit 0
|
24
|
+
|
25
|
+
# Read configuration variable file if it is present
|
26
|
+
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
|
27
|
+
|
28
|
+
# Define LSB log_* functions.
|
29
|
+
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
|
30
|
+
. /lib/lsb/init-functions
|
31
|
+
|
32
|
+
#
|
33
|
+
# Function that starts the daemon/service
|
34
|
+
#
|
35
|
+
do_start()
|
36
|
+
{
|
37
|
+
mkdir -p $(dirname $PIDFILE)
|
38
|
+
# Return
|
39
|
+
# 0 if daemon has been started
|
40
|
+
# 1 if daemon was already running
|
41
|
+
# 2 if daemon could not be started
|
42
|
+
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|
43
|
+
|| return 1
|
44
|
+
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
|
45
|
+
$DAEMON_ARGS $EXTRA_ARGS\
|
46
|
+
|| return 2
|
47
|
+
# Add code here, if necessary, that waits for the process to be ready
|
48
|
+
# to handle requests from services started subsequently which depend
|
49
|
+
# on this one. As a last resort, sleep for some time.
|
50
|
+
}
|
51
|
+
|
52
|
+
#
|
53
|
+
# Function that stops the daemon/service
|
54
|
+
#
|
55
|
+
do_stop()
|
56
|
+
{
|
57
|
+
# Return
|
58
|
+
# 0 if daemon has been stopped
|
59
|
+
# 1 if daemon was already stopped
|
60
|
+
# 2 if daemon could not be stopped
|
61
|
+
# other if a failure occurred
|
62
|
+
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE
|
63
|
+
RETVAL="$?"
|
64
|
+
[ "$RETVAL" = 2 ] && return 2
|
65
|
+
# Many daemons don't delete their pidfiles when they exit.
|
66
|
+
rm -f $PIDFILE
|
67
|
+
return "$RETVAL"
|
68
|
+
}
|
69
|
+
|
70
|
+
#
|
71
|
+
# Function that sends a SIGHUP to the daemon/service
|
72
|
+
#
|
73
|
+
do_reload() {
|
74
|
+
#
|
75
|
+
# If the daemon can reload its configuration without
|
76
|
+
# restarting (for example, when it is sent a SIGHUP),
|
77
|
+
# then implement that here.
|
78
|
+
#
|
79
|
+
start-stop-daemon --stop --signal HUP --quiet --pidfile $PIDFILE
|
80
|
+
return 0
|
81
|
+
}
|
82
|
+
|
83
|
+
case "$1" in
|
84
|
+
start)
|
85
|
+
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
|
86
|
+
do_start
|
87
|
+
case "$?" in
|
88
|
+
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
89
|
+
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
90
|
+
esac
|
91
|
+
;;
|
92
|
+
stop)
|
93
|
+
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
94
|
+
do_stop
|
95
|
+
case "$?" in
|
96
|
+
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
97
|
+
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
98
|
+
esac
|
99
|
+
;;
|
100
|
+
status)
|
101
|
+
status_of_proc -p ${PIDFILE} && exit 0 || exit $?
|
102
|
+
;;
|
103
|
+
reload|force-reload)
|
104
|
+
log_daemon_msg "Reloading $DESC" "$NAME"
|
105
|
+
do_reload
|
106
|
+
log_end_msg $?
|
107
|
+
;;
|
108
|
+
restart)
|
109
|
+
log_daemon_msg "Restarting $DESC" "$NAME"
|
110
|
+
do_stop
|
111
|
+
case "$?" in
|
112
|
+
0|1)
|
113
|
+
do_start
|
114
|
+
case "$?" in
|
115
|
+
0) log_end_msg 0 ;;
|
116
|
+
1) log_end_msg 1 ;; # Old process is still running
|
117
|
+
*) log_end_msg 1 ;; # Failed to start
|
118
|
+
esac
|
119
|
+
;;
|
120
|
+
*)
|
121
|
+
# Failed to stop
|
122
|
+
log_end_msg 1
|
123
|
+
;;
|
124
|
+
esac
|
125
|
+
;;
|
126
|
+
*)
|
127
|
+
echo "Usage: $SCRIPTNAME {start|stop|status|restart|reload|force-reload}" >&2
|
128
|
+
exit 3
|
129
|
+
;;
|
130
|
+
esac
|
data/litmus_paper.gemspec
CHANGED
@@ -17,9 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.version = LitmusPaper::VERSION
|
18
18
|
|
19
19
|
gem.add_dependency "sinatra", "~> 1.3.2"
|
20
|
-
gem.add_dependency "facter", "~> 1.7.5"
|
21
20
|
gem.add_dependency "remote_syslog_logger", "~> 1.0.3"
|
22
|
-
gem.add_dependency "popen4", "~> 0.1.2"
|
23
21
|
gem.add_dependency "unicorn", "~> 4.6.2"
|
24
22
|
gem.add_dependency "colorize"
|
25
23
|
|
@@ -1,47 +1,40 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'litmus_paper/
|
2
|
+
require 'litmus_paper/agent_check_handler'
|
3
3
|
|
4
|
-
describe LitmusPaper::
|
4
|
+
describe LitmusPaper::AgentCheckHandler do
|
5
5
|
before :each do
|
6
6
|
LitmusPaper.configure(TEST_CONFIG)
|
7
7
|
end
|
8
8
|
|
9
|
-
def agent_check(service)
|
10
|
-
output = StringIO.new
|
11
|
-
LitmusPaper::CLI::AgentCheck.new.output_service_status(service, output)
|
12
|
-
output.rewind
|
13
|
-
output.readline
|
14
|
-
end
|
15
|
-
|
16
9
|
describe "output_service_status" do
|
17
10
|
it "returns the forced health value for a healthy service" do
|
18
11
|
test_service = LitmusPaper::Service.new('test', [AlwaysAvailableDependency.new], [LitmusPaper::Metric::ConstantMetric.new(100)])
|
19
12
|
LitmusPaper.services['test'] = test_service
|
20
13
|
LitmusPaper::StatusFile.service_health_file("test").create("Forcing health", 88)
|
21
|
-
|
14
|
+
LitmusPaper::AgentCheckHandler.handle("test").should == "ready\tup\t88%"
|
22
15
|
end
|
23
16
|
|
24
17
|
it "returns the actual health value for an unhealthy service when the measured health is less than the forced value" do
|
25
18
|
test_service = LitmusPaper::Service.new('test', [NeverAvailableDependency.new], [LitmusPaper::Metric::ConstantMetric.new(100)])
|
26
19
|
LitmusPaper.services['test'] = test_service
|
27
20
|
LitmusPaper::StatusFile.service_health_file("test").create("Forcing health", 88)
|
28
|
-
|
21
|
+
LitmusPaper::AgentCheckHandler.handle("test").should == "ready\tup\t0%"
|
29
22
|
end
|
30
23
|
|
31
24
|
it "is 'ready' when the service is passing" do
|
32
25
|
test_service = LitmusPaper::Service.new('test', [AlwaysAvailableDependency.new], [LitmusPaper::Metric::ConstantMetric.new(100)])
|
33
26
|
LitmusPaper.services['test'] = test_service
|
34
|
-
|
27
|
+
LitmusPaper::AgentCheckHandler.handle("test").should == "ready\tup\t100%"
|
35
28
|
end
|
36
29
|
|
37
30
|
it "is 'down' when the check fails" do
|
38
31
|
test_service = LitmusPaper::Service.new('test', [NeverAvailableDependency.new], [LitmusPaper::Metric::ConstantMetric.new(100)])
|
39
32
|
LitmusPaper.services['test'] = test_service
|
40
|
-
|
33
|
+
LitmusPaper::AgentCheckHandler.handle("test").should == "down\t0%"
|
41
34
|
end
|
42
35
|
|
43
36
|
it "is 'failed' when the service is unknown" do
|
44
|
-
|
37
|
+
LitmusPaper::AgentCheckHandler.handle("unknown").should == "failed#NOT_FOUND"
|
45
38
|
end
|
46
39
|
|
47
40
|
it "is 'drain' when an up file and down file exists" do
|
@@ -49,7 +42,7 @@ describe LitmusPaper::CLI::AgentCheck do
|
|
49
42
|
LitmusPaper.services['test'] = test_service
|
50
43
|
LitmusPaper::StatusFile.service_up_file("test").create("Up for testing")
|
51
44
|
LitmusPaper::StatusFile.service_down_file("test").create("Down for testing")
|
52
|
-
|
45
|
+
LitmusPaper::AgentCheckHandler.handle("test").should == "drain\t0%"
|
53
46
|
end
|
54
47
|
|
55
48
|
it "is 'drain' when a global down file and up file exists" do
|
@@ -57,28 +50,28 @@ describe LitmusPaper::CLI::AgentCheck do
|
|
57
50
|
LitmusPaper.services['test'] = test_service
|
58
51
|
LitmusPaper::StatusFile.global_down_file.create("Down for testing")
|
59
52
|
LitmusPaper::StatusFile.global_up_file.create("Up for testing")
|
60
|
-
|
53
|
+
LitmusPaper::AgentCheckHandler.handle("test").should == "drain\t0%"
|
61
54
|
end
|
62
55
|
|
63
56
|
it "is 'ready' when an up file exists" do
|
64
57
|
test_service = LitmusPaper::Service.new('test', [NeverAvailableDependency.new], [LitmusPaper::Metric::ConstantMetric.new(100)])
|
65
58
|
LitmusPaper.services['test'] = test_service
|
66
59
|
LitmusPaper::StatusFile.service_up_file("test").create("Up for testing")
|
67
|
-
|
60
|
+
LitmusPaper::AgentCheckHandler.handle("test").should == "ready\tup\t100%"
|
68
61
|
end
|
69
62
|
|
70
63
|
it "is 'drain' when a global down file exists" do
|
71
64
|
test_service = LitmusPaper::Service.new('test', [AlwaysAvailableDependency.new], [LitmusPaper::Metric::ConstantMetric.new(100)])
|
72
65
|
LitmusPaper.services['test'] = test_service
|
73
66
|
LitmusPaper::StatusFile.global_down_file.create("Down for testing")
|
74
|
-
|
67
|
+
LitmusPaper::AgentCheckHandler.handle("test").should == "drain\t0%"
|
75
68
|
end
|
76
69
|
|
77
70
|
it "is 'ready' when a global up file exists" do
|
78
71
|
test_service = LitmusPaper::Service.new('test', [NeverAvailableDependency.new], [LitmusPaper::Metric::ConstantMetric.new(100)])
|
79
72
|
LitmusPaper.services['test'] = test_service
|
80
73
|
LitmusPaper::StatusFile.global_up_file.create("Up for testing")
|
81
|
-
|
74
|
+
LitmusPaper::AgentCheckHandler.handle("test").should == "ready\tup\t100%"
|
82
75
|
end
|
83
76
|
end
|
84
77
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'litmus_paper/agent_check_server'
|
3
|
+
|
4
|
+
describe LitmusPaper::AgentCheckServer do
|
5
|
+
pid = nil
|
6
|
+
|
7
|
+
before :all do
|
8
|
+
if ! Kernel.system("bundle exec litmus-agent-check -s passing_test:9191,test:9192 -c spec/support/test.config -w 10 -D")
|
9
|
+
fail('Unable to start server')
|
10
|
+
end
|
11
|
+
port_open = false
|
12
|
+
while ! port_open do
|
13
|
+
begin
|
14
|
+
TCPSocket.new('localhost', 9191)
|
15
|
+
rescue StandardError => e
|
16
|
+
sleep 0.1
|
17
|
+
next
|
18
|
+
end
|
19
|
+
port_open = true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
after :all do
|
24
|
+
Process.kill(:TERM, File.read('/tmp/litmus-agent-check.pid').to_i)
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "The agent-check text protocol" do
|
28
|
+
it "returns the health from a passing test" do
|
29
|
+
TCPSocket.open('localhost', 9191) do |s|
|
30
|
+
s.gets.should match(/ready\tup\t\d+%\r\n/)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
it "returns the health from a failing test" do
|
34
|
+
TCPSocket.open('localhost', 9192) do |s|
|
35
|
+
s.gets.should match(/down\t0%\r\n/)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "server" do
|
41
|
+
it "has the configured number of children running" do
|
42
|
+
pid = File.read('/tmp/litmus-agent-check.pid').to_i
|
43
|
+
children = `ps --no-headers --ppid #{pid}|wc -l`
|
44
|
+
children.strip.to_i == 10
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "server" do
|
49
|
+
it "if a child dies you get a new one" do
|
50
|
+
pid = File.read('/tmp/litmus-agent-check.pid').to_i
|
51
|
+
Kernel.system("kill -9 $(ps --no-headers --ppid #{pid} -o pid=|tail -1)")
|
52
|
+
sleep 0.5
|
53
|
+
children = `ps --no-headers --ppid #{pid}|wc -l`
|
54
|
+
children.strip.to_i == 10
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -418,22 +418,6 @@ describe LitmusPaper::App do
|
|
418
418
|
last_response.headers["X-Health-Forced"].should == "up"
|
419
419
|
last_response.body.should match(/Up for testing/)
|
420
420
|
end
|
421
|
-
|
422
|
-
it "resets the Facter cache" do
|
423
|
-
test_service = LitmusPaper::Service.new('test', [AlwaysAvailableDependency.new], [LitmusPaper::Metric::ConstantMetric.new(100)])
|
424
|
-
LitmusPaper.services['test'] = test_service
|
425
|
-
|
426
|
-
get "/test/status"
|
427
|
-
last_response.should be_ok
|
428
|
-
|
429
|
-
facter_uptime = Facter.value("uptime_seconds")
|
430
|
-
sleep 1
|
431
|
-
|
432
|
-
get "/test/status"
|
433
|
-
last_response.should be_ok
|
434
|
-
|
435
|
-
Facter.value("uptime_seconds").should > facter_uptime
|
436
|
-
end
|
437
421
|
end
|
438
422
|
|
439
423
|
describe "server errors" do
|
@@ -33,7 +33,7 @@ describe 'litmusctl' do
|
|
33
33
|
describe 'status' do
|
34
34
|
it 'returns the status of a service' do
|
35
35
|
_litmusctl('status test').should match("Health: 0")
|
36
|
-
_litmusctl('status passing_test').should match(/Health: \d
|
36
|
+
_litmusctl('status passing_test').should match(/Health: \d+/)
|
37
37
|
end
|
38
38
|
|
39
39
|
it "returns 'NOT FOUND' for a service that doesn't exist" do
|
@@ -79,7 +79,7 @@ describe 'litmusctl' do
|
|
79
79
|
_litmusctl('force up test -d').should match("File deleted")
|
80
80
|
|
81
81
|
status = _litmusctl('status passing_test')
|
82
|
-
status.should match(/Health: \d
|
82
|
+
status.should match(/Health: \d+/)
|
83
83
|
status.should_not match(/for testing/)
|
84
84
|
end
|
85
85
|
|
@@ -87,7 +87,7 @@ describe 'litmusctl' do
|
|
87
87
|
_litmusctl('force health 88 test -r "for testing"').should match("File created")
|
88
88
|
_litmusctl('force health test -d').should match("File deleted")
|
89
89
|
status = _litmusctl('status passing_test')
|
90
|
-
status.should match(/Health: \d
|
90
|
+
status.should match(/Health: \d+/)
|
91
91
|
status.should_not match(/for testing/)
|
92
92
|
end
|
93
93
|
|
@@ -7,8 +7,28 @@ describe LitmusPaper::Dependency::Script do
|
|
7
7
|
check.should be_available
|
8
8
|
end
|
9
9
|
|
10
|
+
it "is true when the script returns a lot of data" do
|
11
|
+
check = LitmusPaper::Dependency::Script.new("dd if=/dev/urandom bs=1M count=1|base64")
|
12
|
+
check.should be_available
|
13
|
+
end
|
14
|
+
|
10
15
|
it "is false when the script returns 1" do
|
11
|
-
check = LitmusPaper::Dependency::Script.new("false")
|
16
|
+
check = LitmusPaper::Dependency::Script.new("echo Hello && echo Goodbye 1>&2 && false")
|
17
|
+
check.should_not be_available
|
18
|
+
end
|
19
|
+
|
20
|
+
it "logs stdout and stderr when it fails" do
|
21
|
+
check = LitmusPaper::Dependency::Script.new("echo Hello && echo Goodbye 1>&2 && false")
|
22
|
+
count = 0
|
23
|
+
logs = [
|
24
|
+
"Available check to echo Hello && echo Goodbye 1>&2 && false failed with status 1",
|
25
|
+
"Failed stdout: Hello\n",
|
26
|
+
"Failed stderr: Goodbye\n",
|
27
|
+
]
|
28
|
+
LitmusPaper.logger.should_receive(:info).exactly(3).times do |log|
|
29
|
+
log.should == logs[count]
|
30
|
+
count += 1
|
31
|
+
end
|
12
32
|
check.should_not be_available
|
13
33
|
end
|
14
34
|
|
@@ -3,14 +3,20 @@ require 'spec_helper'
|
|
3
3
|
describe LitmusPaper::Metric::CPULoad do
|
4
4
|
describe "#current_health" do
|
5
5
|
it "is the percent of available cpu capacity" do
|
6
|
-
|
7
|
-
|
6
|
+
LitmusPaper::Metric::CPULoad.any_instance.stub(
|
7
|
+
:processor_count => 4,
|
8
|
+
:load_average => 1.00,
|
9
|
+
)
|
10
|
+
cpu_load = LitmusPaper::Metric::CPULoad.new(40)
|
8
11
|
cpu_load.current_health.should == 30
|
9
12
|
end
|
10
13
|
|
11
14
|
it "is one when the load is above one per core" do
|
12
|
-
|
13
|
-
|
15
|
+
LitmusPaper::Metric::CPULoad.any_instance.stub(
|
16
|
+
:processor_count => 4,
|
17
|
+
:load_average => 20.00,
|
18
|
+
)
|
19
|
+
cpu_load = LitmusPaper::Metric::CPULoad.new(50)
|
14
20
|
cpu_load.current_health.should == 1
|
15
21
|
end
|
16
22
|
end
|
@@ -22,7 +28,7 @@ describe LitmusPaper::Metric::CPULoad do
|
|
22
28
|
end
|
23
29
|
|
24
30
|
it "is cached" do
|
25
|
-
|
31
|
+
File.should_receive(:readlines).with('/proc/cpuinfo').once.and_return(["processor : 0\n"])
|
26
32
|
cpu_load = LitmusPaper::Metric::CPULoad.new(50)
|
27
33
|
cpu_load.processor_count
|
28
34
|
cpu_load.processor_count
|
@@ -35,6 +41,13 @@ describe LitmusPaper::Metric::CPULoad do
|
|
35
41
|
cpu_load = LitmusPaper::Metric::CPULoad.new(50)
|
36
42
|
cpu_load.load_average.should > 0.0
|
37
43
|
end
|
44
|
+
|
45
|
+
it "is not cached" do
|
46
|
+
File.should_receive(:read).with('/proc/loadavg').twice.and_return("0.08 0.12 0.15 2/1190 9152\n")
|
47
|
+
cpu_load = LitmusPaper::Metric::CPULoad.new(50)
|
48
|
+
cpu_load.load_average.should > 0.0
|
49
|
+
cpu_load.load_average.should > 0.0
|
50
|
+
end
|
38
51
|
end
|
39
52
|
|
40
53
|
describe "#to_s" do
|
@@ -7,6 +7,26 @@ describe LitmusPaper::Metric::Script do
|
|
7
7
|
check.current_health.should == 1
|
8
8
|
end
|
9
9
|
|
10
|
+
it "is true when the script returns a lot of data" do
|
11
|
+
check = LitmusPaper::Metric::Script.new("dd if=/dev/urandom bs=1M count=1|base64 >&2 && echo 1", 1)
|
12
|
+
check.current_health.should == 1
|
13
|
+
end
|
14
|
+
|
15
|
+
it "logs stdout and stderr when it fails" do
|
16
|
+
check = LitmusPaper::Metric::Script.new("echo Hello && echo Goodbye 1>&2 && false", 1)
|
17
|
+
count = 0
|
18
|
+
logs = [
|
19
|
+
"Available check to echo Hello && echo Goodbye 1>&2 && false failed with status 1",
|
20
|
+
"Failed stdout: Hello\n",
|
21
|
+
"Failed stderr: Goodbye\n",
|
22
|
+
]
|
23
|
+
LitmusPaper.logger.should_receive(:info).exactly(3).times do |log|
|
24
|
+
log.should == logs[count]
|
25
|
+
count += 1
|
26
|
+
end
|
27
|
+
check.current_health.should == 0
|
28
|
+
end
|
29
|
+
|
10
30
|
it "is zero when the script exits 1" do
|
11
31
|
check = LitmusPaper::Metric::Script.new("false", 1)
|
12
32
|
check.current_health.should == 0
|
data/spec/spec_helper.rb
CHANGED
data/spec/support/test.config
CHANGED
@@ -8,10 +8,9 @@ service :test do |s|
|
|
8
8
|
s.depends Dependency::HTTP, "http://localhost/heartbeat"
|
9
9
|
|
10
10
|
s.measure_health Metric::CPULoad, :weight => 50
|
11
|
-
s.measure_health Metric::AvailableMemory, :weight => 50
|
12
11
|
end
|
13
12
|
|
14
13
|
service :passing_test do |s|
|
15
14
|
s.measure_health Metric::CPULoad, :weight => 50
|
16
|
-
s.
|
15
|
+
s.depends Dependency::Script, "/bin/true"
|
17
16
|
end
|
@@ -8,10 +8,8 @@ service :foo do |s|
|
|
8
8
|
s.depends Dependency::HTTP, "http://localhost/heartbeat"
|
9
9
|
|
10
10
|
s.measure_health Metric::CPULoad, :weight => 50
|
11
|
-
s.measure_health Metric::AvailableMemory, :weight => 50
|
12
11
|
end
|
13
12
|
|
14
13
|
service :passing_test do |s|
|
15
14
|
s.measure_health Metric::CPULoad, :weight => 50
|
16
|
-
s.measure_health Metric::AvailableMemory, :weight => 50
|
17
15
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: litmus_paper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-
|
12
|
+
date: 2017-06-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sinatra
|
@@ -27,22 +27,6 @@ dependencies:
|
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 1.3.2
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: facter
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
|
-
requirements:
|
35
|
-
- - ~>
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: 1.7.5
|
38
|
-
type: :runtime
|
39
|
-
prerelease: false
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: 1.7.5
|
46
30
|
- !ruby/object:Gem::Dependency
|
47
31
|
name: remote_syslog_logger
|
48
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -59,22 +43,6 @@ dependencies:
|
|
59
43
|
- - ~>
|
60
44
|
- !ruby/object:Gem::Version
|
61
45
|
version: 1.0.3
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: popen4
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
|
-
requirements:
|
67
|
-
- - ~>
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: 0.1.2
|
70
|
-
type: :runtime
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ~>
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: 0.1.2
|
78
46
|
- !ruby/object:Gem::Dependency
|
79
47
|
name: unicorn
|
80
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -193,8 +161,9 @@ files:
|
|
193
161
|
- bin/litmus-agent-check
|
194
162
|
- bin/litmusctl
|
195
163
|
- config.ru
|
196
|
-
- lib/facts/loadaverage.rb
|
197
164
|
- lib/litmus_paper.rb
|
165
|
+
- lib/litmus_paper/agent_check_handler.rb
|
166
|
+
- lib/litmus_paper/agent_check_server.rb
|
198
167
|
- lib/litmus_paper/app.rb
|
199
168
|
- lib/litmus_paper/cli/admin.rb
|
200
169
|
- lib/litmus_paper/cli/admin/command.rb
|
@@ -212,7 +181,6 @@ files:
|
|
212
181
|
- lib/litmus_paper/dependency/tcp.rb
|
213
182
|
- lib/litmus_paper/health.rb
|
214
183
|
- lib/litmus_paper/logger.rb
|
215
|
-
- lib/litmus_paper/metric/available_memory.rb
|
216
184
|
- lib/litmus_paper/metric/big_brother_service.rb
|
217
185
|
- lib/litmus_paper/metric/constant_metric.rb
|
218
186
|
- lib/litmus_paper/metric/cpu_load.rb
|
@@ -222,10 +190,12 @@ files:
|
|
222
190
|
- lib/litmus_paper/status_file.rb
|
223
191
|
- lib/litmus_paper/terminal_output.rb
|
224
192
|
- lib/litmus_paper/version.rb
|
193
|
+
- litmus-agent-check.init.sh
|
225
194
|
- litmus_paper.gemspec
|
195
|
+
- spec/litmus_paper/agent_check_handler_spec.rb
|
196
|
+
- spec/litmus_paper/agent_check_server_spec.rb
|
226
197
|
- spec/litmus_paper/app_spec.rb
|
227
198
|
- spec/litmus_paper/cli/admin_spec.rb
|
228
|
-
- spec/litmus_paper/cli/agent_check_spec.rb
|
229
199
|
- spec/litmus_paper/configuration_file_spec.rb
|
230
200
|
- spec/litmus_paper/dependency/file_contents_spec.rb
|
231
201
|
- spec/litmus_paper/dependency/haproxy_backends_spec.rb
|
@@ -233,7 +203,6 @@ files:
|
|
233
203
|
- spec/litmus_paper/dependency/script_spec.rb
|
234
204
|
- spec/litmus_paper/dependency/tcp_spec.rb
|
235
205
|
- spec/litmus_paper/health_spec.rb
|
236
|
-
- spec/litmus_paper/metric/available_memory_spec.rb
|
237
206
|
- spec/litmus_paper/metric/big_brother_service_spec.rb
|
238
207
|
- spec/litmus_paper/metric/constant_metric_spec.rb
|
239
208
|
- spec/litmus_paper/metric/cpu_load_spec.rb
|
@@ -254,12 +223,10 @@ files:
|
|
254
223
|
- spec/support/http_test_server_config.ru
|
255
224
|
- spec/support/never_available_dependency.rb
|
256
225
|
- spec/support/stdout_logger.rb
|
257
|
-
- spec/support/stub_facter.rb
|
258
226
|
- spec/support/test.config
|
259
227
|
- spec/support/test.d.config
|
260
228
|
- spec/support/test.reload.config
|
261
229
|
- spec/support/test.unicorn.config
|
262
|
-
- xinetd.conf
|
263
230
|
homepage: https://github.com/braintree/litmus_paper
|
264
231
|
licenses: []
|
265
232
|
post_install_message:
|
@@ -285,9 +252,10 @@ signing_key:
|
|
285
252
|
specification_version: 3
|
286
253
|
summary: Backend health tester for HA Services, partner project of big_brother
|
287
254
|
test_files:
|
255
|
+
- spec/litmus_paper/agent_check_handler_spec.rb
|
256
|
+
- spec/litmus_paper/agent_check_server_spec.rb
|
288
257
|
- spec/litmus_paper/app_spec.rb
|
289
258
|
- spec/litmus_paper/cli/admin_spec.rb
|
290
|
-
- spec/litmus_paper/cli/agent_check_spec.rb
|
291
259
|
- spec/litmus_paper/configuration_file_spec.rb
|
292
260
|
- spec/litmus_paper/dependency/file_contents_spec.rb
|
293
261
|
- spec/litmus_paper/dependency/haproxy_backends_spec.rb
|
@@ -295,7 +263,6 @@ test_files:
|
|
295
263
|
- spec/litmus_paper/dependency/script_spec.rb
|
296
264
|
- spec/litmus_paper/dependency/tcp_spec.rb
|
297
265
|
- spec/litmus_paper/health_spec.rb
|
298
|
-
- spec/litmus_paper/metric/available_memory_spec.rb
|
299
266
|
- spec/litmus_paper/metric/big_brother_service_spec.rb
|
300
267
|
- spec/litmus_paper/metric/constant_metric_spec.rb
|
301
268
|
- spec/litmus_paper/metric/cpu_load_spec.rb
|
@@ -316,7 +283,6 @@ test_files:
|
|
316
283
|
- spec/support/http_test_server_config.ru
|
317
284
|
- spec/support/never_available_dependency.rb
|
318
285
|
- spec/support/stdout_logger.rb
|
319
|
-
- spec/support/stub_facter.rb
|
320
286
|
- spec/support/test.config
|
321
287
|
- spec/support/test.d.config
|
322
288
|
- spec/support/test.reload.config
|
data/lib/facts/loadaverage.rb
DELETED
@@ -1,36 +0,0 @@
|
|
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('memorysize').split(' ')
|
23
|
-
@memory_total = (size.to_f * MULTIPLIER[scale]).to_i
|
24
|
-
end
|
25
|
-
|
26
|
-
def memory_free
|
27
|
-
size, scale = @facter.value('memoryfree').split(' ')
|
28
|
-
(size.to_f * MULTIPLIER[scale]).to_i
|
29
|
-
end
|
30
|
-
|
31
|
-
def to_s
|
32
|
-
"Metric::AvailableMemory(#{@weight})"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe LitmusPaper::Metric::AvailableMemory do
|
4
|
-
describe "#current_health" do
|
5
|
-
it "multiplies weight by memory available" do
|
6
|
-
facter = StubFacter.new({"memorysize" => "10 GB", "memoryfree" => "5 GB"})
|
7
|
-
memory = LitmusPaper::Metric::AvailableMemory.new(50, facter)
|
8
|
-
memory.current_health.should == 25
|
9
|
-
end
|
10
|
-
|
11
|
-
it "multiplies weight by memory available when handling floating point values" do
|
12
|
-
facter = StubFacter.new({"memorysize" => "2.0 GB", "memoryfree" => "1.8 GB"})
|
13
|
-
memory = LitmusPaper::Metric::AvailableMemory.new(50, facter)
|
14
|
-
memory.current_health.should == 44
|
15
|
-
end
|
16
|
-
|
17
|
-
describe "#memory_total" do
|
18
|
-
it "is a positive integer" do
|
19
|
-
metric = LitmusPaper::Metric::AvailableMemory.new(50)
|
20
|
-
metric.memory_total.should > 1_000
|
21
|
-
end
|
22
|
-
|
23
|
-
it "handles floating point values properly" do
|
24
|
-
facter = StubFacter.new("memorysize" => "1.80 GB")
|
25
|
-
memory = LitmusPaper::Metric::AvailableMemory.new(50, facter)
|
26
|
-
memory.memory_total.should == 1932735283
|
27
|
-
end
|
28
|
-
|
29
|
-
it "is cached" do
|
30
|
-
Facter.should_receive(:value).once.and_return("10 MB")
|
31
|
-
metric = LitmusPaper::Metric::AvailableMemory.new(50)
|
32
|
-
metric.memory_total
|
33
|
-
metric.memory_total
|
34
|
-
metric.memory_total
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe "#memory_free" do
|
39
|
-
it "is a positive integer" do
|
40
|
-
metric = LitmusPaper::Metric::AvailableMemory.new(50)
|
41
|
-
metric.memory_free.should > 100
|
42
|
-
end
|
43
|
-
|
44
|
-
it "handles floating point values properly" do
|
45
|
-
facter = StubFacter.new("memoryfree" => "1.80 GB")
|
46
|
-
memory = LitmusPaper::Metric::AvailableMemory.new(50, facter)
|
47
|
-
memory.memory_free.should == 1932735283
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
describe "#to_s" do
|
52
|
-
it "is the name of the check and the max weight" do
|
53
|
-
metric = LitmusPaper::Metric::AvailableMemory.new(50)
|
54
|
-
metric.to_s.should == "Metric::AvailableMemory(50)"
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
data/spec/support/stub_facter.rb
DELETED
data/xinetd.conf
DELETED