class LogStash::Outputs::Icinga
This plugin runs actions on an Icinga
server by calling its API. The Icinga
API is available since version 2.4. It replaces the formerly used command pipe by providing a similiar interface with filter capabilities. Actions are used in order to process check results, manage downtimes, tell Icinga
to send notifications and so on.
This plugin handles a defined set of actions. A list of all Icinga
actions is avaiable in the docs.icinga.com/icinga2/latest/doc/module/icinga2/chapter/icinga2-api#icinga2-api-actions[Icinga Docs].
Examples:
. Process a check result based on syslog severity
- source,ruby
-
filter {
if [syslog_severity] == "error" { mutate { replace => { "exit_status" => "2" } } }
} output {
icinga { host => 'demo.icinga.com' user => 'icinga' password => 'supersecret' action => 'process-check-result' action_config => { exit_status => "%{exit_status}" plugin_output => "%{message}" } icinga_host => "%{hostname}" icinga_service => "dummy" }
}
. Set a downtime of 2 hours, starting from now
- source,ruby
-
filter {
ruby { code => "event.set('start_time', Time.now.to_i)" } ruby { code => "event.set('end_time', Time.now.to_i + 7200)" }
} output {
icinga { host => 'demo' user => 'root' password => 'icinga' ssl_verify => false action => 'schedule-downtime' action_config => { author => "logstash" comment => "Downtime set by Logstash Output" start_time => "%{start_time}" end_time => "%{end_time}" } icinga_host => '%{hostname}' icinga_service => 'dummy' }
Constants
- ACTION_CONFIG_FIELDS
Public Instance Methods
receive(event)
click to toggle source
# File lib/logstash/outputs/icinga.rb, line 290 def receive(event) @available_hosts = @host.count begin @httpclient ||= connect request_body = Hash.new icinga_host = event.sprintf(@icinga_host) icinga_service = event.sprintf(@icinga_service) @uri.path = "/v1/actions/#{@action}" # Depending on the action we take, set either a filter in the request body or set a host and/or service in the # url parameters. case @action when 'remove-downtime', 'remove-comment' action_type = @action.split('-').last request_body['type'] = action_type.capitalize if @icinga_service request_body['filter'] = "host.name == \"#{icinga_host}\" && service.name == \"#{icinga_service}\" && #{action_type}.author == \"#{@action_config['author']}\"" else request_body['filter'] = "host.name == \"#{icinga_host}\" && #{action_type}.author == \"#{@action_config['author']}\"" end else if @icinga_service @uri.query = URI.encode_www_form({:service => "#{icinga_host}!#{icinga_service}"}).gsub('+','%20') else @uri.query = URI.encode_www_form({:host => icinga_host}).gsub('+','%20') end @action_config.each do |key, value| request_body[key] = event.sprintf(value) end end request = Net::HTTP::Post.new(@uri.request_uri) request.initialize_http_header({'Accept' => 'application/json'}) request.basic_auth(@user, @password.value) request.body = LogStash::Json.dump(request_body) response = @httpclient.request(request) raise StandardError if response.code != '200' response_body = LogStash::Json.load(response.body) response_body['results'].each do |result| logging_data = { :host => "#{@uri.host}:#{@uri.port}", :request_path => request.path, :request_body => request.body, :result_code => result['code'].to_i, :result_status => result['status'] } if result['code'] == 200 @logger.debug("Action '#{@action}' succeeded", logging_data) else @logger.warn("Action '#{@action}' failed", logging_data) end end.empty? and begin @logger.debug('Returned result was epty', :response_body => response.body) end rescue Timeout::Error => e @logger.warn( "Request failed", :host => @uri.host, :port => @uri.port, :path => request.path, :body => request.body, :error => e ) # If a host is not reachable, try the same request with the next host in the list. Try each host host only once per # request. if not (@available_hosts -= 1).zero? @httpclient = connect @logger.info("Retrying request with '#{@uri.host}:#{@uri.port}'") retry end rescue Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, OpenSSL::SSL::SSLError, StandardError => e @logger.warn("Request failed", :host => @uri.host, :port => @uri.port, :path => request.path, :body => request.body, :error => e ) if response @logger.warn("Response: ", :response_code => response.code, :response_body => response.body) if response.code == '404' && @create_object == true object = create_object(event) if object.code == '200' @logger.info("Retrying action on freshly created object", :action => @action) retry else @logger.warn("Failed to create object", :response_code => object.code, :response_body => object.body) end end end end end
register()
click to toggle source
# File lib/logstash/outputs/icinga.rb, line 283 def register validate_action_config @ssl_verify ? @ssl_verify_mode = OpenSSL::SSL::VERIFY_PEER : @ssl_verify_mode = OpenSSL::SSL::VERIFY_NONE @host_id = 0 end
Private Instance Methods
connect()
click to toggle source
# File lib/logstash/outputs/icinga.rb, line 406 def connect @current_host, @current_port = @host[@host_id].split(':') @host_id = @host_id + 1 >= @host.length ? 0 : @host_id + 1 if not @current_port @current_port = @port end @uri = URI.parse("https://#{@current_host}:#{@current_port}") http = Net::HTTP.new(@uri.host, @uri.port) http.use_ssl = true http.verify_mode = @ssl_verify_mode http.ca_file = @ca_file if @ca_file http.open_timeout = 2 http.read_timeout = 5 http end
create_object(event)
click to toggle source
# File lib/logstash/outputs/icinga.rb, line 425 def create_object(event) object_config = Hash.new object_config['templates'] = @object_templates object_config['attrs'] = Hash.new icinga_host = event.sprintf(@icinga_host) icinga_service = event.sprintf(@icinga_service) @object_attrs.each do |key, value| object_config['attrs'][key] = event.sprintf(value) end if @icinga_service @uri.path = '/v1/objects/services/' + URI.encode("#{icinga_host}!#{icinga_service}") else @uri.path = '/v1/objects/hosts/' + URI.encode(icinga_host) end @uri.query = URI.encode_www_form({:ignore_on_error => 1}) request = Net::HTTP::Put.new(@uri.request_uri) request.initialize_http_header({'Accept' => 'application/json'}) request.basic_auth(@user, @password.value) request.body = LogStash::Json.dump(object_config) @logger.info( "Creating Object", :request_uri => @uri.request_uri, :request_body => request.body, :icinga_host => icinga_host, :icinga_service => icinga_service ) response = @httpclient.request(request) response end
validate_action_config()
click to toggle source
# File lib/logstash/outputs/icinga.rb, line 392 def validate_action_config ACTION_CONFIG_FIELDS[@action].each do |field, settings| if settings['required'] && !@action_config.key?(field) @logger.error("Setting '#{field}' is required for action '#{@action}'") end end @action_config.each_key do |field| if not ACTION_CONFIG_FIELDS[@action].key?(field) @logger.warn("Unknown setting '#{field}' for action '#{action}'") end end end