diff --git a/centreon-certified/canopsis/canopsis2x-events-apiv2.lua b/centreon-certified/canopsis/canopsis2x-events-apiv2.lua old mode 100644 new mode 100755 index 7be345a5..f5d09f9d --- a/centreon-certified/canopsis/canopsis2x-events-apiv2.lua +++ b/centreon-certified/canopsis/canopsis2x-events-apiv2.lua @@ -63,9 +63,7 @@ function EventQueue.new(params) self.fail = true end - -- force buffer size to 1 because this SC does not allows the event bulk at this moment. (can't send more than one event at once) - params.max_buffer_size = 1 - self.sc_logger:notice("[EventQueue:new]: max_buffer_size = 1 (force buffer size to 1 because this SC does not allows the event bulk at this moment)") + self.sc_params.params.max_buffer_size = params.max_buffer_size or 1000 -- mandatory parameter self.sc_params.params.canopsis_authkey = params.canopsis_authkey @@ -73,10 +71,9 @@ function EventQueue.new(params) -- overriding default parameters for this stream connector if the default values doesn't suit the basic needs self.sc_params.params.accepted_categories = params.accepted_categories or "neb" self.sc_params.params.accepted_elements = params.accepted_elements or "host_status,service_status,acknowledgement,downtime" - self.sc_params.params.canopsis_downtime_comment_route = params.canopsis_downtime_comment_route or "/api/v4/pbehavior-comments" self.sc_params.params.canopsis_downtime_reason_name = params.canopsis_downtime_reason_name or "Centreon_downtime" self.sc_params.params.canopsis_downtime_reason_route = params.canopsis_downtime_reason_route or "/api/v4/pbehavior-reasons" - self.sc_params.params.canopsis_downtime_route = params.canopsis_downtime_route or "/api/v4/pbehaviors" + self.sc_params.params.canopsis_downtime_route = params.canopsis_downtime_route or "/api/v4/bulk/connector-pbehaviors" self.sc_params.params.canopsis_downtime_send_pbh = params.canopsis_downtime_send_pbh or 1 self.sc_params.params.canopsis_downtime_type_name = params.canopsis_downtime_type_name or "Default maintenance" self.sc_params.params.canopsis_downtime_type_route = params.canopsis_downtime_type_route or "/api/v4/pbehavior-types" @@ -121,7 +118,7 @@ function EventQueue.new(params) self.sc_flush:add_queue_metadata(categories.neb.id, elements.host_status.id, {event_route = self.sc_params.params.canopsis_event_route}) self.sc_flush:add_queue_metadata(categories.neb.id, elements.service_status.id, {event_route = self.sc_params.params.canopsis_event_route}) self.sc_flush:add_queue_metadata(categories.neb.id, elements.acknowledgement.id, {event_route = self.sc_params.params.canopsis_event_route}) - self.sc_flush:add_queue_metadata(categories.neb.id, elements.downtime.id, {event_route = self.sc_params.params.canopsis_downtime_route}) + self.sc_flush:add_queue_metadata(categories.neb.id, elements.downtime.id, {method = "PUT", event_route = self.sc_params.params.canopsis_downtime_route}) self.format_event = { [categories.neb.id] = { @@ -162,14 +159,27 @@ function EventQueue.new(params) --Check if downtime are wanted if self.sc_params.params.canopsis_downtime_send_pbh ~= 0 and self.sc_params.params.accepted_elements_info["downtime"] then + -- 1. Check Canopsis version : if the API endpoint exists + local metadata_route = { + method = "PUT", + event_route = self.sc_params.params.canopsis_downtime_route + } + local routeExists = self:checkCanopsisAPI(metadata_route, {}) + if routeExists ~= true then + self.sc_logger:info("[EventQueue.new]: route " .. self.sc_params.params.canopsis_downtime_route .. " is not available - check Canopsis API release") + -- if the route doesn't exist disable pbehavior management + self.sc_params.params.canopsis_downtime_send_pbh = 0 + self.sc_params.params.canopsis_downtime_not_send_pbh_reason = " route " .. self.sc_params.params.canopsis_downtime_route .. " is not available - check Canopsis API release" + + return self + end + + -- 2. Reason : Ensure reason "centreon_reason" exists, if not create it and post it local metadata_reason = { method = "GET", event_route = self.sc_params.params.canopsis_downtime_reason_route } - pbh_maintenance_reason_id = self:getCanopsisAPI(metadata_reason, self.sc_params.params.canopsis_downtime_reason_route, "", self.sc_params.params.canopsis_downtime_reason_name) - - -- 1. Reason : Ensure reason "centreon_reason" exists, if not create it and post it if pbh_maintenance_reason_id == false then self.sc_logger:notice("Reason for Centreon downtimes doesn't exist in Canopsis API: Creating pbehavior-reason 'centreon_reason") new_reason = { @@ -180,20 +190,24 @@ function EventQueue.new(params) method = "POST", event_route = self.sc_params.params.canopsis_downtime_reason_route } - self:postCanopsisAPI(metadata_post, self.sc_params.params.canopsis_downtime_reason_route, new_reason) - else + pbh_maintenance_reason_id = self:postCanopsisAPI(metadata_post, self.sc_params.params.canopsis_downtime_reason_route, new_reason) + end + + if pbh_maintenance_reason_id ~= false then -- If the reason id is reachable with downtime_reason_route - if pbh_maintenance_reason_id ~= false and self.sc_params.params.send_data_test ~= 1 then + if self.sc_params.params.send_data_test ~= 1 then self.sc_params.params.canopsis_downtime_reason_id = pbh_maintenance_reason_id - elseif pbh_maintenance_reason_id ~= false and self.sc_params.params.send_data_test == 1 then - self.sc_params.params.canopsis_downtime_reason_id = "RRRR" else - -- if unable to get reason id, disable pbehavior management - self.sc_params.params.canopsis_downtime_send_pbh = 0 + self.sc_params.params.canopsis_downtime_reason_id = "RRRR" end + else + -- if unable to get reason id, disable pbehavior management + self.sc_logger:info("[EventQueue.new]: Canopsis reason is not available") + self.sc_params.params.canopsis_downtime_send_pbh = 0 + self.sc_params.params.canopsis_downtime_not_send_pbh_reason = " Canopsis reason is not available" end - -- 2. Type : Dynamically get pbehavior type id for canopsis_downtime_type_name + -- 3. Type : Dynamically get pbehavior type id for canopsis_downtime_type_name local metadata_type = { method = "GET", event_route = self.sc_params.params.canopsis_downtime_type_route @@ -206,15 +220,16 @@ function EventQueue.new(params) self.sc_params.params.canopsis_downtime_type_id = "TTTT" else -- if unable to get type id, disable pbehavior management + self.sc_logger:info("[EventQueue.new]: Canopsis type is not available") self.sc_params.params.canopsis_downtime_send_pbh = 0 + self.sc_params.params.canopsis_downtime_not_send_pbh_reason = " Canopsis type is not available" + end + else + if self.sc_params.params.canopsis_downtime_send_pbh ~= 1 then + self.sc_params.params.canopsis_downtime_not_send_pbh_reason = " parameter canopsis_downtime_send_pbh is set to 0" + else + self.sc_params.params.canopsis_downtime_not_send_pbh_reason = " parameter accepted_elements doesn't contain downtime" end - - -- 3. Type : Check Canopsis version to add or not the color value - local metadata_type = { - method = "GET", - event_route = "/api/v4/app-info" - } - canopsis_version = self:getCanopsisAPI(metadata_type, "/api/v4/app-info", "", "") end return self @@ -386,64 +401,44 @@ end function EventQueue:format_event_downtime() local event = self.sc_event.event - local elements = self.sc_params.params.bbdo.elements if not event.internal_id then event.internal_id = event.id end - local downtime_name = "centreon-downtime-" .. tostring(event.internal_id) .. "-" .. tostring(event.entry_time) - if event.cancelled == true or (self.bbdo_version == 2 and event.deletion_time == 1) or (self.bbdo_version > 2 and event.deletion_time ~= -1) then - local metadata = { - method = "DELETE", - event_route = self.sc_params.params.canopsis_downtime_route + self.sc_event.event.formated_event = { + action = "delete", + origin = self.sc_params.params.connector .. "/" .. self:get_connector_name(), + tstart = event.start_time, + tstop = event.end_time, + comment = event.comment_data } - self:send_data({name = downtime_name}, metadata) else + local origin = self.sc_params.params.connector .. "/" .. self:get_connector_name() + local downtime_name = origin .. " downtime " .. tostring(event.start_time) .. "-" .. tostring(event.end_time) .. " " .. event.comment_data + if string.len(downtime_name) > 255 then + downtime_name = string.sub(downtime_name, 1, 252) .. "..." + end self.sc_event.event.formated_event = { - _id = downtime_name, - author = event.author, - enabled = true, + action = "create", name = downtime_name, + origin = origin, reason = self.sc_params.params.canopsis_downtime_reason_id, - rrule = "", tstart = event.start_time, tstop = event.end_time, type = self.sc_params.params.canopsis_downtime_type_id, - -- timezone = self.sc_params.params.timezone, - comment = { - { - --['author'] = event.author, - ['pbehavior'] = downtime_name, - ['message'] = event.comment_data - } - }, - entity_pattern = { - { - { - field = "_id", - cond = { - type = "eq" - } - } - } - } - -- exdates = {} + comment = event.comment_data, + color = "#73D8FF" } + end - -- in downtime events, service id is equal to 0 when the downtime is about a host (same for BBDO 2 and 3) - if event.service_id ~= 0 then - self.sc_event.event.formated_event["entity_pattern"][1][1]["cond"]["value"] = tostring(event.cache.service.description) - .. "/" .. tostring(event.cache.host.name) - else - self.sc_event.event.formated_event["entity_pattern"][1][1]["cond"]["value"] = tostring(event.cache.host.name) - end - - -- In case of Canopsis version 22.10.X a color value is add in downtime: - if string.find(canopsis_version, "22.10.") ~= nil then - self.sc_event.event.formated_event["color"] = "#73D8FF" - end + -- in downtime events, service id is equal to 0 when the downtime is about a host (same for BBDO 2 and 3) + if event.service_id ~= 0 then + self.sc_event.event.formated_event["entities"] = {tostring(event.cache.service.description) + .. "/" .. tostring(event.cache.host.name)} + else + self.sc_event.event.formated_event["entities"] = {tostring(event.cache.host.name)} end end @@ -487,47 +482,32 @@ end function EventQueue:send_data(payload, queue_metadata) self.sc_logger:debug("[EventQueue:send_data]: Starting to send data") + if self.sc_params.params.canopsis_downtime_send_pbh ~= 1 and queue_metadata.event_route == self.sc_params.params.canopsis_downtime_route then + if self.sc_params.params.canopsis_downtime_not_send_pbh_reason ~= nil then + self.sc_logger:info("[EventQueue:send_data]: Downtime data is not sent, " .. self.sc_params.params.canopsis_downtime_not_send_pbh_reason) + else + self.sc_logger:info("[EventQueue:send_data]: Downtime data is not sent") + end + + return true + end + local params = self.sc_params.params - local downtime_comment = "" - local send_downtime_comment = false local http_method = "POST" local url = params.sending_protocol .. "://" .. params.canopsis_host .. ':' .. params.canopsis_port .. queue_metadata.event_route - -- Deletion (for downtimes) - if queue_metadata.method ~= nil and queue_metadata.method == "DELETE" then + if queue_metadata.method ~= nil then http_method = queue_metadata.method - url = url .. "?name=" .. payload.name - queue_metadata.headers = { - "accept: */*", - "x-canopsis-authkey: " .. tostring(self.sc_params.params.canopsis_authkey) - } - payload = broker.json_encode(payload) - self.sc_logger:log_curl_command(url, queue_metadata, self.sc_params.params, "") - - -- Downtime events creation - elseif queue_metadata.event_route == self.sc_params.params.canopsis_downtime_route then - payload = payload[1] - queue_metadata.headers = { - "content-type: application/json", - "x-canopsis-authkey: " .. tostring(self.sc_params.params.canopsis_authkey) - } - downtime_comment = table_extract_and_remove_key(payload,"comment") - send_downtime_comment = true - payload = broker.json_encode(payload) - - self.sc_logger:log_curl_command(url, queue_metadata, self.sc_params.params, payload) - - -- Other Event than downtimes - else - payload = broker.json_encode(payload) - queue_metadata.headers = { - "content-length: " .. string.len(payload), - "content-type: application/json", - "x-canopsis-authkey: " .. tostring(self.sc_params.params.canopsis_authkey) - } - self.sc_logger:log_curl_command(url, queue_metadata, self.sc_params.params, payload) end + payload = broker.json_encode(payload) + queue_metadata.headers = { + "content-length: " .. string.len(payload), + "content-type: application/json", + "x-canopsis-authkey: " .. tostring(self.sc_params.params.canopsis_authkey) + } + self.sc_logger:log_curl_command(url, queue_metadata, self.sc_params.params, payload) + -- write payload in the logfile for test purpose if self.sc_params.params.send_data_test == 1 then self.sc_logger:notice("[send_data]: " .. tostring(payload)) @@ -586,17 +566,6 @@ function EventQueue:send_data(payload, queue_metadata) if http_response_code >= 200 and http_response_code <= 299 then self.sc_logger:info("[EventQueue:send_data]: HTTP " .. http_method .. " request successful: return code is " .. tostring(http_response_code)) - - -- in case of Downtime event post, an other post is required - if send_downtime_comment == true then - self.sc_logger:info("[EventQueue:send_data]: Comment to send is " .. tostring(downtime_comment)) - local metadata_comment = { - method = "POST", - event_route = self.sc_params.params.canopsis_downtime_comment_route - } - self:postCanopsisAPI(metadata_comment, self.sc_params.params.canopsis_downtime_comment_route, downtime_comment) - end - retval = true elseif http_response_code == 400 and (string.match(tostring(http_response_body), "Trying to insert PBehavior with already existing _id") or string.find(tostring(http_response_body), "ID already exists")) then self.sc_logger:notice("[EventQueue:send_data]: Ignoring downtime with id: " .. tostring(payload._id) @@ -698,7 +667,7 @@ function flush() end -------------------------------------------------------------------------------- --- Function to send a Post Request to Canopsis API for Reason route +-- Function to send a Post Request to Canopsis API for reason route -------------------------------------------------------------------------------- function EventQueue:postCanopsisAPI(self_metadata, route, data_to_send) @@ -710,22 +679,12 @@ function EventQueue:postCanopsisAPI(self_metadata, route, data_to_send) local params = self.sc_params.params local url = params.sending_protocol .. "://" .. params.canopsis_host .. ':' .. params.canopsis_port .. route - if route == self.sc_params.params.canopsis_downtime_comment_route then - data_to_send = data_to_send[1] - self_metadata.headers = { - "accept: application/json", - "content-type: application/json", - "x-canopsis-authkey: " .. tostring(self.sc_params.params.canopsis_authkey) - } - data_to_send = broker.json_encode(data_to_send) - else - data_to_send = broker.json_encode(data_to_send) - self_metadata.headers = { - "content-length: " .. string.len(data_to_send), - "content-type: application/json", - "x-canopsis-authkey: " .. tostring(self.sc_params.params.canopsis_authkey) - } - end + data_to_send = broker.json_encode(data_to_send) + self_metadata.headers = { + "content-length: " .. string.len(data_to_send), + "content-type: application/json", + "x-canopsis-authkey: " .. tostring(self.sc_params.params.canopsis_authkey) + } self.sc_logger:log_curl_command(url, self_metadata, self.sc_params.params, data_to_send) @@ -786,7 +745,15 @@ function EventQueue:postCanopsisAPI(self_metadata, route, data_to_send) .. tostring(http_response_code)) self.sc_logger:notice("[postCanopsisAPI]: HTTP POST request successful: return code is " .. tostring(http_response_code)) - retval = true + + local json_response_decoded, error = broker.json_decode(http_response_body) + if error then + self.sc_logger:error("[postCanopsisAPI]: couldn't decode json string: " .. tostring(http_response_body) + .. ". Error is: " .. tostring(error)) + return retval + end + + retval = json_response_decoded["_id"] else self.sc_logger:error("[postCanopsisAPI]: HTTP POST request FAILED, return code is " .. tostring(http_response_code) .. ". Message is: " .. tostring(http_response_body)) @@ -800,7 +767,7 @@ function EventQueue:postCanopsisAPI(self_metadata, route, data_to_send) end -------------------------------------------------------------------------------- --- Function to send a Get Request to Canopsis API for Reason, type and version routes +-- Function to send a Get Request to Canopsis API for reason and type routes -------------------------------------------------------------------------------- function EventQueue:getCanopsisAPI(self_metadata, route, type_name, reason_name) @@ -893,13 +860,6 @@ function EventQueue:getCanopsisAPI(self_metadata, route, type_name, reason_name) retval = reason_object["_id"] end end - -- No type_name and no reason_name had been given => getCanopsisAPI is used to check Canopsis version - elseif type_name == "" and reason_name == "" then - for json_element, json_object in pairs(json_response_decoded) do - if json_element == "version" then - retval = json_object - end - end end else self.sc_logger:error("[getCanopsisAPI]: HTTP request FAILED, return code is " @@ -908,3 +868,92 @@ function EventQueue:getCanopsisAPI(self_metadata, route, type_name, reason_name) return retval end + +-------------------------------------------------------------------------------- +-- Function to send a request to Canopsis API and check if a route exists +-------------------------------------------------------------------------------- +function EventQueue:checkCanopsisAPI(self_metadata, data_to_send) + self.sc_logger:debug("[checkCanopsisAPI]:Sending data to Canopsis route: ".. self_metadata.event_route) + + -- Handling the return code + local retval = false + local data_to_send = data_to_send + local params = self.sc_params.params + local url = params.sending_protocol .. "://" .. params.canopsis_host .. ':' .. params.canopsis_port .. self_metadata.event_route + + data_to_send = broker.json_encode(data_to_send) + self_metadata.headers = { + "content-length: " .. string.len(data_to_send), + "content-type: application/json", + "x-canopsis-authkey: " .. tostring(self.sc_params.params.canopsis_authkey) + } + + self.sc_logger:log_curl_command(url, self_metadata, self.sc_params.params, data_to_send) + + -- write payload in the logfile for test purpose + if self.sc_params.params.send_data_test == 1 then + self.sc_logger:notice("[checkCanopsisAPI]: " .. tostring(data_to_send)) + return true + end + + self.sc_logger:info("[checkCanopsisAPI]: Going to send the following json: " .. data_to_send) + self.sc_logger:info("[checkCanopsisAPI]: Canopsis address is: " .. tostring(url)) + + local http_response_body = "" + local http_request = curl.easy() + :setopt_url(url) + :setopt_writefunction( + function (response) + http_response_body = http_response_body .. tostring(response) + end + ) + :setopt(curl.OPT_TIMEOUT, self.sc_params.params.connection_timeout) + :setopt(curl.OPT_SSL_VERIFYPEER, self.sc_params.params.verify_certificate) + :setopt(curl.OPT_SSL_VERIFYHOST, self.sc_params.params.verify_certificate) + :setopt(curl.OPT_HTTPHEADER, self_metadata.headers) + :setopt(curl.OPT_CUSTOMREQUEST, self_metadata.method) + + -- set proxy address configuration + if (self.sc_params.params.proxy_address ~= '') then + if (self.sc_params.params.proxy_port ~= '') then + http_request:setopt(curl.OPT_PROXY, self.sc_params.params.proxy_address .. ':' .. self.sc_params.params.proxy_port) + else + self.sc_logger:error("[checkCanopsisAPI]: proxy_port parameter is not set but proxy_address is used") + end + end + + -- set proxy user configuration + if (self.sc_params.params.proxy_username ~= '') then + if (self.sc_params.params.proxy_password ~= '') then + http_request:setopt(curl.OPT_PROXYUSERPWD, self.sc_params.params.proxy_username + .. ':' .. self.sc_params.params.proxy_password) + else + self.sc_logger:error("[checkCanopsisAPI]: proxy_password parameter is not set but proxy_username is used") + end + end + + if self_metadata.method == 'POST' or self_metadata.method == 'PUT' then + http_request:setopt_postfields(data_to_send) + end + + -- performing the HTTP request + http_request:perform() + + -- collecting results + http_response_code = http_request:getinfo(curl.INFO_RESPONSE_CODE) + + http_request:close() + + if http_response_code >= 200 and http_response_code <= 299 or http_response_code == 400 then + self.sc_logger:info("[checkCanopsisAPI]: HTTP request successful: return code is " + .. tostring(http_response_code)) + self.sc_logger:notice("[checkCanopsisAPI]: HTTP request successful: return code is " + .. tostring(http_response_code)) + retval = true + else + self.sc_logger:error("[checkCanopsisAPI]: HTTP request FAILED, return code is " + .. tostring(http_response_code) .. ". Message is: " .. tostring(http_response_body)) + end + + return retval +end \ No newline at end of file