rnagios 0.0.1
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.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +34 -0
- data/lib/rnagios/active_status.rb +75 -0
- data/lib/rnagios/nagios_error.rb +7 -0
- data/lib/rnagios/nsca_host_status.rb +78 -0
- data/lib/rnagios/nsca_service_status.rb +62 -0
- data/lib/rnagios/plugin.rb +369 -0
- data/lib/rnagios/status.rb +28 -0
- data/lib/rnagios.rb +30 -0
- metadata +53 -0
data/README.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
rnagios
|
2
|
+
=======
|
3
|
+
|
4
|
+
Ruby gem to make creating Nagios plugins easier
|
5
|
+
|
6
|
+
There are two types of checks you can perform that Nagios will process:
|
7
|
+
active and NSCA checks. Active checks are run on the Nagios
|
8
|
+
monitoring host and actively check services. NSCA checks are run
|
9
|
+
by remote hosts and their output is sent back to the ` host
|
10
|
+
for processing by the NSCA daemon. Active checks are "actively" run
|
11
|
+
by Nagios; NSCA checks are "passively" run by other servers.
|
12
|
+
|
13
|
+
To create an active check, create logic that measures a service
|
14
|
+
(such as a database, a web service, or a custom application) and
|
15
|
+
returns a fully-populated ActiveStatus object. By the same token,
|
16
|
+
to create an NSCA check, create logic that measures a service and
|
17
|
+
returns a fully-populated NscaHostStatus or NscaServiceStatus object.
|
18
|
+
(There are many gems available that can help you connect to services
|
19
|
+
and parse their output; this class does not attempt to be everything
|
20
|
+
to everyone.)
|
21
|
+
|
22
|
+
RNagios handles the formatting, and provides the appropriate
|
23
|
+
exit code so Nagios will process it correctly. When running on
|
24
|
+
UNIX/Linux, Nagios will check the exit codes along with the string
|
25
|
+
in the status message to determine how to handle it. Under Windows,
|
26
|
+
Nagios only cares about the strings in the status message.
|
27
|
+
|
28
|
+
RNagios allows you to use an optional configuration file in case your
|
29
|
+
plugin requires access to multiple configuration parameters. If
|
30
|
+
you supply a configuration file, it should be a YAML file, and it will
|
31
|
+
be parsed in the check method before the measure method is called.
|
32
|
+
measure() can then use the @config attribute to access configuration
|
33
|
+
parameters. The configuration file is expected to be in the same
|
34
|
+
directory as the plugin.
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# Represents the status of an active check. Valid status strings for
|
2
|
+
# Nagios are OK, WARNING, CRITICAL, and UNKNOWN. UNIX/Linux exit codes
|
3
|
+
# are set automatically when you set the status attribute.
|
4
|
+
class ActiveStatus < Status
|
5
|
+
|
6
|
+
# Indicates everything is good with the service
|
7
|
+
OK = 'OK'
|
8
|
+
# Indicates a status of concern; not necessarily catastrophic
|
9
|
+
WARNING = 'WARNING'
|
10
|
+
# Indicates a serious failure or error
|
11
|
+
CRITICAL = 'CRITICAL'
|
12
|
+
# Indicates that the status is unknown or can not be determined
|
13
|
+
UNKNOWN = 'UNKNOWN'
|
14
|
+
|
15
|
+
# UNIX/Linux exit code for Nagios OK
|
16
|
+
OK_EXIT_CODE = 0
|
17
|
+
# UNIX/Linux exit code for Nagios WARNING
|
18
|
+
WARNING_EXIT_CODE = 1
|
19
|
+
# UNIX/Linux exit code for Nagios CRITICAL
|
20
|
+
CRITICAL_EXIT_CODE = 2
|
21
|
+
# UNIX/Linux exit code for Nagios UNKNOWN
|
22
|
+
UNKNOWN_EXIT_CODE = 3
|
23
|
+
|
24
|
+
# If status is not given, it will default to UNKNOWN. If message
|
25
|
+
# is not given, it will default to <EMPTY>. UNIX/Linux exit codes
|
26
|
+
# are assigned automatically.
|
27
|
+
def initialize(status=nil, message=nil)
|
28
|
+
if status.nil? || (status != OK && status != WARNING && status != CRITICAL && status != UNKNOWN)
|
29
|
+
@status = UNKNOWN
|
30
|
+
else
|
31
|
+
@status = status if !status.nil?
|
32
|
+
end
|
33
|
+
|
34
|
+
if message.nil?
|
35
|
+
@message = '<EMPTY>'
|
36
|
+
else
|
37
|
+
@message = message
|
38
|
+
end
|
39
|
+
|
40
|
+
case @status
|
41
|
+
when OK
|
42
|
+
@exit_code = OK_EXIT_CODE
|
43
|
+
when WARNING
|
44
|
+
@exit_code = WARNING_EXIT_CODE
|
45
|
+
when CRITICAL
|
46
|
+
@exit_code = CRITICAL_EXIT_CODE
|
47
|
+
when UNKNOWN
|
48
|
+
@exit_code = UNKNOWN_EXIT_CODE
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def status=(value)
|
53
|
+
if value.nil? || (value != OK && value != WARNING && value != CRITICAL && value != UNKNOWN)
|
54
|
+
@status = UNKNOWN
|
55
|
+
else
|
56
|
+
@status = value
|
57
|
+
end
|
58
|
+
|
59
|
+
case @status
|
60
|
+
when OK
|
61
|
+
@exit_code = OK_EXIT_CODE
|
62
|
+
when WARNING
|
63
|
+
@exit_code = WARNING_EXIT_CODE
|
64
|
+
when CRITICAL
|
65
|
+
@exit_code = CRITICAL_EXIT_CODE
|
66
|
+
when UNKNOWN
|
67
|
+
@exit_code = UNKNOWN_EXIT_CODE
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def empty?
|
72
|
+
@status == UNKNOWN && (@message.nil? || @message.empty? || @message == '<EMPTY>')
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# NscaHostStatus has a different set of statuses from ActiveStatus.
|
2
|
+
# Instead of OK, WARNING, UNKNOWN, and CRITICAL, NscaHostStatus
|
3
|
+
# uses UP, DOWN, and UNREACHABLE. These statuses are all meant to apply
|
4
|
+
# only to hosts and not services. Also, passive checks do not need to
|
5
|
+
# concern themselves with exit codes, as their output will be sent via
|
6
|
+
# the send_nsca program to a Nagios server for processing. It just so
|
7
|
+
# happens that the 'host status' is exactly the same as the UNIX/Linux
|
8
|
+
# exit codes, but we use the @passive_code attribute anyway for clarity.
|
9
|
+
class NscaHostStatus < Status
|
10
|
+
|
11
|
+
# Stand-in for host status
|
12
|
+
attr_reader :passive_code
|
13
|
+
|
14
|
+
# Host is up and available
|
15
|
+
UP = 'UP'
|
16
|
+
# Host is down and unavailable
|
17
|
+
DOWN = 'DOWN'
|
18
|
+
# Host is unreachable (e.g. behind a router or host that is down)
|
19
|
+
UNREACHABLE = 'UNREACHABLE'
|
20
|
+
|
21
|
+
# Host status code for UP
|
22
|
+
UP_CODE = 0
|
23
|
+
# Host status code for DOWN
|
24
|
+
DOWN_CODE = 1
|
25
|
+
# Host status code for UNREACHABLE
|
26
|
+
UNREACHABLE_CODE = 2
|
27
|
+
|
28
|
+
# If status is not given, it will default to UNREACHABLE. If message
|
29
|
+
# is not given, it will default to <EMPTY>. UNIX/Linux exit codes
|
30
|
+
# are assigned automatically.
|
31
|
+
def initialize(status=nil, message=nil)
|
32
|
+
if status.nil? || (status != UP && status != DOWN && status != UNREACHABLE)
|
33
|
+
@status = UNREACHABLE
|
34
|
+
else
|
35
|
+
@status = status
|
36
|
+
end
|
37
|
+
|
38
|
+
if message.nil?
|
39
|
+
@message = '<EMPTY>'
|
40
|
+
else
|
41
|
+
@message = message
|
42
|
+
end
|
43
|
+
|
44
|
+
case @status
|
45
|
+
when UP
|
46
|
+
@passive_code = UP_CODE
|
47
|
+
when DOWN
|
48
|
+
@passive_code = DOWN_CODE
|
49
|
+
when UNREACHABLE
|
50
|
+
@passive_code = UNREACHABLE_CODE
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# If status is not given, it will default to UNREACHABLE. Changing
|
55
|
+
# the status will change the passive_code accordingly
|
56
|
+
def status=(value)
|
57
|
+
if value.nil? || (value != UP && value != DOWN && value != UNREACHABLE)
|
58
|
+
@status = UNREACHABLE
|
59
|
+
else
|
60
|
+
@status = value
|
61
|
+
end
|
62
|
+
|
63
|
+
case @status
|
64
|
+
when UP
|
65
|
+
@passive_code = UP_CODE
|
66
|
+
when DOWN
|
67
|
+
@passive_code = DOWN_CODE
|
68
|
+
when UNREACHABLE
|
69
|
+
@passive_code = UNREACHABLE_CODE
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def empty?
|
74
|
+
@status == UNREACHABLE && (@message.nil? || @message.empty? || @message == '<EMPTY>')
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# NscaServiceStatus is essentially an ActiveStatus object with
|
2
|
+
# only an extra :passive_code attribute.
|
3
|
+
class NscaServiceStatus < ActiveStatus
|
4
|
+
|
5
|
+
# Stand-in for return code
|
6
|
+
attr_reader :passive_code
|
7
|
+
|
8
|
+
# We call super.initialize to setup the ActiveStatus object then
|
9
|
+
# we set @passive_code to @exit_code. The values are exactly the
|
10
|
+
# same
|
11
|
+
def initialize(status=nil, message=nil)
|
12
|
+
if status.nil? || (status != OK && status != WARNING && status != CRITICAL && status != UNKNOWN)
|
13
|
+
@status = UNKNOWN
|
14
|
+
else
|
15
|
+
@status = status
|
16
|
+
end
|
17
|
+
|
18
|
+
if message.nil?
|
19
|
+
@message = '<EMPTY>'
|
20
|
+
else
|
21
|
+
@message = message
|
22
|
+
end
|
23
|
+
|
24
|
+
case @status
|
25
|
+
when OK
|
26
|
+
@passive_code = OK_EXIT_CODE
|
27
|
+
when WARNING
|
28
|
+
@passive_code = WARNING_EXIT_CODE
|
29
|
+
when CRITICAL
|
30
|
+
@passive_code = CRITICAL_EXIT_CODE
|
31
|
+
when UNKNOWN
|
32
|
+
@passive_code = UNKNOWN_EXIT_CODE
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# We call super.status to setup the ActiveStatus object then
|
37
|
+
# we set @passive_code to @exit_code. The values are exactly the
|
38
|
+
# same
|
39
|
+
def status=(value)
|
40
|
+
if value.nil? || (value != OK && value != WARNING && value != CRITICAL && value != UNKNOWN)
|
41
|
+
@status = UNKNOWN
|
42
|
+
else
|
43
|
+
@status = value
|
44
|
+
end
|
45
|
+
|
46
|
+
case @status
|
47
|
+
when OK
|
48
|
+
@passive_code = OK_EXIT_CODE
|
49
|
+
when WARNING
|
50
|
+
@passive_code = WARNING_EXIT_CODE
|
51
|
+
when CRITICAL
|
52
|
+
@passive_code = CRITICAL_EXIT_CODE
|
53
|
+
when UNKNOWN
|
54
|
+
@passive_code = UNKNOWN_EXIT_CODE
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def empty?
|
59
|
+
@status == UNKNOWN && (@message.nil? || @message.empty? || @message == '<EMPTY>')
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,369 @@
|
|
1
|
+
# There are two types of checks you can perform that Nagios will process:
|
2
|
+
# active and NSCA checks. Active checks are run on the Nagios
|
3
|
+
# monitoring host and actively check services. NSCA checks are run
|
4
|
+
# by remote hosts and their output is sent back to the ` host
|
5
|
+
# for processing by the NSCA daemon. Active checks are "actively" run
|
6
|
+
# by Nagios; NSCA checks are "passively" run by other servers.
|
7
|
+
#
|
8
|
+
# To create an active check, create logic that measures a service
|
9
|
+
# (such as a database, a web service, or a custom application) and
|
10
|
+
# returns a fully-populated ActiveStatus object. By the same token,
|
11
|
+
# to create an NSCA check, create logic that measures a service and
|
12
|
+
# returns a fully-populated NscaHostStatus or NscaServiceStatus object.
|
13
|
+
# (There are many gems available that can help you connect to services
|
14
|
+
# and parse their output; this class does not attempt to be everything
|
15
|
+
# to everyone.)
|
16
|
+
#
|
17
|
+
# Plugin handles the formatting, and provides the appropriate
|
18
|
+
# exit code so Nagios will process it correctly. When running on
|
19
|
+
# UNIX/Linux, Nagios will check the exit codes along with the string
|
20
|
+
# in the status message to determine how to handle it. Under Windows,
|
21
|
+
# Nagios only cares about the strings in the status message.
|
22
|
+
#
|
23
|
+
# Plugin allows you to use an optional configuration file in case your
|
24
|
+
# plugin requires access to multiple configuration parameters. If
|
25
|
+
# you supply a configuration file, it should be a YAML file, and it will
|
26
|
+
# be parsed in the check method before the measure method is called.
|
27
|
+
# measure() can then use the @config attribute to access configuration
|
28
|
+
# parameters. The configuration file is expected to be in the same
|
29
|
+
# directory as the plugin.
|
30
|
+
class Plugin
|
31
|
+
|
32
|
+
# Internal configuration access attribute
|
33
|
+
attr_reader :config
|
34
|
+
# Name of the plugin (e.g. check_service)
|
35
|
+
attr_reader :name
|
36
|
+
|
37
|
+
# Warning level
|
38
|
+
attr_accessor :w
|
39
|
+
# Critical level
|
40
|
+
attr_accessor :c
|
41
|
+
# Path to the configuration file
|
42
|
+
attr_accessor :config_file
|
43
|
+
# Name of host to check
|
44
|
+
attr_accessor :host
|
45
|
+
# Port of host to check (defaults to 80)
|
46
|
+
attr_accessor :port
|
47
|
+
# Set to true to use SSL
|
48
|
+
attr_accessor :use_ssl
|
49
|
+
# Whether we verify the host if using SSL to connect
|
50
|
+
attr_accessor :verify_ssl
|
51
|
+
|
52
|
+
# Plugin expects a hash with the following symbols:
|
53
|
+
# :host # The hostname or IP address to check (required)
|
54
|
+
# :port # The port on :host to check (default: 80)
|
55
|
+
# :name # The name of the service, usually starting with 'check_' (default: <UNDEFINED>)
|
56
|
+
# :config_file # Path to YAML configuration file (optional)
|
57
|
+
# :w # Warning level (optional, usually numeric)
|
58
|
+
# :c # Critical level (optional, usually numeric)
|
59
|
+
# :use_ssl # True to use SSL, false otherwise (default: false)
|
60
|
+
# :verify_ssl # If using SSL, set to true to verify the server (default: false)
|
61
|
+
# :host must be provided, otherwise a NagiosError will be thrown.
|
62
|
+
def initialize(params={})
|
63
|
+
if !blank?(params)
|
64
|
+
if params[:host].nil?
|
65
|
+
raise NagiosError.new('Hostname must be provided')
|
66
|
+
else
|
67
|
+
@host = params[:host]
|
68
|
+
end
|
69
|
+
if params[:port].nil?
|
70
|
+
@port = 80
|
71
|
+
elsif params[:port].is_a?(String)
|
72
|
+
begin
|
73
|
+
@port = params[:port].to_i
|
74
|
+
rescue
|
75
|
+
raise NagiosError.new('Port number must be numeric')
|
76
|
+
end
|
77
|
+
else
|
78
|
+
@port = params[:port]
|
79
|
+
end
|
80
|
+
@name = default(params[:name])
|
81
|
+
@config_file = params[:config_file] if !params[:config_file].nil?
|
82
|
+
@w = params[:w] if !params[:w].nil?
|
83
|
+
@c = params[:c] if !params[:c].nil?
|
84
|
+
if !params[:use_ssl].nil?
|
85
|
+
@use_ssl = params[:use_ssl]
|
86
|
+
else
|
87
|
+
@use_ssl = false
|
88
|
+
end
|
89
|
+
if !params[:verify_ssl].nil?
|
90
|
+
@verify_ssl = params[:verify_ssl]
|
91
|
+
else
|
92
|
+
@verify_ssl = false
|
93
|
+
end
|
94
|
+
else
|
95
|
+
raise NagiosError.new('At least hostname must be provided')
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# The name of the Plugin. This should conform to the Nagios
|
100
|
+
# convention of "check_<service>" as the name of the script to
|
101
|
+
# run. The name can have extensions such as ".py" or ".rb";
|
102
|
+
# they will be stripped off. This name will show up in capital
|
103
|
+
# letters as the service name in Nagios status information columns
|
104
|
+
def name=(value)
|
105
|
+
@name = default(value)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Returns a Status with the message to print to STDOUT
|
109
|
+
# and an exit code to return if running under UNIX/Linux. If
|
110
|
+
# the operating system is not UNIX/Linux, the exit_code will be
|
111
|
+
# zero (0). If the measure method throws an exception or the
|
112
|
+
# status object is not a properly-populated Status object,
|
113
|
+
# then this method will throw a NagiosError.
|
114
|
+
#
|
115
|
+
# This method will run the user-overloaded measure() method. If
|
116
|
+
# measure() should return an uncaught exception, the exception
|
117
|
+
# message will be returned to Nagios as an UNKNOWN status, so
|
118
|
+
# make sure to handle all known error conditions within measure()
|
119
|
+
# to make the output of your script meaningful.
|
120
|
+
#
|
121
|
+
# Scripts should call this method at the very end. The general
|
122
|
+
# flow of a script running on UNIX/Linux should be as follows:
|
123
|
+
#
|
124
|
+
# class MyCheck < Nagios::Plugin
|
125
|
+
# def measure
|
126
|
+
# stat = Nagios::ActiveStatus.new
|
127
|
+
# stat.status = <...service check code goes here, returns Nagios::Status::<constant> status...>
|
128
|
+
# stat.message = <...service message state construction goes here...>
|
129
|
+
# # UNIX/Linux exit codes are taken core of for you
|
130
|
+
# end
|
131
|
+
# end
|
132
|
+
#
|
133
|
+
# plugin = MyCheck.new( { :name => 'check_service', :host = '<my_host>', :w => 15, :c => 5 })
|
134
|
+
# status = plugin.check
|
135
|
+
# $stdout.puts status.message # status.message needs to be output to STDOUT
|
136
|
+
# exit status.exit_code # For UNIX/Linux
|
137
|
+
#
|
138
|
+
# It is up to the developer to handle command-line arguments.
|
139
|
+
# (See the gem trollop for a good example of command-line parameter
|
140
|
+
# hadling.) Nagios plugins usually accept "w" as a warning level and "c"
|
141
|
+
# as a critical level, but it is up to the plugin developer if
|
142
|
+
# these values are used in the measure method.
|
143
|
+
def check
|
144
|
+
start_time = Time.now
|
145
|
+
end_time = -1
|
146
|
+
status = nil
|
147
|
+
|
148
|
+
# If there is a config file, load it
|
149
|
+
if !blank? @config_file
|
150
|
+
@config = YAML.load_file(@config_file)
|
151
|
+
end
|
152
|
+
|
153
|
+
# measure() is where the magic happens. measure() should
|
154
|
+
# return a Status object. Any exceptions thrown
|
155
|
+
# in measure() drop right out, so make sure you handle all
|
156
|
+
# error conditions appropriately before using your plugin
|
157
|
+
# with Nagios
|
158
|
+
status = measure
|
159
|
+
|
160
|
+
# Mark the end time for Nagios performance stats
|
161
|
+
end_time = Time.now
|
162
|
+
|
163
|
+
# Since we can't effectively check for exceptions, we make
|
164
|
+
# sure we get a good Status
|
165
|
+
if !valid?(status)
|
166
|
+
raise NagiosError.new('Returned status must be an instance or subclass of Status')
|
167
|
+
elsif !valid_status?(status)
|
168
|
+
raise NagiosError.new('Status must have be a valid status constant')
|
169
|
+
elsif status.is_a?(NscaHostStatus) && !valid_passive_code?(status)
|
170
|
+
raise NagiosError.new('Status passive code is invalid')
|
171
|
+
elsif status.is_a? ActiveStatus
|
172
|
+
if status.is_a? NscaServiceStatus
|
173
|
+
if !valid_passive_code? status
|
174
|
+
raise NagiosError.new('Status passive code is invalid')
|
175
|
+
end
|
176
|
+
elsif !valid_exit_code? status
|
177
|
+
raise NagiosError.new('Status exit code is invalid')
|
178
|
+
end
|
179
|
+
elsif blank?(status.message)
|
180
|
+
raise NagiosError.new('Status message must not be nil or empty')
|
181
|
+
end
|
182
|
+
|
183
|
+
# Status checks out as valid -- we now format the output based on
|
184
|
+
# the type of Status received
|
185
|
+
if status.is_a? NscaHostStatus
|
186
|
+
status.message = format_passive_host_check(status)
|
187
|
+
elsif status.is_a? NscaServiceStatus
|
188
|
+
status.message = format_passive_service_check(status)
|
189
|
+
else
|
190
|
+
status.message = format_active_service_check(status, start_time, end_time)
|
191
|
+
end
|
192
|
+
|
193
|
+
status
|
194
|
+
end
|
195
|
+
|
196
|
+
# This method should be overloaded by classes that subclass
|
197
|
+
# Plugin. For active checks, measure() should return an
|
198
|
+
# ActiveStatus object. For passive checks, measure()
|
199
|
+
# should return a NscaHostStatus or NscaServiceStatus
|
200
|
+
# object.
|
201
|
+
#
|
202
|
+
# The developer of must determine how to best check the
|
203
|
+
# service in question. Below is an example of how measure()
|
204
|
+
# should be structured.
|
205
|
+
#
|
206
|
+
# status = ''
|
207
|
+
# message = ''
|
208
|
+
# begin
|
209
|
+
# random_measure = 1 + rand(4) # Bad real-world event simulator
|
210
|
+
# if random_measure == 1
|
211
|
+
# status = ActiveStatus::OK
|
212
|
+
# message = 'Everything looks good'
|
213
|
+
# elsif random_measure == 2
|
214
|
+
# status = ActiveStatus::WARNING
|
215
|
+
# message = 'Keep an eye on this service'
|
216
|
+
# elsif random_measure == 3
|
217
|
+
# status = ActiveStatus::CRITICAL
|
218
|
+
# message = 'There''s a problem'
|
219
|
+
# else
|
220
|
+
# status = ActiveStatus::UNKNOWN
|
221
|
+
# message = 'Can''t figure out what''s going on'
|
222
|
+
# end
|
223
|
+
# rescue StandardError => e
|
224
|
+
# # You should decide what kind of status to return in case
|
225
|
+
# # of an error. You should not let errors go unhandled in
|
226
|
+
# # a Nagios plugin, otherwise Nagios will handle it as a
|
227
|
+
# # failure and you may be spammed with unnecessary notifications
|
228
|
+
# # for something that should only merit a warning
|
229
|
+
# status = ActiveStatus::WARNING
|
230
|
+
# message = 'Possibly recoverable error occurred'
|
231
|
+
# rescue Exception => e
|
232
|
+
# # It is wise to account for exceptions you don't anticipate
|
233
|
+
# # and create a status that is more meaningful for your service.
|
234
|
+
# # For your situation, unanticipated errors may be critical, or
|
235
|
+
# # they may be worth only a warning; you decide
|
236
|
+
# status = ActiveStatus::CRITICAL
|
237
|
+
# message = 'Something we didn''t anticipate occurred'
|
238
|
+
# ensure
|
239
|
+
# # Make sure the returned status has something in it if all else fails
|
240
|
+
# status = ActiveStatus::UNKNOWN
|
241
|
+
# message = 'Don''t know what happened'
|
242
|
+
# end
|
243
|
+
# ActiveStatus.new(status, message)
|
244
|
+
def measure
|
245
|
+
# Overload this method to populate the status object
|
246
|
+
raise NagiosError.new('Call to measure should not invoke base class measure method; measure method should be overridden')
|
247
|
+
end
|
248
|
+
|
249
|
+
private
|
250
|
+
# This method uses the value of @name to create a default.
|
251
|
+
# As long as the name sticks to the Nagios convention of
|
252
|
+
# "check_<service>", this method can make a good guess as
|
253
|
+
# to the default it should create
|
254
|
+
def default(value=nil)
|
255
|
+
if !blank? value
|
256
|
+
if value.downcase.include? 'check_'
|
257
|
+
value.downcase.gsub('check_', '').upcase
|
258
|
+
else
|
259
|
+
value.upcase
|
260
|
+
end
|
261
|
+
elsif blank?(value) && !blank?(@name)
|
262
|
+
@name.downcase.gsub('check_', '').upcase
|
263
|
+
else
|
264
|
+
'<UNDEFINED>'
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def format_active_service_check(status, start_time, end_time)
|
269
|
+
@name + ' ' + status.to_s + ' | time=' + (end_time - start_time).to_s + ';;;' + @w.to_s + ';' + @c.to_s
|
270
|
+
end
|
271
|
+
|
272
|
+
# NSCA check results are different from active check results
|
273
|
+
# [<timestamp>] PROCESS_SERVICE_CHECK_RESULT;<host_name>;<svc_description>;<return_code>;<plugin_output>
|
274
|
+
def format_passive_service_check(status)
|
275
|
+
'[' + Time.now.to_i.to_s + '] PROCESS_SERVICE_CHECK_RESULT;' + @host + ';' + @name + ';' + status.passive_code.to_s + ';' + status.message
|
276
|
+
end
|
277
|
+
|
278
|
+
# NSCA check results are different from active check results
|
279
|
+
# [<timestamp>] PROCESS_HOST_CHECK_RESULT;<host_name>;<host_status>;<plugin_output>
|
280
|
+
def format_passive_host_check(status)
|
281
|
+
'[' + Time.now.to_i.to_s + '] PROCESS_HOST_CHECK_RESULT;' + @host + ';' + status.passive_code.to_s + ';' + status.message
|
282
|
+
end
|
283
|
+
|
284
|
+
def valid?(status)
|
285
|
+
blank?(status) || !status.is_a?(Status) ? false : true
|
286
|
+
end
|
287
|
+
|
288
|
+
def valid_status?(status)
|
289
|
+
if blank?(status) || blank?(status.status) || !status.status.is_a?(String)
|
290
|
+
false
|
291
|
+
elsif status.is_a?(ActiveStatus) || status.is_a?(NscaServiceStatus)
|
292
|
+
case status.status
|
293
|
+
when ActiveStatus::OK
|
294
|
+
true
|
295
|
+
when ActiveStatus::WARNING
|
296
|
+
true
|
297
|
+
when ActiveStatus::UNKNOWN
|
298
|
+
true
|
299
|
+
when ActiveStatus::CRITICAL
|
300
|
+
true
|
301
|
+
else
|
302
|
+
false
|
303
|
+
end
|
304
|
+
elsif status.is_a? NscaHostStatus
|
305
|
+
case status.status
|
306
|
+
when NscaHostStatus::UP
|
307
|
+
true
|
308
|
+
when NscaHostStatus::DOWN
|
309
|
+
true
|
310
|
+
when NscaHostStatus::UNREACHABLE
|
311
|
+
true
|
312
|
+
else
|
313
|
+
false
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
def valid_exit_code?(status)
|
319
|
+
if blank?(status) || !status.exit_code.is_a?(Integer) || !status.is_a?(ActiveStatus)
|
320
|
+
false
|
321
|
+
else
|
322
|
+
case status.exit_code
|
323
|
+
when ActiveStatus::OK_EXIT_CODE
|
324
|
+
true
|
325
|
+
when ActiveStatus::WARNING_EXIT_CODE
|
326
|
+
true
|
327
|
+
when ActiveStatus::UNKNOWN_EXIT_CODE
|
328
|
+
true
|
329
|
+
when ActiveStatus::CRITICAL_EXIT_CODE
|
330
|
+
true
|
331
|
+
else
|
332
|
+
false
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
def valid_passive_code?(status)
|
338
|
+
if blank?(status) || !status.passive_code.is_a?(Integer)
|
339
|
+
false
|
340
|
+
elsif status.is_a?(NscaServiceStatus)
|
341
|
+
case status.passive_code
|
342
|
+
when ActiveStatus::OK_EXIT_CODE
|
343
|
+
true
|
344
|
+
when ActiveStatus::WARNING_EXIT_CODE
|
345
|
+
true
|
346
|
+
when ActiveStatus::UNKNOWN_EXIT_CODE
|
347
|
+
true
|
348
|
+
when ActiveStatus::CRITICAL_EXIT_CODE
|
349
|
+
true
|
350
|
+
else
|
351
|
+
false
|
352
|
+
end
|
353
|
+
elsif status.is_a?(NscaHostStatus)
|
354
|
+
case status.passive_code
|
355
|
+
when NscaHostStatus::UP_CODE
|
356
|
+
true
|
357
|
+
when NscaHostStatus::DOWN_CODE
|
358
|
+
true
|
359
|
+
when NscaHostStatus::UNREACHABLE_CODE
|
360
|
+
true
|
361
|
+
else
|
362
|
+
false
|
363
|
+
end
|
364
|
+
else
|
365
|
+
false
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Superclass for ActiveStatus, NscaHostStatus, and NscaServiceStatus
|
2
|
+
class Status
|
3
|
+
|
4
|
+
# A Nagios::Status constant
|
5
|
+
attr_accessor :status
|
6
|
+
# UNIX/Linux exit code
|
7
|
+
attr_reader :exit_code
|
8
|
+
# The status output from the measure() method
|
9
|
+
attr_accessor :message
|
10
|
+
|
11
|
+
def initialize(status=nil, message=nil)
|
12
|
+
@status = status if !status.nil? && !status.empty?
|
13
|
+
@message = message if !message.nil? && !message.empty?
|
14
|
+
@exit_code = 0
|
15
|
+
end
|
16
|
+
|
17
|
+
# Formats the given message for output to Nagios
|
18
|
+
def to_s
|
19
|
+
@status = '' if @status.nil?
|
20
|
+
@message = '' if @message.nil?
|
21
|
+
@status + ': ' + @message
|
22
|
+
end
|
23
|
+
|
24
|
+
def empty?
|
25
|
+
(@status.nil? && @message.nil?) || (@status.empty? && @message.empty?)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/lib/rnagios.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rnagios/status'
|
2
|
+
require 'rnagios/active_status'
|
3
|
+
require 'rnagios/nsca_host_status'
|
4
|
+
require 'rnagios/nsca_service_status'
|
5
|
+
require 'rnagios/nagios_error'
|
6
|
+
require 'rnagios/plugin'
|
7
|
+
|
8
|
+
def blank?(value)
|
9
|
+
value.nil? || value.empty?
|
10
|
+
end
|
11
|
+
|
12
|
+
# Check for Windows OS
|
13
|
+
def windows?
|
14
|
+
(/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
|
15
|
+
end
|
16
|
+
|
17
|
+
# Check for Mac OS
|
18
|
+
def mac?
|
19
|
+
(/darwin/ =~ RUBY_PLATFORM) != nil
|
20
|
+
end
|
21
|
+
|
22
|
+
# Check for UNIX or UNIX-like OS
|
23
|
+
def unix?
|
24
|
+
!OS.windows?
|
25
|
+
end
|
26
|
+
|
27
|
+
# Check for Linux
|
28
|
+
def linux?
|
29
|
+
OS.unix? and not OS.mac?
|
30
|
+
end
|