lib/nagiosharder.rb in nagiosharder-0.3.0 vs lib/nagiosharder.rb in nagiosharder-0.4.0.rc1
- old
+ new
@@ -1,10 +1,11 @@
require 'restclient'
require 'nokogiri'
require 'active_support' # fine, we'll just do all of activesupport instead of the parts I want. thank Rails 3 for shuffling requires around.
require 'cgi'
require 'hashie'
+require 'nagiosharder/filters'
# :(
require 'active_support/version' # double and triplely ensure ActiveSupport::VERSION is around
if ActiveSupport::VERSION::MAJOR > 2
require 'active_support/core_ext/array'
@@ -22,50 +23,72 @@
class NagiosHarder
class Site
attr_accessor :nagios_url, :user, :password, :default_options, :default_cookies, :version, :nagios_time_format
include HTTParty::ClassMethods
- def initialize(nagios_url, user, password, version = 3)
+ def initialize(nagios_url, user, password, version = 3, nagios_time_format = nil)
@nagios_url = nagios_url.gsub(/\/$/, '')
@user = user
@password = password
@default_options = {}
@default_cookies = {}
@version = version
+ debug_output if ENV['DEBUG']
basic_auth(@user, @password) if @user && @password
-
- @nagios_time_format = if @version.to_i < 3
- "%m-%d-%Y %H:%M:%S"
- else
- "%Y-%m-%d %H:%M:%S"
- end
+ @nagios_time_format = if nagios_time_format == 'us'
+ "%m-%d-%Y %H:%M:%S"
+ else
+ if @version.to_i < 3
+ "%m-%d-%Y %H:%M:%S"
+ else
+ "%Y-%m-%d %H:%M:%S"
+ end
+ end
+ self
end
def acknowledge_service(host, service, comment)
- # extra options: sticky_arg, send_notification, persistent
-
request = {
:cmd_typ => 34,
:cmd_mod => 2,
:com_author => @user,
:com_data => comment,
:host => host,
- :service => service
+ :service => service,
+ :send_notification => true,
+ :persistent => false,
+ :sticky_ack => true
}
response = post(cmd_url, :body => request)
response.code == 200 && response.body =~ /successful/
end
+ def acknowledge_host(host, comment)
+ request = {
+ :cmd_typ => 33,
+ :cmd_mod => 2,
+ :com_author => @user,
+ :com_data => comment,
+ :host => host,
+ :send_notification => true,
+ :persistent => false,
+ :sticky_ack => true
+ }
+
+ response = post(cmd_url, :body => request)
+ response.code == 200 && response.body =~ /successful/
+ end
+
def unacknowledge_service(host, service)
request = {
:cmd_typ => 52,
:cmd_mod => 2,
:host => host,
:service => service
}
-
+
response = post(cmd_url, :body => request)
response.code == 200 && response.body =~ /successful/
end
def schedule_service_downtime(host, service, options = {})
@@ -128,11 +151,11 @@
response = post(cmd_url, :body => request)
response.code == 200 && response.body =~ /successful/
end
-
+
def cancel_downtime(downtime_id, downtime_type = :host_downtime)
downtime_types = {
:host_downtime => 78,
:service_downtime => 79
}
@@ -141,11 +164,11 @@
:cmd_mod => 2,
:down_id => downtime_id
})
response.code == 200 && response.body =~ /successful/
end
-
+
def schedule_host_check(host)
response = post(cmd_url, :body => {
:start_time => formatted_time_for(Time.now),
:host => host,
:force_check => true,
@@ -165,69 +188,53 @@
:cmd_mod => 2
})
response.code == 200 && response.body =~ /successful/
end
- def service_status(type, options = {})
- service_status_type = case type
- when :ok then 2
- when :warning then 4
- when :unknown then 8
- when :critical then 16
- when :pending then 1
- when :all_problems then 28
- when :all then nil
- else
- raise "Unknown type"
- end
+ def service_status(options = {})
+ params = {}
- sort_type = case options[:sort_type]
- when :asc then 1
- when :desc then 2
- when nil then nil
- else
- raise "Invalid options[:sort_type]"
- end
+ {
+ :host_status_types => :notification_host,
+ :service_status_types => :notification_service,
+ :sort_type => :sort,
+ :sort_option => :sort,
+ :host_props => :host,
+ :service_props => :service,
+ }.each do |key, val|
+ if options[key] && (options[key].is_a?(Array) || options[key].is_a?(Symbol))
+ params[key.to_s.gsub(/_/, '')] = Nagiosharder::Filters.value(val, *options[key])
+ end
+ end
- sort_option = case options[:sort_option]
- when :host then 1
- when :service then 2
- when :status then 3
- when :last_check then 4
- when :duration then 6
- when :attempts then 5
- when nil then nil
- else
- raise "Invalid options[:sort_option]"
- end
+ # if any of the standard filter params are already integers, those win
+ %w(
+ :hoststatustypes,
+ :servicestatustypes,
+ :sorttype,
+ :sortoption,
+ :hostprops,
+ :serviceprops,
+ ).each do |key|
+ params[key.to_s] = options[:val] if !options[:val].nil? && options[:val].match(/^\d*$/)
+ end
- service_group = options[:group]
+ if @version == 3
+ params['servicegroup'] = options[:group] || 'all'
+ params['style'] = 'detail'
+ params['embedded'] = '1'
+ params['noheader'] = '1'
+ else
+ if options[:group]
+ params['servicegroup'] = options[:group]
+ params['style'] = 'detail'
+ else
+ params['host'] = 'all'
+ end
+ end
-
- params = {
- 'hoststatustype' => 15,
- 'servicestatustype' => service_status_type,
- 'host' => 'all'
- }
-
-
- params = if @version == 3
- [ "servicegroup=all", "style=detail" ]
- else
- if service_group
- ["servicegroup=#{service_group}", "style=detail"]
- else
- ["host=all"]
- end
- end
- params += [
- service_status_type ? "servicestatustypes=#{service_status_type}" : nil,
- sort_type ? "sorttype=#{sort_type}" : nil,
- sort_option ? "sortoption=#{sort_option}" : nil,
- "hoststatustypes=15"
- ]
- query = params.compact.join('&')
+ query = params.select {|k,v| v }.map {|k,v| "#{k}=#{v}" }.join('&')
url = "#{status_url}?#{query}"
response = get(url)
raise "wtf #{url}? #{response.code}" unless response.code == 200
@@ -238,31 +245,37 @@
statuses
end
def host_status(host)
- host_status_url = "#{status_url}?host=#{host}"
+ host_status_url = "#{status_url}?host=#{host}&embedded=1&noheader=1"
response = get(host_status_url)
raise "wtf #{host_status_url}? #{response.code}" unless response.code == 200
services = {}
parse_status_html(response) do |status|
services[status[:service]] = status
end
-
+
services
end
def disable_service_notifications(host, service, options = {})
request = {
:cmd_mod => 2,
- :cmd_typ => 23,
- :host => host,
- :service => service,
+ :host => host
}
+ if service
+ request[:cmd_typ] = 23
+ request[:service] = service
+ else
+ request[:cmd_typ] = 29
+ request[:ahas] = true
+ end
+
response = post(cmd_url, :body => request)
if response.code == 200 && response.body =~ /successful/
# TODO enable waiting. seems to hang intermittently
#if options[:wait]
# sleep(3) until service_notifications_disabled?(host, service)
@@ -274,15 +287,21 @@
end
def enable_service_notifications(host, service, options = {})
request = {
:cmd_mod => 2,
- :cmd_typ => 22,
- :host => host,
- :service => service,
+ :host => host
}
+ if service
+ request[:cmd_typ] = 22
+ request[:service] = service
+ else
+ request[:cmd_typ] = 28
+ request[:ahas] = true
+ end
+
response = post(cmd_url, :body => request)
if response.code == 200 && response.body =~ /successful/
# TODO enable waiting. seems to hang intermittently
#if options[:wait]
# sleep(3) while service_notifications_disabled?(host, service)
@@ -290,16 +309,16 @@
true
else
false
end
end
-
+
def service_notifications_disabled?(host, service)
self.host_status(host)[service].notifications_disabled
end
-
-
+
+
def status_url
"#{nagios_url}/status.cgi"
end
def cmd_url
@@ -315,29 +334,32 @@
def formatted_time_for(time)
time.strftime(nagios_time_format)
end
def parse_status_html(response)
- doc = Nokogiri::HTML(response)
+ doc = Nokogiri::HTML(response.to_s)
rows = doc.css('table.status > tr')
last_host = nil
rows.each do |row|
columns = Nokogiri::HTML(row.inner_html).css('body > td').to_a
if columns.any?
-
+
+ # Host column
host = columns[0].inner_text.gsub(/\n/, '')
# for a given host, the host details are blank after the first row
if host != ''
# remember it for next time
last_host = host
else
# or save it for later
host = last_host
end
+ debug 'parsed host column'
+ # Service Column
if columns[1]
service_links = columns[1].css('td a')
service_link, other_links = service_links[0], service_links[1..-1]
if service_links.size > 1
comments_link = other_links.detect do |link|
@@ -364,29 +386,45 @@
extra_service_notes_url = extra_service_notes_link.attribute('href').to_s if extra_service_notes_link
end
service = service_links[0].inner_html
end
-
+ debug 'parsed service column'
+
+ # Status
status = columns[2].inner_html if columns[2]
+ debug 'parsed status column'
+
+ # Last Check
last_check = if columns[3] && columns[3].inner_html != 'N/A'
last_check_str = columns[3].inner_html
-
- DateTime.strptime(columns[3].inner_html, nagios_time_format).to_time
+ debug "Need to parse #{columns[3].inner_html} in #{nagios_time_format}"
+ DateTime.strptime(columns[3].inner_html, nagios_time_format).to_s
end
+ debug 'parsed last check column'
+
+ # Duration
duration = columns[4].inner_html.squeeze(' ').gsub(/^ /, '') if columns[4]
started_at = if duration && match_data = duration.match(/^\s*(\d+)d\s+(\d+)h\s+(\d+)m\s+(\d+)s\s*$/)
(
match_data[1].to_i.days +
match_data[2].to_i.hours +
match_data[3].to_i.minutes +
match_data[4].to_i.seconds
).ago
end
+ debug 'parsed duration column'
+
+ # Attempts
attempts = columns[5].inner_html if columns[5]
- status_info = columns[6].inner_html.gsub(' ', '') if columns[6]
+ debug 'parsed attempts column'
+ # Status info
+ status_info = columns[6].inner_html.gsub(' ', '').gsub("\302\240", '') if columns[6]
+ debug 'parsed status info column'
+
+
if host && service && status && last_check && duration && attempts && started_at && status_info
service_extinfo_url = "#{extinfo_url}?type=2&host=#{host}&service=#{CGI.escape(service)}"
host_extinfo_url = "#{extinfo_url}?type=1&host=#{host}"
status = Hashie::Mash.new :host => host,
@@ -410,9 +448,12 @@
end
end
nil
end
-
- end
+ def debug(*args)
+ $stderr.puts *args if ENV['DEBUG']
+ end
+
+ end
end