Class: Nagira
- Inherits:
-
Sinatra::Base
- Object
- Sinatra::Base
- Nagira
- Defined in:
- lib/app.rb,
lib/nagira.rb,
lib/app/routes/put.rb,
lib/app/routes/put/host.rb,
lib/app/routes/get/status.rb,
lib/app/routes/put/status.rb,
lib/app/routes/get/config.rb,
lib/app/routes/get/objects.rb
Overview
PUT method routes for services status.
Constant Summary
- VERSION =
File.read(File.(File.dirname(__FILE__)) + '/../version.txt').strip
- GITHUB =
"http://dmytro.github.com/nagira/"
- AR_PREFIX =
When this prefix added to routes convert output to ActiveResource compatible format (basically Array instead of Hash).
"/ar"
Instance Method Summary (collapse)
-
- (Object) api
Get all routes that Nagira provides.
-
- (Object) after("ArgumentError")
Return 400 if result of PUT operation is not success.
-
- (Object) before("clear data")
Clear values onf instance variables before start.
- - (Object) after("Return Array for ActiveResouce routes")
-
- (Object) before('find callback name')
Detects if request is using jQuery JSON-P and sets @callback variable.
-
- (Object) get_1_object
Get single Nagios object.
-
- (Object) get(/_api))
Provide information about API routes.
-
- (Object) get("/_config")
Get Nagios configuration hash form parsing main Nagios configuration file nagios.cfg.
-
- (Object) get_object_type
Get all objects of type :type.
-
- (Object) get_objects
Get full list of Nagios objects.
-
- (Object) get(/_runtime))
Print out nagira runtime configuration.
-
- (Object) get(/))
Returns application information: name, version, github repository.
-
- (Object) get_status
Return all hosts status.
-
- (Object) get_status_hostname
Hoststatus for single host.
-
- (Object) get_status_hostname_services
Endpoints:
-
GET /_status/:hostname/_services
-
GET /_status/:hostname/_hostcomments
-
GET /_status/:hostname/_servicecomments.
-
-
- (Object) get_status_hostname_services_service_name
Full or short status information for single service on single host.
-
- (Object) after("Object not found or bad request")
If result-set of object/status search is empty return HTTP 404 .
-
- (Array) before("Parse PUT request body")
Process the data before on each HTTP request.
-
- (Object) before("Parse Nagios files")
Parse nagios files.
-
- (Object) put("/_host_status/:host_name")
Same as /_status/:host_name (Not implemented).
-
- (Object) put("/_status")
Submit JSON Hash for multiple services, on multiple hosts.
-
- (Object) put(/_status/:host_name/_services/:service_description/_return_code/:return_code/_plugin_output/:plugin_output)
Update single service status on a single host.
-
- (Object) put("/_status/:host_name")
Update hoststatus information only for the given host.
-
- (Object) put("/_status/:host_name/_services")
Update multiple services on the same host.
-
- (Object) after("Return formatted data")
If it's a JSON-P request, return its data with prepended @callback function name.
-
- (Object) before("Initial Config")
Do some necessary tasks at start and then run Sinatra app.
-
- (Object) before("detect format")
Detect and strip output format extension.
-
- (Object) before('detect output mode')
Detect output mode modifier.
-
- (Object) update_host_status(params)
Small helper to submit data to ::Nagios::ExternalCommands object.
-
- (Object) update_service_status(params)
Small helper to submit data to ::Nagios::ExternalCommands object.
Instance Method Details
- (Object) api
Get all routes that Nagira provides.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/nagira.rb', line 41 def api api = { } param_regex = Regexp.new '\(\[\^\\\\\/\?\#\]\+\)' Nagira.routes.keys.each do |method| api[method] ||= [] Nagira.routes[method].each do |r| path = r[0].inspect[3..-3] r[1].each do |parm| path.sub!(param_regex,":#{parm}") end path.gsub!('\\','') api[method] << path unless path.empty? end end api end |
- (Object) after("ArgumentError")
Return 400 if result of PUT operation is not success.
284 285 286 287 |
# File 'lib/app.rb', line 284 after do return unless request.put? halt [400, @data.send("to_#{@format}") ] if ! @data[:result] end |
- (Object) before("clear data")
Clear values onf instance variables before start.
171 172 173 174 |
# File 'lib/app.rb', line 171 before do @data = [] @format = @output = nil end |
- (Object) after("Return Array for ActiveResouce routes")
295 296 297 |
# File 'lib/app.rb', line 295 after do @data = @data.values if @active_resource && @data.is_a?(Hash) end |
- (Object) before('find callback name')
Detects if request is using jQuery JSON-P and sets @callback variable. @callback variable is used if after method and prepends JSON data with callback function name.
Example
GET /_api?callback=jQuery12313123123 # @callback == jQuery12313123123
JSONP support is based on the code from sinatra/jsonp
Gem github.com/shtirlic/sinatra-jsonp.
249 250 251 252 253 254 255 |
# File 'lib/app.rb', line 249 before do if @format == :json ['callback','jscallback','jsonp','jsoncallback'].each do |x| @callback = params.delete(x) unless @callback end end end |
- (Object) get_1_object
Get single Nagios object.
Accepted output type modifiers:
-
none
59 60 61 62 63 64 65 66 67 |
# File 'lib/app/routes/get/objects.rb', line 59 get "/_objects/:type/:name" do |type,name| begin @data = @objects[type.to_sym][name] rescue NoMethodError nil end nil end |
- (Object) get(/_api))
Provide information about API routes
327 328 329 330 |
# File 'lib/app.rb', line 327 get "/_api" do @data = self.api nil end |
- (Object) get("/_config")
Get Nagios configuration hash form parsing main Nagios configuration file nagios.cfg
20 21 22 23 |
# File 'lib/app/routes/get/config.rb', line 20 get "/_config" do @data = $nagios[:config].configuration nil end |
- (Object) get_object_type
Get all objects of type :type
Accepted output type modifiers:
-
/_list
: Short list of available objects, depending on the current request context: hosts, services, etc.
36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/app/routes/get/objects.rb', line 36 get "/_objects/:type" do |type| begin @data = @objects[type.to_sym] @data = @data.keys if @output == :list rescue NoMethodError nil end nil end |
- (Object) get_objects
Get full list of Nagios objects. Returns hash containing all configured objects in Nagios: hosts, hostgroups, services, contacts. etc.
Accepted output type modifiers:
-
/_list
: Short list of available objects, depending on the current request context: hosts, services, etc.
16 17 18 19 20 21 22 23 24 |
# File 'lib/app/routes/get/objects.rb', line 16 get "/_objects" do @data = begin @output == :list ? @objects.keys : @objects rescue NoMethodError nil end nil end |
- (Object) get(/_runtime))
Print out nagira runtime configuration
338 339 340 341 342 343 344 345 346 347 348 349 350 |
# File 'lib/app.rb', line 338 get "/_runtime" do @data = { application: self.class, version: VERSION, runtime: { environment: Nagira.settings.environment, home: ENV['HOME'], user: ENV['LOGNAME'], nagiosFiles: $nagios.keys.map { |x| { x => $nagios[x].path }} } } nil end |
- (Object) get(/))
Returns application information: name, version, github repository.
356 357 358 359 360 361 362 363 364 |
# File 'lib/app.rb', line 356 get "/" do @data = { :application => self.class, :version => VERSION, :source => GITHUB, :apiUrl => request.url.sub(/\/$/,'') + "/_api", } nil end |
- (Object) get_status
Return all hosts status.
If no output modifier provided, outputs full hosttatus information for each
host. Not including services information. When _full
modifier
is provided data include hoststatus, servicestatus and all comments
(servicecomments and hostcomments) for hosts.
Alias: get /_status is the same thing as get /_status/_hosts with ActiveResource compatibility, i.e. for */_hosts request Nagira returns array instead of hash.
Accepted output type modifiers:
-
/_state
- Instead of full status information send only current state. For hosts up/down, for services OK, Warn, Critical, Unknown (0,1,2-1) -
/_list
: Short list of available objects, depending on the current request context: hosts, services, etc. -
/_full
- Show full status information. When used in /_status/_full call will display full hoststaus and servicestatus information for each host.
Support for (see API):
-
plural resources: N/A
-
object access by ID: N/A
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/app/routes/get/status.rb', line 137 get /^\/_status(\/_hosts)?$/ do @data = @status.dup case @output when :state @data.each { |k,v| @data[k] = v['hoststatus'].slice("host_name", "current_state") } when :list @data = @data.keys when :full @data else @data.each { |k,v| @data[k] = v['hoststatus'] } end nil end |
- (Object) get_status_hostname
Hoststatus for single host
Accepted output type modifiers:
-
/_state
- Instead of full status information send only current state. For hosts up/down, for services OK, Warn, Critical, Unknown (0,1,2-1)
Support for:
-
plural resources: N/A
-
object access by ID: NO (TODO)
168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/app/routes/get/status.rb', line 168 get "/_status/:hostname" do |hostname| hostname = hostname.to_i if hostname =~ /^\d+$/ @data = @status[hostname]['hoststatus'].dup if @status.has_key? hostname if @output == :state @data = @data.slice("host_name", "current_state") end nil end |
- (Object) get_status_hostname_services
Endpoints:
-
GET /_status/:hostname/_services
-
GET /_status/:hostname/_hostcomments
-
GET /_status/:hostname/_servicecomments
Read services
, hostcomments
or
servicecomments
for single host.
Accepted output type modifiers:
-
/_state
- Instead of full status information send only current state. For hosts up/down, for services OK, Warn, Critical, Unknown (0,1,2-1) -
/_list
: Short list of available objects, depending on the current request context: hosts, services, etc. -
/_full
- Show full status information. When used in /_status/_full call will display full hoststaus and servicestatus information for each host.
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/app/routes/get/status.rb', line 90 get %r{^/_status/(?<hostname>[\w\-\.]+)/_(?<service>(services|hostcomments|servicecomments))$} do |hostname,service| hostname = hostname.to_i if hostname =~ /^\d+$/ key = case service when 'services' 'servicestatus' else service end if @status && @status[hostname] case @output when :list @data = @status[hostname][key].keys when :state @data = @status.each { |k,v| @data[k] = v.slice("host_name", "service_description", "current_state") } else @data = @status[hostname][key] end end nil end |
- (Object) get_status_hostname_services_service_name
Full or short status information for single service on single host.
Accepted output type modifiers:
-
/_state
- Instead of full status information send only current state. For hosts up/down, for services OK, Warn, Critical, Unknown (0,1,2-1)
61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/app/routes/get/status.rb', line 61 get "/_status/:hostname/_services/:service_name" do |hostname,service| hostname = hostname.to_i if hostname =~ /^\d+$/ if @status && @status[hostname] if @output == :state @data = @status[hostname]['servicestatus'][service].slice("hostname", "service_description", "current_state") else @data = @status[hostname]['servicestatus'][service] end end nil end |
- (Object) after("Object not found or bad request")
If result-set of object/status search is empty return HTTP 404 . This can happen when you are requesting status for not existing host and/or service.
267 268 269 270 271 272 273 274 275 |
# File 'lib/app.rb', line 267 after do if ! @data || @data.empty? halt [404, { :message => "Object not found or bad request", :error => "HTTP::Notfound" }.send("to_#{@format}") ] end end |
- (Array) before("Parse PUT request body")
Process the data before on each HTTP request.
10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/app/routes/put.rb', line 10 before do if request.put? data = request.body.read @input = case @format when :json then JSON.parse data when :xml then Hash.from_xml data when :yaml then YAML.load data end # Make sure we always return an Array @input = [@input] if @input.is_a? Hash end @input end |
- (Object) before("Parse Nagios files")
Parse nagios files.
Note: *.parse methods are monkey-patched here (if you have required
'lib/nagira' above) to set min parsing interval to avoid file
paring on each HTTP request. File is parsed only if it was changed and if
it was parsed more then 60 (default) seconds ago. See
lib/nagira/timed_parse.rb
for mor more info.
In development mode use files located under ./test/data
directory. This allows to do development on the host where Nagios is
notinstalled. If you want to change this edit configuration in
config/environment.rb file.
See also comments in config/default.rb file regarding nagios_cfg, status_cfg, objects_cfg.
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/app.rb', line 126 before do if Nagira.settings.start_background_parser unless $bg.alive? logger.warn "Background Parser is configured to run, but is not active" $nagios[:config].parse $nagios[:status].parse $nagios[:objects].parse end $use_inflight_status ? @status = $nagios[:status_inflight].status['hosts'] : @status = $nagios[:status].status['hosts'] $use_inflight_objects ? @objects = $nagios[:objects_inflight].objects : @objects = $nagios[:objects].objects else $nagios[:config].parse $nagios[:status].parse $nagios[:objects].parse @status = $nagios[:status].status['hosts'] @objects = $nagios[:objects].objects end ## # TODO: This stuff breaks XML valid. Will have to wait. # # idx = 0 # @status.keys.uniq.each do |hostname| # @status[idx] = @status[hostname] # idx += 1 # end # # Add plural keys to use ActiveResource with Nagira # @objects.keys.each do |singular| @objects[singular.to_s.pluralize.to_sym] = @objects[singular] end end |
- (Object) put("/_host_status/:host_name")
Same as /_status/:host_name (Not implemented)
47 48 49 |
# File 'lib/app/routes/put/host.rb', line 47 put "/_host_status/:host_name" do "Not implemented: TODO" end |
- (Object) put("/_status")
Submit JSON Hash for multiple services, on multiple hosts.
10 11 12 |
# File 'lib/app/routes/put/host.rb', line 10 put "/_status" do "TODO: Not implemented" end |
- (Object) put(/_status/:host_name/_services/:service_description/_return_code/:return_code/_plugin_output/:plugin_output)
Update single service status on a single host. Use data provided in RESTful path as parameters.
Example
curl -d "test data" -X PUT http://localhost:4567/_status/viy/_services/PING/_return_code/0/_plugin_output/OK # => ok
93 94 95 96 |
# File 'lib/app/routes/put/status.rb', line 93 put "/_status/:host_name/_services/:service_description/_return_code/:return_code/_plugin_output/:plugin_output" do @data = update_service_status params nil end |
- (Object) put("/_status/:host_name")
Update hoststatus information only for the given host. URL hostname always override hostname given in the JSON file.
Example
$ curl -i -H "Accept: application/json" -d @host.json -X PUT http://localhost:4567/_status/svaroh => {"result": true, "object": [{"data": {"host_name":"svaroh", "status_code": "0", "plugin_output": "ping OK", "action": "PROCESS_HOST_CHECK_RESULT"}, "result":true, "messages": []}]}
Example JSON
{
"status_code":"0",
"plugin_output" : "ping OK"
}
35 36 37 38 39 40 |
# File 'lib/app/routes/put/host.rb', line 35 put "/_status/:host_name" do @data = update_host_status @input.first.merge({ 'host_name' => params['host_name'] }) nil end |
- (Object) put("/_status/:host_name/_services")
Update multiple services on the same host.
Hostname from URL always overrides host_name if it's is provided in the JSON data.
Example return JSON data
$ curl -i -H "Accept: application/json" -d @dat_m.json -X PUT http://localhost:4567/_status/svaroh/_services {"result"=>true, "object"=> [{"data"=> {"return_code"=>0, "plugin_output"=>"All OK", "service_description"=>"PING", "host_name"=>"archive", "action"=>"PROCESS_SERVICE_CHECK_RESULT"}, "result"=>true, "messages"=>[]}]}
Example JSON for submit
All attributes provided in the example below are requried for host service status information:
-
host_name
-
service_description
-
return_code
-
plugin_output
[{ "host_name":"viy", "service_description":"PING", "return_code":"0", "plugin_output":"64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.046 ms " }, {"host_name":"svaroh", "service_description":"Apache", "return_code":"2", "plugin_output":"HTTP GEt failed" } ]
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/app/routes/put/status.rb', line 54 put "/_status/:host_name/_services" do data, result = [], true @input.each do |datum| # FIXME - this calls update for each service. Should be batching them together update = update_service_status( datum.merge({ 'host_name' => params['host_name'] }) ) data << update[:object].first result &&= update[:result] end @data = { result: result, object: data } nil end |
- (Object) after("Return formatted data")
If it's a JSON-P request, return its data with prepended @callback
function name. JSONP request is detected by before
method.
If no callback paramete given, then simply return formatted data as XML, JSON, or YAML in response body.
Example
314 315 316 |
# File 'lib/app.rb', line 314 after do body( @callback ? "#{@callback.to_s} (#{@data.to_json})" : @data.send("to_#{@format}") ) end |
- (Object) before("Initial Config")
Do some necessary tasks at start and then run Sinatra app.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/app.rb', line 62 configure do $nagios = { } $nagios[:config] = Nagios::Config.new Nagira.settings.nagios_cfg $nagios[:config].parse $nagios.merge!({ status: Nagios::Status.new( Nagira.settings.status_cfg || $nagios[:config].status_file ), objects: Nagios::Objects.new( Nagira.settings.objects_cfg || $nagios[:config].object_cache_file ), commands: Nagios::ExternalCommands.new( Nagira.settings.command_file || $nagios[:config].command_file ) }) $nagios.merge!({ status_inflight: Nagios::Status.new( Nagira.settings.status_cfg || $nagios[:config].status_file ), objects_inflight: Nagios::Objects.new( Nagira.settings.objects_cfg || $nagios[:config].object_cache_file ) }) if ::DEFAULT[:start_background_parser] puts "[#{Time.now}] -- Starting Nagira application" puts "[#{Time.now}] -- Version #{Nagira::VERSION}" puts "[#{Time.now}] -- Running in #{Nagira.settings.environment} environment" $nagios.keys.each do |x| puts "[#{Time.now}] -- Using nagios #{x} file: #{$nagios[x].path}" end $nagios[:status].parse $nagios[:objects].parse @status = $nagios[:status].status['hosts'] @objects = $nagios[:objects].objects Nagios::BackgroundParser.new end |
- (Object) before("detect format")
Detect and strip output format extension
Strip extension (@format) from HTTP route and set it as instance variable @format. Valid formats are .xml, .json, .yaml. If format is not specified, it is set to default format (Nagira.settings.format).
@format can be assigned one of the symbols: :xml, :json, :yaml.
Examples
GET /_objects # => default format GET /_objects.json # => :json GET /_status/_list.yaml # => :yaml
195 196 197 198 199 |
# File 'lib/app.rb', line 195 before do request.path_info.sub!(/#{settings.format_extensions}/, '') @format = ($1 || settings.format).to_sym content_type "application/#{@format.to_s}" end |
- (Object) before('detect output mode')
Detect output mode modifier
Detect and strip output type from HTTP route. Full list of output types is
:list
, :state
or :full
,
corresponding to (+/list, /state
, /full
routes).
Output type defined by route modifier appended to the end of HTTP route. If
no output type specfied it is set to :full
. Output mode can be
followed by format extension (.json
, .xml
or
.yaml
).
Examples
GET /_objects/_list # => :list GET /_status/_state # => :state GET /_status/:hostname # => :full GET /_status # => :normal
229 230 231 232 |
# File 'lib/app.rb', line 229 before do request.path_info.sub!(/\/_(list|state|full)$/, '') @output = ($1 || :normal).to_sym end |
- (Object) update_host_status(params)
Small helper to submit data to ::Nagios::ExternalCommands object. For host status updates sends external command via ::Nagios::ExternalCommands.write method.
49 50 51 |
# File 'lib/app/routes/put.rb', line 49 def update_host_status params put_update :PROCESS_HOST_CHECK_RESULT, params end |
- (Object) update_service_status(params)
Small helper to submit data to ::Nagios::ExternalCommands object. For status updates sends external coond via ::Nagios::ExternalCommands.send method.
42 43 44 |
# File 'lib/app/routes/put.rb', line 42 def update_service_status params put_update :PROCESS_SERVICE_CHECK_RESULT, params end |