2013-12-13 16:14:12 +01:00
#
2020-01-06 15:19:23 +01:00
# Copyright 2020 Centreon (http://www.centreon.com/)
2015-07-21 11:51:02 +02: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.
#
2013-12-13 16:14:12 +01:00
package centreon::plugins::statefile ;
2014-05-07 11:40:16 +02:00
use strict ;
use warnings ;
2013-12-13 16:14:12 +01:00
use Data::Dumper ;
use vars qw( $datas ) ;
2014-05-09 22:55:13 +02:00
use centreon::plugins::misc ;
2013-12-13 16:14:12 +01:00
2014-02-21 11:31:20 +01:00
my $ default_dir = '/var/lib/centreon/centplugins' ;
2020-08-05 10:40:29 +02:00
if ( $^O eq 'MSWin32' ) {
$ default_dir = 'C:/Windows/Temp' ;
}
2014-02-21 11:31:20 +01:00
2013-12-13 16:14:12 +01:00
sub new {
my ( $ class , % options ) = @ _ ;
my $ self = { } ;
bless $ self , $ class ;
if ( defined ( $ options { options } ) ) {
2019-07-03 09:08:54 +02:00
$ options { options } - > add_options ( arguments = > {
2020-06-15 09:20:24 +02:00
'memcached:s' = > { name = > 'memcached' } ,
'redis-server:s' = > { name = > 'redis_server' } ,
'redis-attribute:s%' = > { name = > 'redis_attribute' } ,
'redis-db:s' = > { name = > 'redis_db' } ,
'memexpiration:s' = > { name = > 'memexpiration' , default = > 86400 } ,
'statefile-dir:s' = > { name = > 'statefile_dir' , default = > $ default_dir } ,
'statefile-suffix:s' = > { name = > 'statefile_suffix' , default = > '' } ,
'statefile-concat-cwd' = > { name = > 'statefile_concat_cwd' } ,
'statefile-storable' = > { name = > 'statefile_storable' } ,
'failback-file' = > { name = > 'failback_file' }
2019-07-03 09:08:54 +02:00
} ) ;
2013-12-13 16:14:12 +01:00
$ options { options } - > add_help ( package = > __PACKAGE__ , sections = > 'RETENTION OPTIONS' , once = > 1 ) ;
}
2020-02-27 10:39:30 +01:00
2015-02-20 11:41:11 +01:00
$ self - > { error } = 0 ;
2013-12-13 16:14:12 +01:00
$ self - > { output } = $ options { output } ;
$ self - > { datas } = { } ;
2014-05-09 22:55:13 +02:00
$ self - > { storable } = 0 ;
$ self - > { memcached_ok } = 0 ;
2013-12-13 16:14:12 +01:00
$ self - > { memcached } = undef ;
2020-02-27 10:39:30 +01:00
2013-12-13 16:14:12 +01:00
$ self - > { statefile_dir } = undef ;
2015-02-16 10:18:39 +01:00
$ self - > { statefile_suffix } = undef ;
2020-02-27 10:39:30 +01:00
2013-12-13 16:14:12 +01:00
return $ self ;
}
sub check_options {
my ( $ self , % options ) = @ _ ;
if ( defined ( $ options { option_results } ) && defined ( $ options { option_results } - > { memcached } ) ) {
2020-02-27 10:39:30 +01:00
centreon::plugins::misc:: mymodule_load (
output = > $ self - > { output } ,
module = > 'Memcached::libmemcached' ,
error_msg = > "Cannot load module 'Memcached::libmemcached'."
) ;
2013-12-13 16:14:12 +01:00
$ self - > { memcached } = Memcached::libmemcached - > new ( ) ;
Memcached::libmemcached:: memcached_server_add ( $ self - > { memcached } , $ options { option_results } - > { memcached } ) ;
}
2020-02-27 10:39:30 +01:00
2017-11-22 13:10:07 +01:00
# Check redis
if ( defined ( $ options { option_results } - > { redis_server } ) ) {
$ self - > { redis_attributes } = '' ;
if ( defined ( $ options { option_results } - > { redis_attribute } ) ) {
foreach ( keys % { $ options { option_results } - > { redis_attribute } } ) {
2019-07-03 09:08:54 +02:00
$ self - > { redis_attributes } . = "$_ => " . $ options { option_results } - > { redis_attribute } - > { $ _ } . ', ' ;
2017-11-22 13:10:07 +01:00
}
}
2020-02-27 10:39:30 +01:00
2020-02-19 11:52:30 +01:00
centreon::plugins::misc:: mymodule_load (
output = > $ self - > { output } ,
module = > 'Redis' ,
error_msg = > "Cannot load module 'Redis'."
) ;
2017-11-22 13:10:07 +01:00
eval {
2020-06-15 09:20:24 +02:00
$ options { option_results } - > { redis_server } . = ':6379' if ( $ options { option_results } - > { redis_server } !~ /:\d+$/ ) ;
2020-02-19 11:52:30 +01:00
$ self - > { redis_cnx } = Redis - > new (
server = > $ options { option_results } - > { redis_server } ,
eval $ self - > { redis_attributes }
) ;
2019-07-03 09:08:54 +02:00
if ( defined ( $ self - > { redis_cnx } ) &&
defined ( $ options { option_results } - > { redis_db } ) &&
$ options { option_results } - > { redis_db } ne ''
) {
$ self - > { redis_cnx } - > select ( $ options { option_results } - > { redis_db } ) ;
}
2017-11-22 13:10:07 +01:00
} ;
2020-06-15 09:20:24 +02:00
if ( ! defined ( $ self - > { redis_cnx } ) && ! defined ( $ options { option_results } - > { failback_file } ) ) {
$ self - > { output } - > add_option_msg ( short_msg = > "redis connection issue: $@" ) ;
$ self - > { output } - > option_exit ( ) ;
}
2017-11-22 13:10:07 +01:00
}
2020-02-27 10:39:30 +01:00
2013-12-13 16:14:12 +01:00
$ self - > { statefile_dir } = $ options { option_results } - > { statefile_dir } ;
2014-02-21 11:31:20 +01:00
if ( $ self - > { statefile_dir } ne $ default_dir && defined ( $ options { option_results } - > { statefile_concat_cwd } ) ) {
2020-02-19 11:52:30 +01:00
centreon::plugins::misc:: mymodule_load (
output = > $ self - > { output } ,
module = > 'Cwd' ,
error_msg = > "Cannot load module 'Cwd'."
) ;
2014-02-21 11:31:20 +01:00
$ self - > { statefile_dir } = Cwd:: cwd ( ) . '/' . $ self - > { statefile_dir } ;
}
2014-05-09 22:55:13 +02:00
if ( defined ( $ options { option_results } - > { statefile_storable } ) ) {
2020-02-19 11:52:30 +01:00
centreon::plugins::misc:: mymodule_load (
output = > $ self - > { output } ,
module = > 'Storable' ,
error_msg = > "Cannot load module 'Storable'."
) ;
2014-05-09 22:55:13 +02:00
$ self - > { storable } = 1 ;
}
2015-02-16 10:18:39 +01:00
$ self - > { statefile_suffix } = $ options { option_results } - > { statefile_suffix } ;
2017-11-22 13:10:07 +01:00
$ self - > { memexpiration } = $ options { option_results } - > { memexpiration } ;
2013-12-13 16:14:12 +01:00
}
2015-02-20 11:41:11 +01:00
sub error {
2016-01-29 15:16:26 +01:00
my ( $ self ) = shift ;
2020-02-19 11:52:30 +01:00
2016-01-29 15:16:26 +01:00
if ( @ _ ) {
2015-02-20 11:41:11 +01:00
$ self - > { error } = $ _ [ 0 ] ;
2016-01-29 15:16:26 +01:00
}
return $ self - > { error } ;
2015-02-20 11:41:11 +01:00
}
2013-12-13 16:14:12 +01:00
sub read {
my ( $ self , % options ) = @ _ ;
2015-02-20 11:41:11 +01:00
$ self - > { statefile_suffix } = defined ( $ options { statefile_suffix } ) ? $ options { statefile_suffix } : $ self - > { statefile_suffix } ;
2013-12-13 16:14:12 +01:00
$ self - > { statefile_dir } = defined ( $ options { statefile_dir } ) ? $ options { statefile_dir } : $ self - > { statefile_dir } ;
2020-02-27 10:39:30 +01:00
$ self - > { statefile } = defined ( $ options { statefile } ) ? $ options { statefile } . $ self - > { statefile_suffix } : $ self - > { statefile } ;
2015-02-20 11:41:11 +01:00
$ self - > { no_quit } = defined ( $ options { no_quit } ) && $ options { no_quit } == 1 ? 1 : 0 ;
2013-12-13 16:14:12 +01:00
if ( defined ( $ self - > { memcached } ) ) {
# if "SUCCESS" or "NOT FOUND" is ok. Other with use the file
2020-02-27 10:39:30 +01:00
my $ val = Memcached::libmemcached:: memcached_get ( $ self - > { memcached } , $ self - > { statefile_dir } . '/' . $ self - > { statefile } ) ;
2013-12-13 16:14:12 +01:00
if ( defined ( $ self - > { memcached } - > errstr ) && $ self - > { memcached } - > errstr =~ /^SUCCESS|NOT FOUND$/i ) {
2014-05-09 22:55:13 +02:00
$ self - > { memcached_ok } = 1 ;
2013-12-13 16:14:12 +01:00
if ( defined ( $ val ) ) {
eval ( $ val ) ;
$ self - > { datas } = $ datas ;
$ datas = { } ;
return 1 ;
}
return 0 ;
}
}
2020-02-19 11:52:30 +01:00
2017-11-22 13:10:07 +01:00
if ( defined ( $ self - > { redis_cnx } ) ) {
my $ val = $ self - > { redis_cnx } - > get ( $ self - > { statefile_dir } . "/" . $ self - > { statefile } ) ;
if ( defined ( $ val ) ) {
eval ( $ val ) ;
$ self - > { datas } = $ datas ;
$ datas = { } ;
return 1 ;
}
2020-02-27 10:39:30 +01:00
2017-11-22 13:10:07 +01:00
return 0 ;
}
2020-02-19 11:52:30 +01:00
2019-07-03 09:08:54 +02:00
if ( ! - e $ self - > { statefile_dir } . '/' . $ self - > { statefile } ) {
2019-01-11 15:43:32 +01:00
if ( ! - w $ self - > { statefile_dir } || ! - x $ self - > { statefile_dir } ) {
2015-02-20 11:41:11 +01:00
$ self - > error ( 1 ) ;
2019-01-11 15:43:32 +01:00
$ self - > { output } - > add_option_msg ( short_msg = > "Cannot write statefile '" . $ self - > { statefile_dir } . "/" . $ self - > { statefile } . "'. Need write/exec permissions on directory." ) ;
2015-02-20 11:41:11 +01:00
if ( $ self - > { no_quit } == 0 ) {
$ self - > { output } - > option_exit ( ) ;
}
2013-12-13 16:14:12 +01:00
}
return 0 ;
2019-07-03 09:08:54 +02:00
} elsif ( ! - w $ self - > { statefile_dir } . '/' . $ self - > { statefile } ) {
2015-02-20 11:41:11 +01:00
$ self - > error ( 1 ) ;
2013-12-13 16:14:12 +01:00
$ self - > { output } - > add_option_msg ( short_msg = > "Cannot write statefile '" . $ self - > { statefile_dir } . "/" . $ self - > { statefile } . "'. Need write permissions on file." ) ;
2015-02-20 11:41:11 +01:00
if ( $ self - > { no_quit } == 0 ) {
$ self - > { output } - > option_exit ( ) ;
}
return 1 ;
2019-07-03 09:08:54 +02:00
} elsif ( ! - s $ self - > { statefile_dir } . '/' . $ self - > { statefile } ) {
2014-02-20 17:58:37 +01:00
# Empty file. Not a problem. Maybe plugin not manage not values
return 0 ;
2013-12-13 16:14:12 +01:00
}
2020-02-19 11:52:30 +01:00
2014-05-09 22:55:13 +02:00
if ( $ self - > { storable } == 1 ) {
2019-07-03 09:08:54 +02:00
open FILE , $ self - > { statefile_dir } . '/' . $ self - > { statefile } ;
2014-05-09 22:55:13 +02:00
eval {
$ self - > { datas } = Storable:: fd_retrieve ( * FILE ) ;
} ;
# File is corrupted surely. We'll reset it
2013-12-13 16:14:12 +01:00
if ( $@ ) {
2014-05-09 22:55:13 +02:00
close FILE ;
return 0 ;
2013-12-13 16:14:12 +01:00
}
2014-05-09 22:55:13 +02:00
close FILE ;
} else {
2019-07-03 09:08:54 +02:00
unless ( my $ return = do $ self - > { statefile_dir } . '/' . $ self - > { statefile } ) {
2014-05-09 22:55:13 +02:00
# File is corrupted surely. We'll reset it
return 0 ;
#if ($@) {
# $self->{output}->add_option_msg(short_msg => "Couldn't parse '" . $self->{statefile_dir} . "/" . $self->{statefile} . "': $@");
# $self->{output}->option_exit();
#}
#unless (defined($return)) {
# $self->{output}->add_option_msg(short_msg => "Couldn't do '" . $self->{statefile_dir} . "/" . $self->{statefile} . "': $!");
# $self->{output}->option_exit();
#}
#unless ($return) {
# $self->{output}->add_option_msg(short_msg => "Couldn't run '" . $self->{statefile_dir} . "/" . $self->{statefile} . "': $!");
# $self->{output}->option_exit();
2013-12-13 16:14:12 +01:00
}
2014-05-09 22:55:13 +02:00
$ self - > { datas } = $ datas ;
$ datas = { } ;
2013-12-13 16:14:12 +01:00
}
return 1 ;
}
sub get_string_content {
my ( $ self , % options ) = @ _ ;
return Data::Dumper:: Dumper ( $ self - > { datas } ) ;
}
sub get {
my ( $ self , % options ) = @ _ ;
if ( defined ( $ self - > { datas } - > { $ options { name } } ) ) {
return $ self - > { datas } - > { $ options { name } } ;
}
return undef ;
}
sub write {
my ( $ self , % options ) = @ _ ;
2014-05-09 22:55:13 +02:00
if ( $ self - > { memcached_ok } == 1 ) {
2020-02-19 11:52:30 +01:00
Memcached::libmemcached:: memcached_set (
$ self - > { memcached } , $ self - > { statefile_dir } . '/' . $ self - > { statefile } ,
Data::Dumper - > Dump ( [ $ options { data } ] , [ 'datas' ] ) , $ self - > { memexpiration }
) ;
2013-12-13 16:14:12 +01:00
if ( defined ( $ self - > { memcached } - > errstr ) && $ self - > { memcached } - > errstr =~ /^SUCCESS$/i ) {
return ;
}
}
2017-11-22 13:10:07 +01:00
if ( defined ( $ self - > { redis_cnx } ) ) {
2020-02-19 11:52:30 +01:00
return if ( defined ( $ self - > { redis_cnx } - > set (
$ self - > { statefile_dir } . '/' . $ self - > { statefile } , Data::Dumper - > Dump ( [ $ options { data } ] , [ 'datas' ] ) ,
'EX' , $ self - > { memexpiration } ) )
) ;
2017-11-22 13:10:07 +01:00
}
2019-07-03 09:08:54 +02:00
open FILE , '>' , $ self - > { statefile_dir } . '/' . $ self - > { statefile } ;
2014-05-09 22:55:13 +02:00
if ( $ self - > { storable } == 1 ) {
Storable:: store_fd ( $ options { data } , * FILE ) ;
} else {
2019-07-03 09:08:54 +02:00
print FILE Data::Dumper - > Dump ( [ $ options { data } ] , [ 'datas' ] ) ;
2014-05-09 22:55:13 +02:00
}
2013-12-13 16:14:12 +01:00
close FILE ;
}
1 ;
__END__
= head1 NAME
Statefile class
= head1 SYNOPSIS
-
= head1 RETENTION OPTIONS
= over 8
= item B <--memcached>
Memcached server to use ( only one server ) .
2017-11-22 13:10:07 +01:00
= item B <--redis-server>
2020-06-15 09:20:24 +02:00
Redis server to use ( only one server ) . SYntax: address [ : port ]
2017-11-22 13:10:07 +01:00
= item B <--redis-attribute>
Set Redis Options ( - - redis - attribute = "cnx_timeout=5" ) .
2019-07-03 09:08:54 +02:00
= item B <--redis-db>
Set Redis database index .
2020-06-15 09:20:24 +02:00
= item B <--failback-file>
Failback on a local file if redis connection failed .
2017-11-22 13:10:07 +01:00
= item B <--memexpiration>
Time to keep data in seconds ( Default: 86400 ) .
2013-12-13 16:14:12 +01:00
= item B <--statefile-dir>
Directory for statefile ( Default: '/var/lib/centreon/centplugins' ) .
2015-02-16 10:15:55 +01:00
= item B <--statefile-suffix>
Add a suffix for the statefile name ( Default: '' ) .
2014-02-21 11:31:20 +01:00
= item B <--statefile-concat-cwd>
Concat current working directory with option '--statefile-dir' .
Useful on Windows when plugin is compiled .
2014-05-09 22:55:13 +02:00
= item B <--statefile-storable>
Use Perl Module 'Storable' ( instead Data:: Dumper ) to store datas .
2013-12-13 16:14:12 +01:00
= back
= head1 DESCRIPTION
B <statefile> .
= cut