#!/usr/bin/env ruby require 'redis' require 'json' require 'yaml' require 'optparse' require 'ostruct' require 'flapjack/data/entity_check' options = OpenStruct.new options.config = File.join('etc', 'flapjack_config.yaml') options.daemonize = nil OptionParser.new do |opts| opts.banner = "Usage: flapjack-nagios-receiver [options]" opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c| options.config = c end opts.on("-f", "--fifo FIFO", String, "Path to the nagios perfdata named pipe") do |f| options.fifo = f end end.parse!(ARGV) FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development' # load the config hash for the current environment if File.file?(options.config) config = YAML::load(File.open(options.config)) else puts "Could not find config file at '#{options.config}', you may want to specify one with the --config option" exit(false) end config_env = config[FLAPJACK_ENV] if config_env.nil? || config_env.empty? puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'" exit(false) end if !options.fifo puts "You must specify a path to the nagios perfdata named pipe using the --fifo option" exit(false) end @fifo = File.new(options.fifo) # nagios.cfg contains the following templates for host and service data (modified from the default # to include hoststate / servicestate, and a fake service 'HOST' for hostperfdata, so that the # fields match up # host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\tHOST\t$HOSTSTATE$\t$HOSTEXECUTIONTIME$\t$HOSTLATENCY$\t$HOSTOUTPUT$\t$HOSTPERFDATA$ # service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICESTATE$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$ @redis_host = config_env['redis']['host'] || 'localhost' @redis_port = config_env['redis']['port'] || '6379' @redis_path = config_env['redis']['path'] || nil @redis_db = config_env['redis']['db'] || 0 if config_env.nil? || config_env.empty? puts "No config data for environment '#{FLAPJACK_ENV}'" exit(false) end def process_input if @redis_path redis = Redis.new(:db => @redis_db, :path => @redis_path) else redis = Redis.new(:db => @redis_db, :host => @redis_host, :port => @redis_port) end begin while line = @fifo.gets skip unless line object_type, timestamp, entity, check, state, check_time, check_latency, check_output, check_perfdata = line.split("\t") puts "#{object_type}, #{timestamp}, #{entity}, #{check}, #{state}, #{check_output}" next unless line.length == 9 next unless timestamp =~ /^\d+$/ next unless (object_type == '[HOSTPERFDATA]') or (object_type == '[SERVICEPERFDATA]') state = 'ok' if state.downcase == 'up' state = 'critical' if state.downcase == 'down' event = { 'entity' => entity, 'check' => check, 'type' => 'service', 'state' => state, 'summary' => check_output, 'timestamp' => timestamp, }.to_json redis.rpush 'events', event end rescue Redis::CannotConnectError puts "Error, unable to to connect to the redis server (#{$!})" rescue EOFError puts "Error - end of file reached when reading from the named pipe. Nagios down?" sleep 10 end end def main while true process_input sleep 10 end end main