2020-02-05 15:40:22 +01:00
#
2021-02-08 09:55:50 +01:00
# Copyright 2021 Centreon (http://www.centreon.com/)
2020-02-05 15:40:22 +01:00
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package notification::sirportly::mode::ticket ;
use base qw( centreon::plugins::mode ) ;
use strict ;
use warnings ;
use centreon::plugins::http ;
use centreon::plugins::statefile ;
use JSON::XS ;
sub new {
my ( $ class , % options ) = @ _ ;
my $ self = $ class - > SUPER:: new ( package = > __PACKAGE__ , % options ) ;
bless $ self , $ class ;
$ options { options } - > add_options ( arguments = > {
'hostname:s' = > { name = > 'hostname' , default = > 'api.sirportly.com' } ,
'port:s' = > { name = > 'port' , default = > 443 } ,
'proto:s' = > { name = > 'proto' , default = > 'https' } ,
'api-token:s' = > { name = > 'api_token' } ,
'api-secret:s' = > { name = > 'api_secret' } ,
'cache' = > { name = > 'cache' } ,
'contact-name:s' = > { name = > 'contact_name' , default = > 'Centreon Notifications' } ,
'contact-type:s' = > { name = > 'contact_type' , default = > 'telephone' } ,
'contact-data:s' = > { name = > 'contact_data' , default = > '-' } ,
'brand:s' = > { name = > 'brand' } ,
'department:s' = > { name = > 'department' } ,
'submit-user:s' = > { name = > 'submit_user' } ,
'close-user:s' = > { name = > 'close_user' } ,
'submit-status:s' = > { name = > 'submit_status' } ,
'close-status:s' = > { name = > 'close_status' } ,
'priority-mapping:s' = > { name = > 'priority_mapping' } ,
'priority:s' = > { name = > 'priority' } ,
'item-id:s' = > { name = > 'item_id' } ,
'subject:s' = > { name = > 'subject' } ,
'message:s' = > { name = > 'message' } ,
'timeout:s' = > { name = > 'timeout' } ,
} ) ;
$ self - > { http } = centreon::plugins::http - > new ( % options ) ;
$ self - > { cache } = centreon::plugins::statefile - > new ( % options ) ;
return $ self ;
}
sub check_options {
my ( $ self , % options ) = @ _ ;
$ self - > SUPER:: init ( % options ) ;
2020-02-12 11:51:24 +01:00
foreach ( ( 'api_token' , 'api_secret' , 'brand' , 'department' , 'submit_status' ,
'close_status' , 'priority' , 'item_id' , 'subject' , 'message' ) ) {
if ( ! defined ( $ self - > { option_results } - > { $ _ } ) ) {
my $ option = $ _ ;
$ option =~ s/_/-/g ;
$ self - > { output } - > add_option_msg ( short_msg = > "You need to set --$option option" ) ;
$ self - > { output } - > option_exit ( ) ;
}
2020-02-05 15:40:22 +01:00
}
$ self - > { http } - > set_options ( % { $ self - > { option_results } } ) ;
$ self - > { cache } - > check_options ( option_results = > $ self - > { option_results } ) ;
}
sub proceed {
my ( $ self , % options ) = @ _ ;
# Let's compute a priority mapping hash, with lc keys
my % priority_mapping ;
if ( defined ( $ self - > { option_results } - > { priority_mapping } ) ) {
my $ i = 0 ;
% priority_mapping = map { $ i + + % 2 ? $ _ : lc } split /[:,]/ , $ self - > { option_results } - > { priority_mapping } ;
}
# Let's compute a ticket tag to be able to find the opened ticket later on
my $ tag = $ options { item_id } ;
if ( $ options { priority } =~ /^(UP|DOWN|UNREACHABLE)$/i ) {
$ tag = "centreon-hst:$tag" ;
} else {
$ tag = "centreon-svc:$tag" ;
}
# Is there an existing Sirportly ticket for this item ?
my $ post_param = [
"spql=SELECT tickets.reference,statuses.name FROM tickets WHERE ticket_tags.tag=\"$tag\" AND statuses.name!=\"$self->{option_results}->{close_status}\" ORDER BY tickets.submitted_at DESC LIMIT 1" ,
] ;
my $ response = $ self - > { http } - > request ( method = > 'POST' , url_path = > '/api/v2/tickets/spql' , post_param = > $ post_param , warning_status = > '' , unknown_status = > '' , critical_status = > '' ) ;
my $ ticket_info ;
eval {
$ ticket_info = JSON::XS - > new - > decode ( $ response ) - > { results } [ 0 ] ;
} ;
2020-02-12 22:37:04 +01:00
if ( $ options { priority } =~ /^(UP|OK)$/i ) { # Close the ticket
2020-02-05 15:40:22 +01:00
if ( defined ( $ ticket_info ) ) {
$ post_param = [
"ticket=$ticket_info->[0]" ,
"contact=$self->{option_results}->{contact_name}" ,
"message=$options{message}" ,
] ;
$ self - > { http } - > request ( method = > 'POST' , url_path = > '/api/v2/tickets/post_update' , post_param = > $ post_param , warning_status = > '' , unknown_status = > '' , critical_status = > '' ) ;
if ( $ ticket_info - > [ 1 ] eq $ self - > { option_results } - > { submit_status } ) {
$ post_param = [
"ticket=$ticket_info->[0]" ,
"user=" . ( defined ( $ self - > { option_results } - > { close_user } ) ? $ self - > { option_results } - > { close_user } : "" ) ,
"status=$self->{option_results}->{close_status}" ,
] ;
2020-02-12 22:37:04 +01:00
my $ response = $ self - > { http } - > request ( method = > 'POST' , url_path = > '/api/v2/tickets/update' , post_param = > $ post_param , warning_status = > '' , unknown_status = > '' , critical_status = > '' ) ;
2020-02-05 15:40:22 +01:00
eval {
2020-02-12 22:37:04 +01:00
JSON::XS - > new - > decode ( $ response ) ;
2020-02-05 15:40:22 +01:00
} ;
2020-02-12 22:37:04 +01:00
if ( $@ ) { # We only check we received a response from Sirportly, thus we don't take the risk to hold the queue/cache processing
2020-02-05 15:40:22 +01:00
$ ticket_info - > [ 0 ] = "failed" ;
}
}
}
2020-02-12 11:51:24 +01:00
} elsif ( defined ( $ ticket_info ) ) { # Update an existing ticket
2020-02-05 15:40:22 +01:00
$ post_param = [
"ticket=$ticket_info->[0]" ,
"contact=$self->{option_results}->{contact_name}" ,
"message=$options{message}" ,
] ;
$ self - > { http } - > request ( method = > 'POST' , url_path = > '/api/v2/tickets/post_update' , post_param = > $ post_param , warning_status = > '' , unknown_status = > '' , critical_status = > '' ) ;
$ post_param = [
"ticket=$ticket_info->[0]" ,
"priority=" . ( defined ( $ priority_mapping { lc ( $ options { priority } ) } ) ? $ priority_mapping { lc ( $ options { priority } ) } : $ options { priority } ) ,
] ;
2020-02-12 22:37:04 +01:00
my $ response = $ self - > { http } - > request ( method = > 'POST' , url_path = > '/api/v2/tickets/update' , post_param = > $ post_param , warning_status = > '' , unknown_status = > '' , critical_status = > '' ) ;
2020-02-05 15:40:22 +01:00
eval {
2020-02-12 22:37:04 +01:00
JSON::XS - > new - > decode ( $ response ) ;
2020-02-05 15:40:22 +01:00
} ;
2020-02-12 22:37:04 +01:00
if ( $@ ) { # We only check we received a response from Sirportly, thus we don't take the risk to hold the queue/cache processing
2020-02-12 11:51:24 +01:00
$ ticket_info - > [ 0 ] = 'failed' ;
2020-02-05 15:40:22 +01:00
}
2020-02-12 11:51:24 +01:00
} else { # Open a new ticket
2020-02-05 15:40:22 +01:00
$ post_param = [
"contact_name=$self->{option_results}->{contact_name}" ,
"contact_method_type=$self->{option_results}->{contact_type}" ,
"contact_method_data=$self->{option_results}->{contact_data}" ,
"brand=$self->{option_results}->{brand}" ,
"department=$self->{option_results}->{department}" ,
"user=" . ( defined ( $ self - > { option_results } - > { submit_user } ) ? $ self - > { option_results } - > { submit_user } : "" ) ,
"status=$self->{option_results}->{submit_status}" ,
"priority=" . ( defined ( $ priority_mapping { lc ( $ options { priority } ) } ) ? $ priority_mapping { lc ( $ options { priority } ) } : $ options { priority } ) ,
"tag_list=$tag" ,
"subject=$options{subject}" ,
"message=$options{message}" ,
] ;
my $ response = $ self - > { http } - > request ( method = > 'POST' , url_path = > '/api/v2/tickets/submit' , post_param = > $ post_param , warning_status = > '' , unknown_status = > '' , critical_status = > '' ) ;
my $ decoded ;
eval {
$ decoded = JSON::XS - > new - > decode ( $ response ) ;
} ;
2020-02-12 22:37:04 +01:00
if ( $@ || ! defined ( $ decoded - > { reference } ) ) { # Here we check Sirportly correctly received the new ticket, as it's the most important step
2020-02-05 15:40:22 +01:00
$ ticket_info - > [ 0 ] = "failed" ;
} else {
$ ticket_info - > [ 0 ] = $ decoded - > { reference } ;
}
}
# Return proceeded ticket
return $ ticket_info - > [ 0 ] ;
}
sub run {
my ( $ self , % options ) = @ _ ;
# Authentication headers
$ self - > { http } - > add_header ( key = > 'X-Auth-Token' , value = > $ self - > { option_results } - > { api_token } ) ;
$ self - > { http } - > add_header ( key = > 'X-Auth-Secret' , value = > $ self - > { option_results } - > { api_secret } ) ;
# Load cache
$ self - > { cache } - > read ( statefile = > 'sirportly_api_' . $ self - > { option_results } - > { api_token } ) ;
my $ cache ;
if ( defined ( $ self - > { option_results } - > { cache } ) ) {
$ cache = $ self - > { cache } - > get ( name = > 'cache' ) ;
} else {
$ cache = { } ;
}
# Add current item to cache
my $ cache_index = time ( ) ;
$ cache - > { $ cache_index } - > { item_id } = $ self - > { option_results } - > { item_id } ;
$ cache - > { $ cache_index } - > { priority } = $ self - > { option_results } - > { priority } ;
$ cache - > { $ cache_index } - > { subject } = $ self - > { option_results } - > { subject } ;
$ cache - > { $ cache_index } - > { message } = $ self - > { option_results } - > { message } ;
$ self - > { cache } - > write ( data = > { cache = > $ cache } ) ;
# Proceed cached notifications
my $ cache_size = keys % { $ cache } ;
my $ cache_done = 0 ;
foreach $ cache_index ( sort keys % { $ cache } ) {
my $ ticket_reference = $ self - > proceed (
priority = > $ cache - > { $ cache_index } - > { priority } ,
item_id = > $ cache - > { $ cache_index } - > { item_id } ,
subject = > $ cache - > { $ cache_index } - > { subject } ,
message = > $ cache - > { $ cache_index } - > { message } ,
) ;
2020-02-12 11:51:24 +01:00
if ( ! defined ( $ ticket_reference ) || $ ticket_reference ne 'failed' ) {
2020-02-05 15:40:22 +01:00
delete ( $ cache - > { $ cache_index } ) ;
$ self - > { cache } - > write ( data = > { cache = > $ cache } ) ;
$ cache_done + + ;
} else {
last ;
}
}
# Exit
2020-02-12 11:51:24 +01:00
$ self - > { output } - > output_add (
severity = > ( $ cache_size == $ cache_done ) ? 'OK' : 'CRITICAL' ,
short_msg = > "Proceeded " . $ cache_done . "/" . $ cache_size . " notifications"
) ;
2020-02-05 15:40:22 +01:00
$ self - > { output } - > display ( force_ignore_perfdata = > 1 ) ;
$ self - > { output } - > exit ( ) ;
}
1 ;
__END__
= head1 MODE
Open tickets via Sirportly API ( https: //si rportly . com /docs/ api - specification / )
= over 6
= item B <--hostname>
Hostname of the OVH SMS API ( default: 'api.sirportly.com' ) .
= item B <--port>
Port used by API ( default: '443' ) .
= item B <--proto>
Specify https if needed ( Default: 'https' ) .
= item B <--api-token>
Specify the API authentication token .
= item B <--api-secret>
Specify the API authentication secret .
= item B <--cache>
Cache notifications not correctly delivered , to retry at next run .
= item B <--contact-name>
Specify the contact name for this ticket ( default: 'Centreon Notifications' ) .
= item B <--contact-type>
Specify the contact type ( email or telephone ) of the contact ( default: 'telephone' ) .
= item B <--contact-data>
Specify the email address or telephone number of the contact ( default: '-' ) .
= item B <--brand>
Specify the brand for this ticket .
= item B <--department>
Specify the department for this ticket .
= item B <--submit-user>
Specify the user to assign the ticket to when submitting the ticket .
= item B <--close-user>
Specify the user to assign the ticket to when closing the ticket .
= item B <--submit-status>
Specify the Sirportly status to be used when submitting the ticket .
= item B <--close-status>
2020-02-12 22:37:04 +01:00
Specify the Sirportly status to be used when closing the ticket ( only if still in submit status ) .
2020-02-05 15:40:22 +01:00
= item B <--priority-mapping>
Map the Centreon priorities to Sirportly ones , comma separated ( syntax: ( down | unreachable | warning | critical | unknown ) : priority ) .
= item B <--priority>
Specify the priority for this ticket .
= item B <--item-id>
Specify the host or service ID for this ticket .
= item B <--subject>
Specify the subject for this ticket .
= item B <--message>
Specify the message for this ticket .
= item B <--timeout>
Threshold for HTTP timeout
= back
= cut