ruby-nagios 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.
- data/COPYING +14 -0
- data/README +5 -0
- data/Rakefile +2 -0
- data/bin/check_check +184 -0
- data/bin/nagsrv +148 -0
- data/lib/nagios/status.rb +335 -0
- data/pkg/ruby-nagios-0.0.1.gem +0 -0
- data/ruby-nagios.gemspec +15 -0
- metadata +88 -0
data/COPYING
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Copyright 2009 R.I.Pienaar
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
14
|
+
|
data/README
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
Have you ever had to disable alerts, retry a check or acknowledge outages on a large amount of services with Nagios and hated the web UI for it?
|
2
|
+
|
3
|
+
This is a CLI tool and Ruby library that parses your status log file and let you query it for information or create external commands to be piped into the nagios command file.
|
4
|
+
|
5
|
+
See http://code.google.com/p/ruby-nagios/ for more information
|
data/Rakefile
ADDED
data/bin/check_check
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Check check- aggregate results from other checks in your nagios instance.
|
4
|
+
# Reads the 'status_file' for current states.
|
5
|
+
#
|
6
|
+
# Useful for having lots of small checks roll up into an aggregate that
|
7
|
+
# only alerts you once during failures, not N times.
|
8
|
+
#
|
9
|
+
# Also useful for business-view monitoring
|
10
|
+
#
|
11
|
+
|
12
|
+
require "rubygems"
|
13
|
+
require "nagios/status"
|
14
|
+
require "optparse"
|
15
|
+
|
16
|
+
class Nagios::Status::Model
|
17
|
+
STATEMAP = {
|
18
|
+
"0" => "OK",
|
19
|
+
"1" => "WARNING",
|
20
|
+
"2" => "CRITICAL",
|
21
|
+
"3" => "UNKNOWN",
|
22
|
+
}
|
23
|
+
|
24
|
+
def initialize(path)
|
25
|
+
@path = path
|
26
|
+
@status = Nagios::Status.new
|
27
|
+
update
|
28
|
+
end # def initialize
|
29
|
+
|
30
|
+
def update
|
31
|
+
@status.parsestatus(@path)
|
32
|
+
end # def update
|
33
|
+
|
34
|
+
def services(service_pattern=nil, host_pattern=nil)
|
35
|
+
matches = []
|
36
|
+
self.hosts(host_pattern).each do |host, hostinfo|
|
37
|
+
#Skip hosts if the host is down - obviously the services will be too, and we should already have alerted on the host.__
|
38
|
+
next if hostinfo["hoststatus"]["current_state"].to_i != 0
|
39
|
+
# Skip hosts if there is no hostinfo (no services associated, etc).
|
40
|
+
next if hostinfo["servicestatus"].nil?
|
41
|
+
# Skip hosts if they are in scheduled downtime
|
42
|
+
next if hostinfo["hoststatus"]["scheduled_downtime_depth"].to_i > 0
|
43
|
+
hostinfo["servicestatus"].each do |name, status|
|
44
|
+
next if service_pattern and !service_pattern.match(name)
|
45
|
+
|
46
|
+
# Skip myself, if we are a check running from nagios.
|
47
|
+
next if name == ENV["NAGIOS_SERVICEDESC"]
|
48
|
+
|
49
|
+
# Skip silenced or checks in scheduled downtime.
|
50
|
+
next if status["notifications_enabled"].to_i == 0
|
51
|
+
next if status["scheduled_downtime_depth"].to_i > 0
|
52
|
+
|
53
|
+
# Only report checks that are in 'hard' state.
|
54
|
+
# If not in hard state, report 'last_hard_state' instead.
|
55
|
+
if status["state_type"] != "1" # not in hard state
|
56
|
+
status["current_state"] = status["last_hard_state"]
|
57
|
+
# TODO(sissel): record that this service is currently
|
58
|
+
# in a soft state transition.
|
59
|
+
end
|
60
|
+
|
61
|
+
# TODO(sissel): Maybe also skip checks that are 'acknowledged'
|
62
|
+
matches << status
|
63
|
+
end
|
64
|
+
end # hosts().each
|
65
|
+
return matches
|
66
|
+
end # def services
|
67
|
+
|
68
|
+
def hosts(pattern=nil)
|
69
|
+
if pattern
|
70
|
+
return @status.status["hosts"].reject { |name,hostinfo| !pattern.match(name) }
|
71
|
+
else
|
72
|
+
return @status.status["hosts"]
|
73
|
+
end # if pattern
|
74
|
+
end # def hosts
|
75
|
+
|
76
|
+
# TODO(sissel): add a proper 'status' model that
|
77
|
+
# has HostStatus, ServiceStatus, etc.
|
78
|
+
|
79
|
+
end # class Nagios::Status::Model
|
80
|
+
|
81
|
+
Settings = Struct.new(:nagios_cfg, :status_path, :service_pattern, :host_pattern, :down_min_percent)
|
82
|
+
def main(args)
|
83
|
+
progname = File.basename($0)
|
84
|
+
settings = Settings.new
|
85
|
+
settings.nagios_cfg = "/etc/nagios3/nagios.cfg" # debian/ubuntu default
|
86
|
+
|
87
|
+
opts = OptionParser.new do |opts|
|
88
|
+
opts.banner = "Usage: #{progname} [options]"
|
89
|
+
|
90
|
+
opts.on("-f NAGIOS_CFG", "--config NAGIOS_CFG",
|
91
|
+
"Path to your nagios.cfg (I will use the status_file setting") do |val|
|
92
|
+
settings.nagios_cfg = val
|
93
|
+
end
|
94
|
+
|
95
|
+
opts.on("-s REGEX", "--service REGEX",
|
96
|
+
"Aggregate only services matching the given pattern") do |val|
|
97
|
+
settings.service_pattern = val
|
98
|
+
end
|
99
|
+
|
100
|
+
opts.on("-h REGEX", "--host REGEX",
|
101
|
+
"Aggregate only services from hosts matching the given pattern") do |val|
|
102
|
+
settings.host_pattern = val
|
103
|
+
end
|
104
|
+
|
105
|
+
opts.on("-p NUM", "--percent NUM",
|
106
|
+
"Only alert if this percentage of the cluster is down") do |val|
|
107
|
+
settings.down_min_percent = Float(val)
|
108
|
+
end
|
109
|
+
end # OptionParser.new
|
110
|
+
|
111
|
+
opts.parse!(args)
|
112
|
+
|
113
|
+
# hacky parsing, for now
|
114
|
+
status_line = File.new(settings.nagios_cfg, "r").readlines.grep(/^\s*status_file\s*=/).first.chomp
|
115
|
+
settings.status_path = status_line.split(/\s*=\s*/)[1]
|
116
|
+
status = Nagios::Status::Model.new(settings.status_path)
|
117
|
+
|
118
|
+
results = Hash.new { |h,k| h[k] = 0 }
|
119
|
+
service_pattern = nil
|
120
|
+
if settings.service_pattern
|
121
|
+
service_pattern = Regexp.new(settings.service_pattern)
|
122
|
+
end
|
123
|
+
|
124
|
+
host_pattern = nil
|
125
|
+
if settings.host_pattern
|
126
|
+
host_pattern = Regexp.new(settings.host_pattern)
|
127
|
+
end
|
128
|
+
|
129
|
+
Nagios::Status::Model::STATEMAP.values.each do |state|
|
130
|
+
results[state] = []
|
131
|
+
end
|
132
|
+
|
133
|
+
# Collect check results by state
|
134
|
+
status.services(service_pattern, host_pattern).each do |service_status|
|
135
|
+
state = Nagios::Status::Model::STATEMAP[service_status["current_state"]]
|
136
|
+
if state == nil
|
137
|
+
state = "UNKNOWN(state=#{service_status["current_state"]})"
|
138
|
+
end
|
139
|
+
|
140
|
+
results[state] << service_status
|
141
|
+
end
|
142
|
+
|
143
|
+
# Output a summary line
|
144
|
+
["OK", "WARNING", "CRITICAL", "UNKNOWN"].each do | state|
|
145
|
+
print "#{state}=#{results[state].length} "
|
146
|
+
end
|
147
|
+
print "services=/#{settings.service_pattern}/ "
|
148
|
+
print "hosts=/#{settings.host_pattern}/ "
|
149
|
+
puts
|
150
|
+
|
151
|
+
# More data output
|
152
|
+
total_results = 0.0
|
153
|
+
["WARNING", "CRITICAL", "UNKNOWN"].each do |state|
|
154
|
+
if results[state] && results[state].size > 0
|
155
|
+
puts "Services in #{state}:"
|
156
|
+
results[state].sort { |a,b| a["host_name"] <=> b["host_name"] }.each do |service|
|
157
|
+
total_results += 1
|
158
|
+
puts " #{service["host_name"]} => #{service["service_description"]}"
|
159
|
+
end
|
160
|
+
end # if results[state]
|
161
|
+
end # for each non-OK state
|
162
|
+
|
163
|
+
exitcode = 0
|
164
|
+
|
165
|
+
if settings.down_min_percent
|
166
|
+
if results["WARNING"].length > 0 && (results["WARNING"].length / total_results) * 100 >= settings.down_min_percent
|
167
|
+
exitcode = 1
|
168
|
+
end
|
169
|
+
if results["CRITICAL"].length > 0 && (results["CRITICAL"].length / total_results) * 100 >= settings.down_min_percent
|
170
|
+
exitcode = 2
|
171
|
+
end
|
172
|
+
else
|
173
|
+
if results["WARNING"].length > 0
|
174
|
+
exitcode = 1
|
175
|
+
end
|
176
|
+
|
177
|
+
if results["CRITICAL"].length > 0
|
178
|
+
exitcode = 2
|
179
|
+
end
|
180
|
+
end
|
181
|
+
return exitcode
|
182
|
+
end
|
183
|
+
|
184
|
+
exit(main(ARGV))
|
data/bin/nagsrv
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# A tool to do mass operations on nagios services. It is intended to be run on
|
4
|
+
# the server that hosts nagios and it needs read access to the status.log file
|
5
|
+
# typically found in the var dir.
|
6
|
+
#
|
7
|
+
# Command options are broken up into several types:
|
8
|
+
#
|
9
|
+
# == General
|
10
|
+
# --statusfile
|
11
|
+
# Where to find the status file
|
12
|
+
#
|
13
|
+
# == Output Selectors
|
14
|
+
# --list-hosts
|
15
|
+
# List hostnames that match certain criteria
|
16
|
+
#
|
17
|
+
# --list-service
|
18
|
+
# List services that match certain criteria
|
19
|
+
#
|
20
|
+
# == Selectors
|
21
|
+
# --with-service
|
22
|
+
# Pass a specific service name or a regex in the form
|
23
|
+
# /pattern/ if you pass a regex you can only pass this
|
24
|
+
# option once, if you pass specific services you can
|
25
|
+
# use this option many times the services will be searches
|
26
|
+
# in an OR fasion
|
27
|
+
#
|
28
|
+
# --for-host
|
29
|
+
# Restrict the selection of services to a specific host or
|
30
|
+
# regex match of hosts, same regex rules as for --with-service
|
31
|
+
#
|
32
|
+
# --notify-enabled
|
33
|
+
# List only services with notifications enabled, in this mode
|
34
|
+
# the output will be in the form host:service
|
35
|
+
#
|
36
|
+
# == Actions
|
37
|
+
# --enable-notify / --disable-notify
|
38
|
+
# Enable or Disable notifications for selected services
|
39
|
+
#
|
40
|
+
# --enable-checks / --disable-checks
|
41
|
+
# Enable of Disable checks for selected services
|
42
|
+
#
|
43
|
+
# --force-check
|
44
|
+
# Force checks for selected services
|
45
|
+
#
|
46
|
+
# --acknowledge
|
47
|
+
# Ackknowledge services without sending notifies
|
48
|
+
#
|
49
|
+
# Released under the terms of the Apache version 2
|
50
|
+
# license
|
51
|
+
#
|
52
|
+
# Please open an issue at ruby-nagios.googlecode.com
|
53
|
+
# with any queries
|
54
|
+
|
55
|
+
require 'nagios/status'
|
56
|
+
|
57
|
+
require 'optparse'
|
58
|
+
|
59
|
+
statusfile = "status.log"
|
60
|
+
listhosts = false
|
61
|
+
withservice = []
|
62
|
+
listservices = false
|
63
|
+
forhost = []
|
64
|
+
notify = nil
|
65
|
+
action = nil
|
66
|
+
options = nil
|
67
|
+
|
68
|
+
OptionParser.new do |opts|
|
69
|
+
opts.separator "General Options"
|
70
|
+
opts.on("--statusfile FILE", "-s", "Path to the Nagios status.log") do |v|
|
71
|
+
statusfile = v
|
72
|
+
end
|
73
|
+
|
74
|
+
opts.separator ""
|
75
|
+
opts.separator "Output Selectors"
|
76
|
+
opts.on("--list-hosts", "List hostnames that match certain criteria") do
|
77
|
+
listhosts = true
|
78
|
+
end
|
79
|
+
|
80
|
+
opts.on("--list-services", "List services that match certain criteria") do
|
81
|
+
listhosts = true
|
82
|
+
end
|
83
|
+
|
84
|
+
opts.separator ""
|
85
|
+
opts.separator "Service and Host Selectors"
|
86
|
+
|
87
|
+
opts.on("--with-service SERVICE", "Match a service or regular expression") do |v|
|
88
|
+
withservice << v
|
89
|
+
end
|
90
|
+
|
91
|
+
opts.on("--for-host HOST", "Restrict selection of services to a specific host") do |v|
|
92
|
+
forhost << v
|
93
|
+
end
|
94
|
+
|
95
|
+
opts.on("--notify-enabled", "List only services with notification enabled") do
|
96
|
+
notify = 1
|
97
|
+
end
|
98
|
+
|
99
|
+
opts.on("--notify-disabled", "List only services with notification disabled") do
|
100
|
+
notify = 0
|
101
|
+
end
|
102
|
+
|
103
|
+
opts.separator ""
|
104
|
+
opts.separator "Actions for Matched Services/Hosts"
|
105
|
+
opts.on("--enable-notify", "Enable notifications for selected services") do
|
106
|
+
action = "[${tstamp}] ENABLE_SVC_NOTIFICATIONS;${host};${service}"
|
107
|
+
end
|
108
|
+
|
109
|
+
opts.on("--disable-notify", "Disable notifications for selected services") do
|
110
|
+
action = "[${tstamp}] DISABLE_SVC_NOTIFICATIONS;${host};${service}"
|
111
|
+
end
|
112
|
+
|
113
|
+
opts.on("--enable-checks", "Enable checks for selected services") do
|
114
|
+
action = "[${tstamp}] ENABLE_SVC_CHECK;${host};${service};${tstamp}"
|
115
|
+
end
|
116
|
+
|
117
|
+
opts.on("--disable-checks", "Disable checks for selected services") do
|
118
|
+
action = "[${tstamp}] DISABLE_SVC_CHECK;${host};${service};${tstamp}"
|
119
|
+
end
|
120
|
+
|
121
|
+
opts.on("--force-check", "Force checks for selected services") do
|
122
|
+
action = "[${tstamp}] SCHEDULE_FORCED_SVC_CHECK;${host};${service};${tstamp}"
|
123
|
+
end
|
124
|
+
|
125
|
+
opts.on("--ackknowledge", "Ackknowledge services without sending notifies") do
|
126
|
+
action = "[${tstamp}] ACKNOWLEDGE_SVC_PROBLEM;${host};${service};1;0;1;#{ENV['USER']};Acknowledged from CLI"
|
127
|
+
end
|
128
|
+
end.parse!
|
129
|
+
|
130
|
+
abort "Cannot find #{statusfile}" unless File.exist?(statusfile)
|
131
|
+
|
132
|
+
nagios = Nagios::Status.new
|
133
|
+
|
134
|
+
nagios.parsestatus(statusfile)
|
135
|
+
|
136
|
+
|
137
|
+
# We want hosts so abuse the action field to print just the hostname
|
138
|
+
# and select all hosts unless other action/forhost was desigred then
|
139
|
+
# this really is just a noop and it reverts to noral behaviour
|
140
|
+
if listhosts
|
141
|
+
action = "${host}" if action == nil
|
142
|
+
forhost = "/." if forhost.size == 0
|
143
|
+
end
|
144
|
+
|
145
|
+
options = {:forhost => forhost, :notifyenabled => notify, :action => action, :withservice => withservice}
|
146
|
+
services = nagios.find_services(options)
|
147
|
+
|
148
|
+
puts services.join("\n")
|
@@ -0,0 +1,335 @@
|
|
1
|
+
module Nagios
|
2
|
+
class Status
|
3
|
+
attr_reader :status
|
4
|
+
|
5
|
+
# Parses a nagios status file returning a data structure for all the data
|
6
|
+
def parsestatus(statusfile)
|
7
|
+
@status = {}
|
8
|
+
@status["hosts"] = {}
|
9
|
+
|
10
|
+
handler = ""
|
11
|
+
blocklines = []
|
12
|
+
|
13
|
+
File.readlines(statusfile).each do |line|
|
14
|
+
# start of new sections
|
15
|
+
if line =~ /(\w+) \{/
|
16
|
+
blocklines = []
|
17
|
+
handler = $1
|
18
|
+
end
|
19
|
+
|
20
|
+
# gather all the lines for the block into an array
|
21
|
+
# we'll pass them to a handler for this kind of block
|
22
|
+
if line =~ /\s+(\w+)=(.+)/ && handler != ""
|
23
|
+
blocklines << line
|
24
|
+
end
|
25
|
+
|
26
|
+
# end of a section
|
27
|
+
if line =~ /\}/ && handler != "" && self.respond_to?("handle_#{handler}", include_private = true)
|
28
|
+
eval("handle_#{handler}(blocklines)")
|
29
|
+
handler = ""
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns a list of all hosts matching the options in options
|
35
|
+
def find_hosts(options = {})
|
36
|
+
forhost = options.fetch(:forhost, [])
|
37
|
+
notifications = options.fetch(:notifyenabled, nil)
|
38
|
+
action = options.fetch(:action, nil)
|
39
|
+
withservice = options.fetch(:withservice, [])
|
40
|
+
|
41
|
+
hosts = []
|
42
|
+
searchquery = []
|
43
|
+
|
44
|
+
# Build up a search query for find_with_properties each
|
45
|
+
# array member is a hash of property and a match
|
46
|
+
forhost.each do |host|
|
47
|
+
searchquery << search_term("host_name", host)
|
48
|
+
end
|
49
|
+
|
50
|
+
withservice.each do |s|
|
51
|
+
searchquery << search_term("service_description", s)
|
52
|
+
end
|
53
|
+
|
54
|
+
searchquery << {"notifications_enabled" => notifications.to_s} if notifications
|
55
|
+
|
56
|
+
hsts = find_with_properties(searchquery)
|
57
|
+
|
58
|
+
hsts.each do |host|
|
59
|
+
host_name = host["host_name"]
|
60
|
+
|
61
|
+
hosts << parse_command_template(action, host_name, "", host_name)
|
62
|
+
end
|
63
|
+
|
64
|
+
hosts.uniq.sort
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns a list of all services matching the options in options
|
68
|
+
def find_services(options = {})
|
69
|
+
forhost = options.fetch(:forhost, [])
|
70
|
+
notifications = options.fetch(:notifyenabled, nil)
|
71
|
+
action = options.fetch(:action, nil)
|
72
|
+
withservice = options.fetch(:withservice, [])
|
73
|
+
|
74
|
+
services = []
|
75
|
+
searchquery = []
|
76
|
+
|
77
|
+
# Build up a search query for find_with_properties each
|
78
|
+
# array member is a hash of property and a match
|
79
|
+
forhost.each do |host|
|
80
|
+
searchquery << search_term("host_name", host)
|
81
|
+
end
|
82
|
+
|
83
|
+
withservice.each do |s|
|
84
|
+
searchquery << search_term("service_description", s)
|
85
|
+
end
|
86
|
+
|
87
|
+
searchquery << {"notifications_enabled" => notifications.to_s} if notifications
|
88
|
+
|
89
|
+
svcs = find_with_properties(searchquery)
|
90
|
+
|
91
|
+
svcs.each do |service|
|
92
|
+
service_description = service["service_description"]
|
93
|
+
host_name = service["host_name"]
|
94
|
+
|
95
|
+
# when printing services with notifications en/dis it makes
|
96
|
+
# most sense to print them in host:service format, abuse the
|
97
|
+
# action option to get this result
|
98
|
+
action = "${host}:${service}" if (notifications != nil && action == nil)
|
99
|
+
|
100
|
+
services << parse_command_template(action, host_name, service_description, service_description)
|
101
|
+
end
|
102
|
+
|
103
|
+
services.uniq.sort
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
# Add search terms, does all the mangling of regex vs string and so on
|
109
|
+
def search_term(haystack, needle)
|
110
|
+
needle = Regexp.new(needle.gsub("\/", "")) if needle.match("^/")
|
111
|
+
{haystack => needle}
|
112
|
+
end
|
113
|
+
|
114
|
+
# Return service blocks for each service that matches any options like:
|
115
|
+
#
|
116
|
+
# "host_name" => "foo.com"
|
117
|
+
#
|
118
|
+
# The 2nd parameter can be a regex too.
|
119
|
+
def find_with_properties(search)
|
120
|
+
services = []
|
121
|
+
query = []
|
122
|
+
|
123
|
+
query << search if search.class == Hash
|
124
|
+
query = search if search.class == Array
|
125
|
+
|
126
|
+
@status["hosts"].each do |host,v|
|
127
|
+
find_host_services(host) do |service|
|
128
|
+
matchcount = 0
|
129
|
+
|
130
|
+
query.each do |q|
|
131
|
+
q.each do |option, match|
|
132
|
+
if match.class == Regexp
|
133
|
+
matchcount += 1 if service[option].match(match)
|
134
|
+
else
|
135
|
+
matchcount += 1 if service[option] == match.to_s
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
if matchcount == query.size
|
141
|
+
services << service
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
services
|
147
|
+
end
|
148
|
+
|
149
|
+
# yields the hash for each service on a host
|
150
|
+
def find_host_services(host)
|
151
|
+
if @status["hosts"][host].has_key?("servicestatus")
|
152
|
+
@status["hosts"][host]["servicestatus"].each do |s, v|
|
153
|
+
yield(@status["hosts"][host]["servicestatus"][s])
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Parses a template given with a nagios command string and populates vars
|
159
|
+
# else return the string given in default
|
160
|
+
def parse_command_template(template, host, service, default)
|
161
|
+
if template.nil?
|
162
|
+
default
|
163
|
+
else
|
164
|
+
template.gsub(/\$\{host\}/, host).gsub(/\$\{service\}/, service).gsub(/\$\{tstamp\}/, Time.now.to_i.to_s)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Figures out the service name from a block in a nagios status file
|
169
|
+
def get_service_name(lines)
|
170
|
+
if s = lines.grep(/\s+service_description=(\w+)/).first
|
171
|
+
if s =~ /service_description=(.+)$/
|
172
|
+
service = $1
|
173
|
+
else
|
174
|
+
raise("Cant't parse service in block: #{s}")
|
175
|
+
end
|
176
|
+
else
|
177
|
+
raise("Cant't find a hostname in block")
|
178
|
+
end
|
179
|
+
|
180
|
+
service
|
181
|
+
end
|
182
|
+
|
183
|
+
# Figures out the host name from a block in a nagios status file
|
184
|
+
def get_host_name(lines)
|
185
|
+
if h = lines.grep(/\s+host_name=(\w+)/).first
|
186
|
+
if h =~ /host_name=(.+)$/
|
187
|
+
host = $1
|
188
|
+
else
|
189
|
+
raise("Cant't parse hostname in block: #{h}")
|
190
|
+
end
|
191
|
+
else
|
192
|
+
raise("Cant't find a hostname in block")
|
193
|
+
end
|
194
|
+
|
195
|
+
host
|
196
|
+
end
|
197
|
+
|
198
|
+
# Parses an info block
|
199
|
+
def handle_info(lines)
|
200
|
+
@status["info"] = {} unless @status["info"]
|
201
|
+
|
202
|
+
lines.each do |l|
|
203
|
+
if l =~ /\s+(\w+)=(\w+)/
|
204
|
+
@status["info"][$1] = $2
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# Parses a servicestatus block
|
210
|
+
def handle_servicestatus(lines)
|
211
|
+
host = get_host_name(lines)
|
212
|
+
service = get_service_name(lines)
|
213
|
+
|
214
|
+
@status["hosts"][host] = {} unless @status["hosts"][host]
|
215
|
+
@status["hosts"][host]["servicestatus"] = {} unless @status["hosts"][host]["servicestatus"]
|
216
|
+
@status["hosts"][host]["servicestatus"][service] = {} unless @status["hosts"][host]["servicestatus"][service]
|
217
|
+
|
218
|
+
lines.each do |l|
|
219
|
+
if l =~ /\s+(\w+)=(.+)$/
|
220
|
+
if $1 == "host_name"
|
221
|
+
@status["hosts"][host]["servicestatus"][service][$1] = host
|
222
|
+
else
|
223
|
+
@status["hosts"][host]["servicestatus"][service][$1] = $2
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
# Parses a servicestatus block
|
230
|
+
def handle_contactstatus(lines)
|
231
|
+
@status['contacts'] ||= {}
|
232
|
+
contact = get_contact_name(lines)
|
233
|
+
@status['contacts'][contact] ||= {}
|
234
|
+
lines.each do |line|
|
235
|
+
match = line.match(/^\s*(.+)=(.*)$/)
|
236
|
+
@status['contacts'][contact][match[1]] = match[2] unless match[1] == 'contact_name'
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def get_contact_name(lines)
|
241
|
+
if h = lines.grep(/\s+contact_name=(\w+)/).first
|
242
|
+
if h =~ /contact_name=(.*)$/
|
243
|
+
contact_name = $1
|
244
|
+
else
|
245
|
+
raise("Can't parse contact_name in block: #{h}")
|
246
|
+
end
|
247
|
+
else
|
248
|
+
raise("Can't parse contactstatus block")
|
249
|
+
end
|
250
|
+
return contact_name
|
251
|
+
end
|
252
|
+
|
253
|
+
# Parses a servicecomment block
|
254
|
+
def handle_servicecomment(lines)
|
255
|
+
host = get_host_name(lines)
|
256
|
+
service = get_service_name(lines)
|
257
|
+
@status["hosts"][host]['servicecomments'] ||= {}
|
258
|
+
@status["hosts"][host]['servicecomments'][service] ||= []
|
259
|
+
comment = {}
|
260
|
+
lines.each do |line|
|
261
|
+
match = line.match(/^\s*(.+)=(.*)$/)
|
262
|
+
comment[match[1]] = match[2] unless match[1] == 'service_name'
|
263
|
+
end
|
264
|
+
@status['hosts'][host]['servicecomments'][service] << comment
|
265
|
+
end
|
266
|
+
|
267
|
+
# Parses hostcomment block
|
268
|
+
def handle_hostcomment(lines)
|
269
|
+
host = get_host_name(lines)
|
270
|
+
@status['hosts'][host]['hostcomments'] ||= []
|
271
|
+
comment = {}
|
272
|
+
lines.each do |line|
|
273
|
+
match = line.match(/^\s*(.+)=(.*)$/)
|
274
|
+
comment[match[1]] = match[2] unless match[1] == 'host_name'
|
275
|
+
end
|
276
|
+
@status['hosts'][host]['hostcomments'] << comment
|
277
|
+
end
|
278
|
+
|
279
|
+
# Parses servicedowntime block
|
280
|
+
def handle_servicedowntime(lines)
|
281
|
+
host = get_host_name(lines)
|
282
|
+
service = get_service_name(lines)
|
283
|
+
downtime_id = get_downtime_id(lines)
|
284
|
+
@status["hosts"][host]["servicedowntime"] = {} unless @status["hosts"][host]["servicedowntime"]
|
285
|
+
@status["hosts"][host]["servicedowntime"][service] = downtime_id
|
286
|
+
end
|
287
|
+
|
288
|
+
# Parses hostdowntime block
|
289
|
+
def handle_hostdowntime(lines)
|
290
|
+
host = get_host_name(lines)
|
291
|
+
downtime_id = get_downtime_id(lines)
|
292
|
+
@status["hosts"][host]["hostdowntime"] = downtime_id
|
293
|
+
end
|
294
|
+
|
295
|
+
# Parse the downtime_id out of a block
|
296
|
+
def get_downtime_id(lines)
|
297
|
+
if h = lines.grep(/\s+downtime_id=(.*)$/).first
|
298
|
+
if h =~ /downtime_id=(.+)$/
|
299
|
+
downtime_id = $1
|
300
|
+
else
|
301
|
+
raise("Can't parse downtime_id in block: #{h}")
|
302
|
+
end
|
303
|
+
else
|
304
|
+
raise("Can't find downtime_id in block")
|
305
|
+
end
|
306
|
+
|
307
|
+
return downtime_id
|
308
|
+
end
|
309
|
+
|
310
|
+
# Parses a programstatus block
|
311
|
+
def handle_programstatus(lines)
|
312
|
+
@status["process"] = {} unless @status["process"]
|
313
|
+
|
314
|
+
lines.each do |l|
|
315
|
+
if l =~ /\s+(\w+)=(\w+)/
|
316
|
+
@status["process"][$1] = $2
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
# Parses a hoststatus block
|
322
|
+
def handle_hoststatus(lines)
|
323
|
+
host = get_host_name(lines)
|
324
|
+
|
325
|
+
@status["hosts"][host] = {} unless @status["hosts"][host]
|
326
|
+
@status["hosts"][host]["hoststatus"] = {} unless @status["hosts"][host]["hoststatus"]
|
327
|
+
|
328
|
+
lines.each do |l|
|
329
|
+
if l =~ /\s+(\w+)=(.+)\s*$/
|
330
|
+
@status["hosts"][host]["hoststatus"][$1] = $2
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
Binary file
|
data/ruby-nagios.gemspec
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
spec = Gem::Specification.new do |s|
|
2
|
+
s.name = 'ruby-nagios'
|
3
|
+
s.version = "0.0.1"
|
4
|
+
s.author = 'R.I.Pienaar'
|
5
|
+
s.email = 'rip@devco.net'
|
6
|
+
s.homepage = 'http://devco.net/'
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.summary = 'Ruby library for managing Nagios'
|
9
|
+
s.description = "Manage alerts, checks and acks in bulk"
|
10
|
+
s.files = `git ls-files`.split("\n")
|
11
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
12
|
+
s.require_paths = ['lib']
|
13
|
+
s.has_rdoc = false
|
14
|
+
s.add_development_dependency('rake')
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby-nagios
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- R.I.Pienaar
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-04-18 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rake
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
description: Manage alerts, checks and acks in bulk
|
36
|
+
email: rip@devco.net
|
37
|
+
executables:
|
38
|
+
- check_check
|
39
|
+
- nagsrv
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files: []
|
43
|
+
|
44
|
+
files:
|
45
|
+
- COPYING
|
46
|
+
- README
|
47
|
+
- Rakefile
|
48
|
+
- bin/check_check
|
49
|
+
- bin/nagsrv
|
50
|
+
- lib/nagios/status.rb
|
51
|
+
- pkg/ruby-nagios-0.0.1.gem
|
52
|
+
- ruby-nagios.gemspec
|
53
|
+
has_rdoc: true
|
54
|
+
homepage: http://devco.net/
|
55
|
+
licenses: []
|
56
|
+
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
hash: 3
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
version: "0"
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
hash: 3
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
version: "0"
|
80
|
+
requirements: []
|
81
|
+
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.3.7
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: Ruby library for managing Nagios
|
87
|
+
test_files: []
|
88
|
+
|