From dd6ff6b79c7d4b756f3f48f8cfddf9fd7bafc83e Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Thu, 20 Dec 2018 11:57:56 +0100 Subject: [PATCH 01/23] Fix mssql version bug --- centreon-plugins/centreon/plugins/dbi.pm | 8 ++++- centreon-plugins/database/mssql/dbi.pm | 41 +++++++++++++++++++++++ centreon-plugins/database/mssql/plugin.pm | 1 + 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 centreon-plugins/database/mssql/dbi.pm diff --git a/centreon-plugins/centreon/plugins/dbi.pm b/centreon-plugins/centreon/plugins/dbi.pm index 5c636307b..05d0cdb7f 100644 --- a/centreon-plugins/centreon/plugins/dbi.pm +++ b/centreon-plugins/centreon/plugins/dbi.pm @@ -190,6 +190,12 @@ sub is_version_minimum { return 1; } + +sub set_version { + my ($self) = @_; + + $self->{version} = $self->{instance}->get_info(18); # SQL_DBMS_VER +} sub connect { my ($self, %options) = @_; @@ -220,7 +226,7 @@ sub connect { return (-1, $err_msg); } - $self->{version} = $self->{instance}->get_info(18); # SQL_DBMS_VER + $self->set_version(); return 0; } diff --git a/centreon-plugins/database/mssql/dbi.pm b/centreon-plugins/database/mssql/dbi.pm new file mode 100644 index 000000000..bb5258413 --- /dev/null +++ b/centreon-plugins/database/mssql/dbi.pm @@ -0,0 +1,41 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 database::mssql::dbi; + +use base qw(centreon::plugins::dbi); + +use strict; +use warnings; + +sub set_version { + my ($self) = @_; + + $self->{version} = $self->{instance}->get_info(18); # SQL_DBMS_VER + return if (defined($self->{version}) && $self->{version} ne ''); + + $self->query(query => q{select SERVERPROPERTY('productversion') as product_version}); + my $row = $self->fetchrow_hashref(); + $self->{version} = $row->{product_version}; +} + +1; + +__END__ \ No newline at end of file diff --git a/centreon-plugins/database/mssql/plugin.pm b/centreon-plugins/database/mssql/plugin.pm index 64dad1ca4..2d653a920 100644 --- a/centreon-plugins/database/mssql/plugin.pm +++ b/centreon-plugins/database/mssql/plugin.pm @@ -48,6 +48,7 @@ sub new { 'transactions' => 'database::mssql::mode::transactions', ); + $self->{sql_modes}{dbi} = 'database::mssql::dbi'; return $self; } From 52b78fd7e6299dcd9c2c6a1c56764e7fc480afd1 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Thu, 20 Dec 2018 12:03:50 +0100 Subject: [PATCH 02/23] + Fix mssql version bug --- centreon-plugins/centreon/plugins/dbi.pm | 7 ++++++- centreon-plugins/database/mssql/dbi.pm | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/centreon-plugins/centreon/plugins/dbi.pm b/centreon-plugins/centreon/plugins/dbi.pm index 05d0cdb7f..560df8a1e 100644 --- a/centreon-plugins/centreon/plugins/dbi.pm +++ b/centreon-plugins/centreon/plugins/dbi.pm @@ -262,18 +262,23 @@ sub fetchrow_hashref { sub query { my ($self, %options) = @_; + my $continue_error = defined($options{continue_error}) && $options{continue_error} == 1 ? 1 : 0; $self->{statement_handle} = $self->{instance}->prepare($options{query}); if (!defined($self->{statement_handle})) { + return 1 if ($continue_error == 1); $self->{output}->add_option_msg(short_msg => "Cannot execute query: " . $self->{instance}->errstr); $self->{output}->option_exit(exit_litteral => $self->{sql_errors_exit}); } my $rv = $self->{statement_handle}->execute; if (!$rv) { + return 1 if ($continue_error == 1); $self->{output}->add_option_msg(short_msg => "Cannot execute query: " . $self->{statement_handle}->errstr); $self->{output}->option_exit(exit_litteral => $self->{sql_errors_exit}); - } + } + + return 0; } 1; diff --git a/centreon-plugins/database/mssql/dbi.pm b/centreon-plugins/database/mssql/dbi.pm index bb5258413..6d70d3231 100644 --- a/centreon-plugins/database/mssql/dbi.pm +++ b/centreon-plugins/database/mssql/dbi.pm @@ -31,7 +31,7 @@ sub set_version { $self->{version} = $self->{instance}->get_info(18); # SQL_DBMS_VER return if (defined($self->{version}) && $self->{version} ne ''); - $self->query(query => q{select SERVERPROPERTY('productversion') as product_version}); + return if ($self->query(query => q{select SERVERPROPERTY('productversion') as product_version}, continue_error => 1) == 1); my $row = $self->fetchrow_hashref(); $self->{version} = $row->{product_version}; } From 669374f46d9eb23930bee6924340b436e5db283b Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Thu, 20 Dec 2018 12:05:39 +0100 Subject: [PATCH 03/23] fix quantum dxi --- centreon-plugins/storage/quantum/dxi/ssh/mode/compaction.pm | 2 +- centreon-plugins/storage/quantum/dxi/ssh/mode/diskusage.pm | 2 +- centreon-plugins/storage/quantum/dxi/ssh/mode/health.pm | 6 +++++- .../storage/quantum/dxi/ssh/mode/hostbusadapterstatus.pm | 4 ++++ centreon-plugins/storage/quantum/dxi/ssh/mode/memory.pm | 2 +- centreon-plugins/storage/quantum/dxi/ssh/mode/network.pm | 6 +++++- .../storage/quantum/dxi/ssh/mode/reclamation.pm | 2 +- centreon-plugins/storage/quantum/dxi/ssh/mode/reduction.pm | 2 +- .../storage/quantum/dxi/ssh/mode/storagearraystatus.pm | 6 +++++- .../storage/quantum/dxi/ssh/mode/systemstatus.pm | 6 +++++- centreon-plugins/storage/quantum/dxi/ssh/mode/throughput.pm | 2 +- centreon-plugins/storage/quantum/dxi/ssh/plugin.pm | 2 +- 12 files changed, 31 insertions(+), 11 deletions(-) diff --git a/centreon-plugins/storage/quantum/dxi/ssh/mode/compaction.pm b/centreon-plugins/storage/quantum/dxi/ssh/mode/compaction.pm index 647f36a2a..ff1eadb65 100644 --- a/centreon-plugins/storage/quantum/dxi/ssh/mode/compaction.pm +++ b/centreon-plugins/storage/quantum/dxi/ssh/mode/compaction.pm @@ -193,7 +193,7 @@ sub check_options { $self->SUPER::check_options(%options); if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { - $self->{option_results}->{remote} = 1; + $self->{option_results}->{remote} = 1; } $instance_mode = $self; diff --git a/centreon-plugins/storage/quantum/dxi/ssh/mode/diskusage.pm b/centreon-plugins/storage/quantum/dxi/ssh/mode/diskusage.pm index 95becbad1..81eeb036d 100644 --- a/centreon-plugins/storage/quantum/dxi/ssh/mode/diskusage.pm +++ b/centreon-plugins/storage/quantum/dxi/ssh/mode/diskusage.pm @@ -242,7 +242,7 @@ sub check_options { $self->SUPER::check_options(%options); if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { - $self->{option_results}->{remote} = 1; + $self->{option_results}->{remote} = 1; } $instance_mode = $self; diff --git a/centreon-plugins/storage/quantum/dxi/ssh/mode/health.pm b/centreon-plugins/storage/quantum/dxi/ssh/mode/health.pm index 4d22c8d09..d4e170632 100644 --- a/centreon-plugins/storage/quantum/dxi/ssh/mode/health.pm +++ b/centreon-plugins/storage/quantum/dxi/ssh/mode/health.pm @@ -119,7 +119,7 @@ sub new { sub change_macros { my ($self, %options) = @_; - foreach ('warning_status', 'critical_status') { + foreach (('warning_status', 'critical_status')) { if (defined($self->{option_results}->{$_})) { $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; } @@ -129,6 +129,10 @@ sub change_macros { sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); + + if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { + $self->{option_results}->{remote} = 1; + } $instance_mode = $self; $self->change_macros(); diff --git a/centreon-plugins/storage/quantum/dxi/ssh/mode/hostbusadapterstatus.pm b/centreon-plugins/storage/quantum/dxi/ssh/mode/hostbusadapterstatus.pm index 50227c723..11bec450e 100644 --- a/centreon-plugins/storage/quantum/dxi/ssh/mode/hostbusadapterstatus.pm +++ b/centreon-plugins/storage/quantum/dxi/ssh/mode/hostbusadapterstatus.pm @@ -128,6 +128,10 @@ sub change_macros { sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); + + if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { + $self->{option_results}->{remote} = 1; + } $instance_mode = $self; $self->change_macros(); diff --git a/centreon-plugins/storage/quantum/dxi/ssh/mode/memory.pm b/centreon-plugins/storage/quantum/dxi/ssh/mode/memory.pm index a407f51c4..dbce15d88 100644 --- a/centreon-plugins/storage/quantum/dxi/ssh/mode/memory.pm +++ b/centreon-plugins/storage/quantum/dxi/ssh/mode/memory.pm @@ -152,7 +152,7 @@ sub check_options { $self->SUPER::check_options(%options); if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { - $self->{option_results}->{remote} = 1; + $self->{option_results}->{remote} = 1; } $instance_mode = $self; diff --git a/centreon-plugins/storage/quantum/dxi/ssh/mode/network.pm b/centreon-plugins/storage/quantum/dxi/ssh/mode/network.pm index fc8f5dc05..d57163ebf 100644 --- a/centreon-plugins/storage/quantum/dxi/ssh/mode/network.pm +++ b/centreon-plugins/storage/quantum/dxi/ssh/mode/network.pm @@ -119,7 +119,7 @@ sub new { sub change_macros { my ($self, %options) = @_; - foreach ('warning_status', 'critical_status') { + foreach (('warning_status', 'critical_status')) { if (defined($self->{option_results}->{$_})) { $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; } @@ -129,6 +129,10 @@ sub change_macros { sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); + + if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { + $self->{option_results}->{remote} = 1; + } $instance_mode = $self; $self->change_macros(); diff --git a/centreon-plugins/storage/quantum/dxi/ssh/mode/reclamation.pm b/centreon-plugins/storage/quantum/dxi/ssh/mode/reclamation.pm index e74d3837b..e53bbc21e 100644 --- a/centreon-plugins/storage/quantum/dxi/ssh/mode/reclamation.pm +++ b/centreon-plugins/storage/quantum/dxi/ssh/mode/reclamation.pm @@ -202,7 +202,7 @@ sub check_options { $self->SUPER::check_options(%options); if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { - $self->{option_results}->{remote} = 1; + $self->{option_results}->{remote} = 1; } $instance_mode = $self; diff --git a/centreon-plugins/storage/quantum/dxi/ssh/mode/reduction.pm b/centreon-plugins/storage/quantum/dxi/ssh/mode/reduction.pm index 3b63668b5..a67a14741 100644 --- a/centreon-plugins/storage/quantum/dxi/ssh/mode/reduction.pm +++ b/centreon-plugins/storage/quantum/dxi/ssh/mode/reduction.pm @@ -217,7 +217,7 @@ sub check_options { $self->SUPER::check_options(%options); if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { - $self->{option_results}->{remote} = 1; + $self->{option_results}->{remote} = 1; } $instance_mode = $self; diff --git a/centreon-plugins/storage/quantum/dxi/ssh/mode/storagearraystatus.pm b/centreon-plugins/storage/quantum/dxi/ssh/mode/storagearraystatus.pm index d12ef425d..715a77f8e 100644 --- a/centreon-plugins/storage/quantum/dxi/ssh/mode/storagearraystatus.pm +++ b/centreon-plugins/storage/quantum/dxi/ssh/mode/storagearraystatus.pm @@ -118,7 +118,7 @@ sub new { sub change_macros { my ($self, %options) = @_; - foreach ('warning_status', 'critical_status') { + foreach (('warning_status', 'critical_status')) { if (defined($self->{option_results}->{$_})) { $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; } @@ -128,6 +128,10 @@ sub change_macros { sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); + + if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { + $self->{option_results}->{remote} = 1; + } $instance_mode = $self; $self->change_macros(); diff --git a/centreon-plugins/storage/quantum/dxi/ssh/mode/systemstatus.pm b/centreon-plugins/storage/quantum/dxi/ssh/mode/systemstatus.pm index f329e4bfb..0f637a965 100644 --- a/centreon-plugins/storage/quantum/dxi/ssh/mode/systemstatus.pm +++ b/centreon-plugins/storage/quantum/dxi/ssh/mode/systemstatus.pm @@ -120,7 +120,7 @@ sub new { sub change_macros { my ($self, %options) = @_; - foreach ('warning_status', 'critical_status') { + foreach (('warning_status', 'critical_status')) { if (defined($self->{option_results}->{$_})) { $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; } @@ -130,6 +130,10 @@ sub change_macros { sub check_options { my ($self, %options) = @_; $self->SUPER::check_options(%options); + + if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { + $self->{option_results}->{remote} = 1; + } $instance_mode = $self; $self->change_macros(); diff --git a/centreon-plugins/storage/quantum/dxi/ssh/mode/throughput.pm b/centreon-plugins/storage/quantum/dxi/ssh/mode/throughput.pm index c13c69596..f5da1c4cb 100644 --- a/centreon-plugins/storage/quantum/dxi/ssh/mode/throughput.pm +++ b/centreon-plugins/storage/quantum/dxi/ssh/mode/throughput.pm @@ -136,7 +136,7 @@ sub check_options { $self->SUPER::check_options(%options); if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') { - $self->{option_results}->{remote} = 1; + $self->{option_results}->{remote} = 1; } $instance_mode = $self; diff --git a/centreon-plugins/storage/quantum/dxi/ssh/plugin.pm b/centreon-plugins/storage/quantum/dxi/ssh/plugin.pm index ed46d1793..da00b5bb8 100644 --- a/centreon-plugins/storage/quantum/dxi/ssh/plugin.pm +++ b/centreon-plugins/storage/quantum/dxi/ssh/plugin.pm @@ -33,8 +33,8 @@ sub new { %{$self->{modes}} = ( 'compaction' => 'storage::quantum::dxi::ssh::mode::compaction', 'disk-usage' => 'storage::quantum::dxi::ssh::mode::diskusage', - 'hostbus-adapter-status' => 'storage::quantum::dxi::ssh::mode::hostbusadapterstatus', 'health' => 'storage::quantum::dxi::ssh::mode::health', + 'hostbus-adapter-status' => 'storage::quantum::dxi::ssh::mode::hostbusadapterstatus', 'memory' => 'storage::quantum::dxi::ssh::mode::memory', 'network' => 'storage::quantum::dxi::ssh::mode::network', 'reclamation' => 'storage::quantum::dxi::ssh::mode::reclamation', From 2574dd65f70bc846dd2c2e97ea511edd828f2950 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Thu, 20 Dec 2018 13:11:44 +0100 Subject: [PATCH 04/23] + Fix bug win real swap snmp --- centreon-plugins/os/windows/snmp/mode/swap.pm | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/centreon-plugins/os/windows/snmp/mode/swap.pm b/centreon-plugins/os/windows/snmp/mode/swap.pm index efcf14a33..0fec3013b 100644 --- a/centreon-plugins/os/windows/snmp/mode/swap.pm +++ b/centreon-plugins/os/windows/snmp/mode/swap.pm @@ -90,22 +90,24 @@ sub run { my $oid_hrStorageSize = '.1.3.6.1.2.1.25.2.3.1.5'; my $oid_hrStorageUsed = '.1.3.6.1.2.1.25.2.3.1.6'; - my $physicalSize = 0; - my $physicalUsed = 0; + my ($physicalSize, $physicalUsed, $physicalUnits) = (0, 0, 0); if (defined($self->{option_results}->{real_swap})) { $self->{snmp}->load(oids => [$oid_hrStorageAllocationUnits, $oid_hrStorageSize, $oid_hrStorageUsed], instances => [$self->{physical_memory_id}]); $result = $self->{snmp}->get_leef(); $physicalSize = $result->{$oid_hrStorageSize . "." . $self->{physical_memory_id}}; $physicalUsed = $result->{$oid_hrStorageUsed . "." . $self->{physical_memory_id}}; + $physicalUnits = $result->{$oid_hrStorageAllocationUnits . "." . $self->{physical_memory_id}}; } $self->{snmp}->load(oids => [$oid_hrStorageAllocationUnits, $oid_hrStorageSize, $oid_hrStorageUsed], instances => [$self->{swap_memory_id}]); $result = $self->{snmp}->get_leef(); - my $swap_used = ($result->{$oid_hrStorageUsed . "." . $self->{swap_memory_id}} - $physicalUsed) * $result->{$oid_hrStorageAllocationUnits . "." . $self->{swap_memory_id}}; - my $total_size = ($result->{$oid_hrStorageSize . "." . $self->{swap_memory_id}} - $physicalSize) * $result->{$oid_hrStorageAllocationUnits . "." . $self->{swap_memory_id}}; + my $swap_used = ($result->{$oid_hrStorageUsed . "." . $self->{swap_memory_id}} * $result->{$oid_hrStorageAllocationUnits . "." . $self->{swap_memory_id}}) + - ($physicalUsed * $physicalUnits); + my $total_size = ($result->{$oid_hrStorageSize . "." . $self->{swap_memory_id}} * $result->{$oid_hrStorageAllocationUnits . "." . $self->{swap_memory_id}}) + - ($physicalSize * $physicalUnits); my $prct_used = $swap_used * 100 / $total_size; my $exit = $self->{perfdata}->threshold_check(value => $prct_used, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); From c039f9605958882e4c01da1c46e0c03067b0c7ac Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Thu, 20 Dec 2018 14:37:17 +0100 Subject: [PATCH 05/23] + Fix bug apc ats (#1127) --- .../hardware/ats/apc/snmp/mode/components/entity.pm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/centreon-plugins/hardware/ats/apc/snmp/mode/components/entity.pm b/centreon-plugins/hardware/ats/apc/snmp/mode/components/entity.pm index 731d14451..1a36a1fc7 100644 --- a/centreon-plugins/hardware/ats/apc/snmp/mode/components/entity.pm +++ b/centreon-plugins/hardware/ats/apc/snmp/mode/components/entity.pm @@ -68,8 +68,9 @@ sub check { $self->{components}->{entity}->{total}++; $self->{output}->output_add(long_msg => sprintf("entity '%s' status is '%s' [instance = %s]", - $mapping->{$_}->{label}, $result->{$_}, $mapping->{$_}->{label})); + $mapping->{$_}->{label}, defined($result->{$_}) ? $result->{$_} : 'n/a', $mapping->{$_}->{label})); + next if (!defined($result->{$_})); my $exit = $self->get_severity(section => 'entity', instance => $mapping->{$_}->{label}, value => $result->{$_}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, From 0e01e33f74bd5d2fd1a191f8a70dbf957a6c859a Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Thu, 20 Dec 2018 23:11:33 +0100 Subject: [PATCH 06/23] + add comment in help --- centreon-plugins/os/windows/snmp/mode/swap.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/centreon-plugins/os/windows/snmp/mode/swap.pm b/centreon-plugins/os/windows/snmp/mode/swap.pm index 0fec3013b..62e949dba 100644 --- a/centreon-plugins/os/windows/snmp/mode/swap.pm +++ b/centreon-plugins/os/windows/snmp/mode/swap.pm @@ -152,8 +152,8 @@ Threshold critical in percent. =item B<--real-swap> -Use this option to remove physical -memory from Windows SNMP swap values. +Use this option to remove physical memory from Windows SNMP swap values. +Using that option can give wrong values (incoherent or negative). =back From 9c42f95974698f417dd26831f52d1523f9b46c60 Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Fri, 21 Dec 2018 14:57:41 +0100 Subject: [PATCH 07/23] add office 365 plugin --- .../microsoft/office365/custom/graphapi.pm | 287 +++++++++++++++++ .../office365/custom/managementapi.pm | 289 ++++++++++++++++++ .../management/mode/servicestatus.pm | 205 +++++++++++++ .../microsoft/office365/management/plugin.pm | 49 +++ 4 files changed, 830 insertions(+) create mode 100644 centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm create mode 100644 centreon-plugins/cloud/microsoft/office365/custom/managementapi.pm create mode 100644 centreon-plugins/cloud/microsoft/office365/management/mode/servicestatus.pm create mode 100644 centreon-plugins/cloud/microsoft/office365/management/plugin.pm diff --git a/centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm b/centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm new file mode 100644 index 000000000..42a2224ab --- /dev/null +++ b/centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm @@ -0,0 +1,287 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 cloud::microsoft::office365::custom::graphapi; + +use strict; +use warnings; +use DateTime; +use centreon::plugins::http; +use centreon::plugins::statefile; +use JSON::XS; +use URI::Encode; +use Digest::MD5 qw(md5_hex); + +sub new { + my ($class, %options) = @_; + my $self = {}; + bless $self, $class; + + if (!defined($options{output})) { + print "Class Custom: Need to specify 'output' argument.\n"; + exit 3; + } + if (!defined($options{options})) { + $options{output}->add_option_msg(short_msg => "Class Custom: Need to specify 'options' argument."); + $options{output}->option_exit(); + } + + if (!defined($options{noptions})) { + $options{options}->add_options(arguments => + { + "tenant:s" => { name => 'tenant' }, + "client-id:s" => { name => 'client_id' }, + "client-secret:s" => { name => 'client_secret' }, + "login-endpoint:s" => { name => 'login_endpoint' }, + "graph-endpoint:s" => { name => 'graph_endpoint' }, + "timeout:s" => { name => 'timeout' }, + "proxyurl:s" => { name => 'proxyurl' }, + }); + } + $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); + + $self->{output} = $options{output}; + $self->{mode} = $options{mode}; + $self->{http} = centreon::plugins::http->new(output => $self->{output}); + $self->{cache} = centreon::plugins::statefile->new(%options); + + return $self; +} + +sub set_options { + my ($self, %options) = @_; + + $self->{option_results} = $options{option_results}; +} + +sub set_defaults { + my ($self, %options) = @_; + + foreach (keys %{$options{default}}) { + if ($_ eq $self->{mode}) { + for (my $i = 0; $i < scalar(@{$options{default}->{$_}}); $i++) { + foreach my $opt (keys %{$options{default}->{$_}[$i]}) { + if (!defined($self->{option_results}->{$opt}[$i])) { + $self->{option_results}->{$opt}[$i] = $options{default}->{$_}[$i]->{$opt}; + } + } + } + } + } +} + +sub check_options { + my ($self, %options) = @_; + + $self->{tenant} = (defined($self->{option_results}->{tenant})) ? $self->{option_results}->{tenant} : undef; + $self->{client_id} = (defined($self->{option_results}->{client_id})) ? $self->{option_results}->{client_id} : undef; + $self->{client_secret} = (defined($self->{option_results}->{client_secret})) ? $self->{option_results}->{client_secret} : undef; + $self->{login_endpoint} = (defined($self->{option_results}->{login_endpoint})) ? $self->{option_results}->{login_endpoint} : 'https://login.microsoftonline.com'; + $self->{graph_endpoint} = (defined($self->{option_results}->{graph_endpoint})) ? $self->{option_results}->{graph_endpoint} : 'https://graph.microsoft.com'; + $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; + $self->{proxyurl} = (defined($self->{option_results}->{proxyurl})) ? $self->{option_results}->{proxyurl} : undef; + $self->{ssl_opt} = (defined($self->{option_results}->{ssl_opt})) ? $self->{option_results}->{ssl_opt} : undef; + + if (!defined($self->{tenant}) || $self->{tenant} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --tenant option."); + $self->{output}->option_exit(); + } + if (!defined($self->{client_id}) || $self->{client_id} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --client-id option."); + $self->{output}->option_exit(); + } + if (!defined($self->{client_secret}) || $self->{client_secret} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --client-secret option."); + $self->{output}->option_exit(); + } + + $self->{cache}->check_options(option_results => $self->{option_results}); + + return 0; +} + +sub build_options_for_httplib { + my ($self, %options) = @_; + + $self->{option_results}->{timeout} = $self->{timeout}; + $self->{option_results}->{proxyurl} = $self->{proxyurl}; + $self->{option_results}->{ssl_opt} = $self->{ssl_opt}; + $self->{option_results}->{warning_status} = ''; + $self->{option_results}->{critical_status} = ''; + $self->{option_results}->{unknown_status} = ''; +} + +sub settings { + my ($self, %options) = @_; + + $self->build_options_for_httplib(); + $self->{http}->add_header(key => 'Accept', value => 'application/json'); + $self->{http}->add_header(key => 'Content-Type', value => 'application/x-www-form-urlencoded'); + if (defined($self->{access_token})) { + $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{access_token}); + } + $self->{http}->set_options(%{$self->{option_results}}); +} + +sub get_access_token { + my ($self, %options) = @_; + + my $has_cache_file = $options{statefile}->read(statefile => 'office365_graphapi_' . md5_hex($self->{tenant}) . '_' . md5_hex($self->{client_id})); + my $expires_on = $options{statefile}->get(name => 'expires_on'); + my $access_token = $options{statefile}->get(name => 'access_token'); + + if ($has_cache_file == 0 || !defined($access_token) || (($expires_on - time()) < 10)) { + my $uri = URI::Encode->new({encode_reserved => 1}); + my $encoded_graph_endpoint = $uri->encode($self->{graph_endpoint} . '/.default'); + my $post_data = 'grant_type=client_credentials' . + '&client_id=' . $self->{client_id} . + '&client_secret=' . $self->{client_secret} . + '&scope=' . $encoded_graph_endpoint; + + $self->settings(); + + my $content = $self->{http}->request(method => 'POST', query_form_post => $post_data, + full_url => $self->{login_endpoint} . '/' . $self->{tenant} . '/oauth2/v2.0/token', + hostname => ''); + + my $decoded; + eval { + $decoded = JSON::XS->new->utf8->decode($content); + }; + if ($@) { + $self->{output}->output_add(long_msg => $content, debug => 1); + $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); + $self->{output}->option_exit(); + } + if (defined($decoded->{error})) { + $self->{output}->output_add(long_msg => "Error message : " . $decoded->{error_description}, debug => 1); + $self->{output}->add_option_msg(short_msg => "Login endpoint API return error code '" . $decoded->{error} . "' (add --debug option for detailed message)"); + $self->{output}->option_exit(); + } + + $access_token = $decoded->{access_token}; + my $datas = { last_timestamp => time(), access_token => $decoded->{access_token}, expires_on => time() + $decoded->{expires_in} }; + $options{statefile}->write(data => $datas); + } + + return $access_token; +} + +sub request_api { + my ($self, %options) = @_; + + if (!defined($self->{access_token})) { + $self->{access_token} = $self->get_access_token(statefile => $self->{cache}); + } + + $self->settings(); + + my $content = $self->{http}->request(%options); + + my $decoded; + eval { + $decoded = JSON::XS->new->utf8->decode($content); + }; + if ($@) { + $self->{output}->output_add(long_msg => $content, debug => 1); + $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); + $self->{output}->option_exit(); + } + if (defined($decoded->{error})) { + $self->{output}->output_add(long_msg => "Error message : " . $decoded->{error}->{message}, debug => 1); + $self->{output}->add_option_msg(short_msg => "Graph endpoint API return error code '" . $decoded->{error}->{code} . "' (add --debug option for detailed message)"); + $self->{output}->option_exit(); + } + + return $decoded; +} + +sub office_get_active_users_set_url { + my ($self, %options) = @_; + + my $url = $self->{graph_endpoint} . "/v1.0/reports/getOffice365ActiveUserDetail(period='D7')"; + + return $url; +} + +sub office_get_active_users { + my ($self, %options) = @_; + + my $full_url = $self->office_get_active_users_set_url(%options); + my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); + + return $response; +} + +1; + +__END__ + +=head1 NAME + +Microsoft Office 365 Graph API + +=head1 REST API OPTIONS + +Microsoft Office 365 Graph API + +To connect to the Office 365 Graph API, you must register an application. + +# Follow the 'How-to guide' in https://docs.microsoft.com/en-us/graph/auth-register-app-v2?view=graph-rest-1.0 + +This custom mode is using the 'OAuth 2.0 Client Credentials Grant Flow'. + +=over 8 + +=item B<--tenant> + +Set Office 365 tenant ID. + +=item B<--client-id> + +Set Office 365 client ID. + +=item B<--client-secret> + +Set Office 365 client secret. + +=item B<--login-endpoint> + +Set Office 365 login endpoint URL (Default: 'https://login.microsoftonline.com') + +=item B<--graph-endpoint> + +Set Office 365 graph endpoint URL (Default: 'https://graph.microsoft.com') + +=item B<--timeout> + +Set timeout in seconds (Default: 10). + +=item B<--proxyurl> + +Proxy URL if any + +=back + +=head1 DESCRIPTION + +B. + +=cut diff --git a/centreon-plugins/cloud/microsoft/office365/custom/managementapi.pm b/centreon-plugins/cloud/microsoft/office365/custom/managementapi.pm new file mode 100644 index 000000000..fdbb11491 --- /dev/null +++ b/centreon-plugins/cloud/microsoft/office365/custom/managementapi.pm @@ -0,0 +1,289 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 cloud::microsoft::office365::custom::managementapi; + +use strict; +use warnings; +use DateTime; +use centreon::plugins::http; +use centreon::plugins::statefile; +use JSON::XS; +use URI::Encode; +use Digest::MD5 qw(md5_hex); + +sub new { + my ($class, %options) = @_; + my $self = {}; + bless $self, $class; + + if (!defined($options{output})) { + print "Class Custom: Need to specify 'output' argument.\n"; + exit 3; + } + if (!defined($options{options})) { + $options{output}->add_option_msg(short_msg => "Class Custom: Need to specify 'options' argument."); + $options{output}->option_exit(); + } + + if (!defined($options{noptions})) { + $options{options}->add_options(arguments => + { + "tenant:s" => { name => 'tenant' }, + "client-id:s" => { name => 'client_id' }, + "client-secret:s" => { name => 'client_secret' }, + "login-endpoint:s" => { name => 'login_endpoint' }, + "management-endpoint:s" => { name => 'management_endpoint' }, + "timeout:s" => { name => 'timeout' }, + "proxyurl:s" => { name => 'proxyurl' }, + }); + } + $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); + + $self->{output} = $options{output}; + $self->{mode} = $options{mode}; + $self->{http} = centreon::plugins::http->new(output => $self->{output}); + $self->{cache} = centreon::plugins::statefile->new(%options); + + return $self; +} + +sub set_options { + my ($self, %options) = @_; + + $self->{option_results} = $options{option_results}; +} + +sub set_defaults { + my ($self, %options) = @_; + + foreach (keys %{$options{default}}) { + if ($_ eq $self->{mode}) { + for (my $i = 0; $i < scalar(@{$options{default}->{$_}}); $i++) { + foreach my $opt (keys %{$options{default}->{$_}[$i]}) { + if (!defined($self->{option_results}->{$opt}[$i])) { + $self->{option_results}->{$opt}[$i] = $options{default}->{$_}[$i]->{$opt}; + } + } + } + } + } +} + +sub check_options { + my ($self, %options) = @_; + + $self->{tenant} = (defined($self->{option_results}->{tenant})) ? $self->{option_results}->{tenant} : undef; + $self->{client_id} = (defined($self->{option_results}->{client_id})) ? $self->{option_results}->{client_id} : undef; + $self->{client_secret} = (defined($self->{option_results}->{client_secret})) ? $self->{option_results}->{client_secret} : undef; + $self->{login_endpoint} = (defined($self->{option_results}->{login_endpoint})) ? $self->{option_results}->{login_endpoint} : 'https://login.windows.net'; + $self->{management_endpoint} = (defined($self->{option_results}->{management_endpoint})) ? $self->{option_results}->{management_endpoint} : 'https://manage.office.com'; + $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; + $self->{proxyurl} = (defined($self->{option_results}->{proxyurl})) ? $self->{option_results}->{proxyurl} : undef; + $self->{ssl_opt} = (defined($self->{option_results}->{ssl_opt})) ? $self->{option_results}->{ssl_opt} : undef; + + if (!defined($self->{tenant}) || $self->{tenant} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --tenant option."); + $self->{output}->option_exit(); + } + if (!defined($self->{client_id}) || $self->{client_id} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --client-id option."); + $self->{output}->option_exit(); + } + if (!defined($self->{client_secret}) || $self->{client_secret} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --client-secret option."); + $self->{output}->option_exit(); + } + + $self->{cache}->check_options(option_results => $self->{option_results}); + + return 0; +} + +sub build_options_for_httplib { + my ($self, %options) = @_; + + $self->{option_results}->{timeout} = $self->{timeout}; + $self->{option_results}->{proxyurl} = $self->{proxyurl}; + $self->{option_results}->{ssl_opt} = $self->{ssl_opt}; + $self->{option_results}->{warning_status} = ''; + $self->{option_results}->{critical_status} = ''; + $self->{option_results}->{unknown_status} = ''; +} + +sub settings { + my ($self, %options) = @_; + + $self->build_options_for_httplib(); + $self->{http}->add_header(key => 'Accept', value => 'application/json'); + $self->{http}->add_header(key => 'Content-Type', value => 'application/x-www-form-urlencoded'); + if (defined($self->{access_token})) { + $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{access_token}); + } + $self->{http}->set_options(%{$self->{option_results}}); +} + +sub get_access_token { + my ($self, %options) = @_; + + my $has_cache_file = $options{statefile}->read(statefile => 'office365_managementapi_' . md5_hex($self->{tenant}) . '_' . md5_hex($self->{client_id})); + my $expires_on = $options{statefile}->get(name => 'expires_on'); + my $access_token = $options{statefile}->get(name => 'access_token'); + + if ($has_cache_file == 0 || !defined($access_token) || (($expires_on - time()) < 10)) { + my $uri = URI::Encode->new({encode_reserved => 1}); + my $encoded_management_endpoint = $uri->encode($self->{management_endpoint}); + my $post_data = 'grant_type=client_credentials' . + '&client_id=' . $self->{client_id} . + '&client_secret=' . $self->{client_secret} . + '&resource=' . $encoded_management_endpoint; + + $self->settings(); + + my $content = $self->{http}->request(method => 'POST', query_form_post => $post_data, + full_url => $self->{login_endpoint} . '/' . $self->{tenant} . '/oauth2/token?api-version=1.0', + hostname => ''); + + my $decoded; + eval { + $decoded = JSON::XS->new->utf8->decode($content); + }; + if ($@) { + $self->{output}->output_add(long_msg => $content, debug => 1); + $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); + $self->{output}->option_exit(); + } + if (defined($decoded->{error})) { + $self->{output}->output_add(long_msg => "Error message : " . $decoded->{error_description}, debug => 1); + $self->{output}->add_option_msg(short_msg => "Login endpoint API return error code '" . $decoded->{error} . "' (add --debug option for detailed message)"); + $self->{output}->option_exit(); + } + + $access_token = $decoded->{access_token}; + my $datas = { last_timestamp => time(), access_token => $decoded->{access_token}, expires_on => $decoded->{expires_on} }; + $options{statefile}->write(data => $datas); + } + + return $access_token; +} + +sub request_api { + my ($self, %options) = @_; + + if (!defined($self->{access_token})) { + $self->{access_token} = $self->get_access_token(statefile => $self->{cache}); + } + + $self->settings(); + + my $content = $self->{http}->request(%options); +use Data::Dumper; +print Dumper $content; + + my $decoded; + eval { + $decoded = JSON::XS->new->utf8->decode($content); + }; + if ($@) { + $self->{output}->output_add(long_msg => $content, debug => 1); + $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); + $self->{output}->option_exit(); + } + if (defined($decoded->{error})) { + $self->{output}->output_add(long_msg => "Error message : " . $decoded->{error}->{message}, debug => 1); + $self->{output}->add_option_msg(short_msg => "Management endpoint API return error code '" . $decoded->{error}->{code} . "' (add --debug option for detailed message)"); + $self->{output}->option_exit(); + } + + return $decoded; +} + +sub office_get_services_status_set_url { + my ($self, %options) = @_; + + my $url = $self->{management_endpoint} . "/api/v1.0/" . $self->{tenant} . "/ServiceComms/CurrentStatus"; + + return $url; +} + +sub office_get_services_status { + my ($self, %options) = @_; + + my $full_url = $self->office_get_services_status_set_url(%options); + my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); + + return $response; +} + +1; + +__END__ + +=head1 NAME + +Microsoft Office 365 Management API + +=head1 REST API OPTIONS + +Microsoft Office 365 Management API + +To connect to the Office 365 Management API, you must register an application. + +Follow the 'How-to guide' in https://docs.microsoft.com/en-us/office/office-365-management-api/get-started-with-office-365-management-apis#register-your-application-in-azure-ad + +This custom mode is using the 'OAuth 2.0 Client Credentials Grant Flow'. + +=over 8 + +=item B<--tenant> + +Set Office 365 tenant ID. + +=item B<--client-id> + +Set Office 365 client ID. + +=item B<--client-secret> + +Set Office 365 client secret. + +=item B<--login-endpoint> + +Set Office 365 login endpoint URL (Default: 'https://login.windows.net') + +=item B<--management-endpoint> + +Set Office 365 management endpoint URL (Default: 'https://manage.office.com') + +=item B<--timeout> + +Set timeout in seconds (Default: 10). + +=item B<--proxyurl> + +Proxy URL if any + +=back + +=head1 DESCRIPTION + +B. + +=cut diff --git a/centreon-plugins/cloud/microsoft/office365/management/mode/servicestatus.pm b/centreon-plugins/cloud/microsoft/office365/management/mode/servicestatus.pm new file mode 100644 index 000000000..42a98a592 --- /dev/null +++ b/centreon-plugins/cloud/microsoft/office365/management/mode/servicestatus.pm @@ -0,0 +1,205 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 cloud::microsoft::office365::management::mode::servicestatus; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = "status is '" . $self->{result_values}->{status} . "'"; + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; + return 0; +} + +sub prefix_service_output { + my ($self, %options) = @_; + + return "Service '" . $options{instance_value}->{service_name} . "' "; +} + +sub prefix_feature_output { + my ($self, %options) = @_; + + return "Service '" . $options{instance_value}->{service_name} . "' Feature '" . $options{instance_value}->{feature_name} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'services', type => 3, cb_prefix_output => 'prefix_service_output', message_multiple => 'All services status are ok', + counters => [ { name => 'features', type => 1, cb_prefix_output => 'prefix_feature_output', message_multiple => 'All features status are ok' } ] }, + ]; + + $self->{maps_counters}->{services} = [ + { label => 'status', set => { + key_values => [ { name => 'status' }, { name => 'service_name' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + ]; + $self->{maps_counters}->{features} = [ + { label => 'status', set => { + key_values => [ { name => 'status' }, { name => 'service_name' }, { name => 'feature_name' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-service-name:s" => { name => 'filter_service_name' }, + "filter-feature-name:s" => { name => 'filter_feature_name' }, + "warning-status:s" => { name => 'warning_status' }, + "critical-status:s" => { name => 'critical_status', default => '%{status} !~ /Normal/i' }, + }); + + return $self; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{services} = {}; + + my $results = $options{custom}->office_get_services_status(); + + foreach my $service (@{$results->{value}}) { + if (defined($self->{option_results}->{filter_service_name}) && $self->{option_results}->{filter_service_name} ne '' && + $service->{WorkloadDisplayName} !~ /$self->{option_results}->{filter_service_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $service->{WorkloadDisplayName} . "': no matching filter name.", debug => 1); + next; + } + $self->{services}->{$service->{Id}}->{service_name} = $service->{WorkloadDisplayName}; + $self->{services}->{$service->{Id}}->{status} = $service->{StatusDisplayName}; + foreach my $feature (@{$service->{FeatureStatus}}) { + if (defined($self->{option_results}->{filter_feature_name}) && $self->{option_results}->{filter_feature_name} ne '' && + $feature->{FeatureDisplayName} !~ /$self->{option_results}->{filter_feature_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $feature->{FeatureDisplayName} . "': no matching filter name.", debug => 1); + next; + } + $self->{services}->{$service->{Id}}->{features}->{$feature->{FeatureName}}->{service_name} = $service->{WorkloadDisplayName}; + $self->{services}->{$service->{Id}}->{features}->{$feature->{FeatureName}}->{feature_name} = $feature->{FeatureDisplayName}; + $self->{services}->{$service->{Id}}->{features}->{$feature->{FeatureName}}->{status} = $feature->{FeatureServiceStatusDisplayName}; + } + } + + if (scalar(keys %{$self->{services}}) <= 0) { + $self->{output}->add_option_msg(short_msg => 'No services found.'); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check services and features status. + +=over 8 + +=item B<--filter-*> + +Filter services and/or features. +Can be: 'service-name', 'feature-name' (can be a regexp). + +=item B<--warning-status> + +Set warning threshold for status (Default: ''). +Can used special variables like: %{service_name}, %{feature_name}, %{status} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{status} !~ /Normal/i'). +Can used special variables like: %{service_name}, %{feature_name}, %{status} + +=back + +=cut diff --git a/centreon-plugins/cloud/microsoft/office365/management/plugin.pm b/centreon-plugins/cloud/microsoft/office365/management/plugin.pm new file mode 100644 index 000000000..ad505c227 --- /dev/null +++ b/centreon-plugins/cloud/microsoft/office365/management/plugin.pm @@ -0,0 +1,49 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 cloud::microsoft::office365::management::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_custom); + +sub new { + my ( $class, %options ) = @_; + my $self = $class->SUPER::new( package => __PACKAGE__, %options ); + bless $self, $class; + + $self->{version} = '0.1'; + %{ $self->{modes} } = ( + 'service-status' => 'cloud::microsoft::office365::management::mode::servicestatus', + ); + + $self->{custom_modes}{managementapi} = 'cloud::microsoft::office365::custom::managementapi'; + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Microsoft Office 365. + +=cut From 0d8a4c80adb3346309bbeea89f70787c9738ff2f Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Fri, 21 Dec 2018 16:30:24 +0100 Subject: [PATCH 08/23] enh office 365 management plugin --- .../office365/custom/managementapi.pm | 19 ++- .../office365/management/mode/listservices.pm | 116 ++++++++++++++++++ .../microsoft/office365/management/plugin.pm | 1 + 3 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 centreon-plugins/cloud/microsoft/office365/management/mode/listservices.pm diff --git a/centreon-plugins/cloud/microsoft/office365/custom/managementapi.pm b/centreon-plugins/cloud/microsoft/office365/custom/managementapi.pm index fdbb11491..9248a57de 100644 --- a/centreon-plugins/cloud/microsoft/office365/custom/managementapi.pm +++ b/centreon-plugins/cloud/microsoft/office365/custom/managementapi.pm @@ -194,8 +194,6 @@ sub request_api { $self->settings(); my $content = $self->{http}->request(%options); -use Data::Dumper; -print Dumper $content; my $decoded; eval { @@ -232,6 +230,23 @@ sub office_get_services_status { return $response; } +sub office_list_services_set_url { + my ($self, %options) = @_; + + my $url = $self->{management_endpoint} . "/api/v1.0/" . $self->{tenant} . "/ServiceComms/Services"; + + return $url; +} + +sub office_list_services { + my ($self, %options) = @_; + + my $full_url = $self->office_list_services_set_url(%options); + my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); + + return $response; +} + 1; __END__ diff --git a/centreon-plugins/cloud/microsoft/office365/management/mode/listservices.pm b/centreon-plugins/cloud/microsoft/office365/management/mode/listservices.pm new file mode 100644 index 000000000..2bf31db06 --- /dev/null +++ b/centreon-plugins/cloud/microsoft/office365/management/mode/listservices.pm @@ -0,0 +1,116 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 cloud::microsoft::office365::management::mode::listservices; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $results = $options{custom}->office_list_services(); + + foreach my $service (@{$results->{value}}) { + if (defined($self->{option_results}->{filter_service_name}) && $self->{option_results}->{filter_service_name} ne '' && + $service->{WorkloadDisplayName} !~ /$self->{option_results}->{filter_service_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $service->{WorkloadDisplayName} . "': no matching filter name.", debug => 1); + next; + } + + $self->{services}->{$service->{Id}} = { + service_id => $service->{Id}, + service_name => $service->{DisplayName}, + } + } +} + +sub run { + my ($self, %options) = @_; + + $self->manage_selection(%options); + foreach my $service (sort keys %{$self->{services}}) { + $self->{output}->output_add(long_msg => sprintf("[service_id = %s] [service_name = %s]", + $self->{services}->{$service}->{service_id}, + $self->{services}->{$service}->{service_name})); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List services:'); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); + $self->{output}->exit(); +} + +sub disco_format { + my ($self, %options) = @_; + + $self->{output}->add_disco_format(elements => ['service_id', 'service_name']); +} + +sub disco_show { + my ($self, %options) = @_; + + $self->manage_selection(%options); + foreach my $service (sort keys %{$self->{services}}) { + $self->{output}->add_disco_entry( + service_id => $self->{services}->{$service}->{service_id}, + service_name => $self->{services}->{$service}->{service_name}, + ); + } +} + +1; + +__END__ + +=head1 MODE + +List services. + +=over 8 + +=item B<--filter-name> + +Filter service name (can be a regexp). + +=back + +=cut diff --git a/centreon-plugins/cloud/microsoft/office365/management/plugin.pm b/centreon-plugins/cloud/microsoft/office365/management/plugin.pm index ad505c227..d03f03345 100644 --- a/centreon-plugins/cloud/microsoft/office365/management/plugin.pm +++ b/centreon-plugins/cloud/microsoft/office365/management/plugin.pm @@ -31,6 +31,7 @@ sub new { $self->{version} = '0.1'; %{ $self->{modes} } = ( + 'list-services' => 'cloud::microsoft::office365::management::mode::listservices', 'service-status' => 'cloud::microsoft::office365::management::mode::servicestatus', ); From cd73b59730d1ee54a4a87742d5136f1c1a382778 Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Mon, 24 Dec 2018 14:51:55 +0100 Subject: [PATCH 09/23] add office365 sharepoint plugin --- .../office365/sharepoint/mode/listsites.pm | 123 +++++++++ .../office365/sharepoint/mode/siteusage.pm | 246 ++++++++++++++++++ .../microsoft/office365/sharepoint/plugin.pm | 50 ++++ 3 files changed, 419 insertions(+) create mode 100644 centreon-plugins/cloud/microsoft/office365/sharepoint/mode/listsites.pm create mode 100644 centreon-plugins/cloud/microsoft/office365/sharepoint/mode/siteusage.pm create mode 100644 centreon-plugins/cloud/microsoft/office365/sharepoint/plugin.pm diff --git a/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/listsites.pm b/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/listsites.pm new file mode 100644 index 000000000..e77fd270c --- /dev/null +++ b/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/listsites.pm @@ -0,0 +1,123 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 cloud::microsoft::office365::sharepoint::mode::listsites; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-url:s" => { name => 'filter_url' }, + "filter-id:s" => { name => 'filter_id' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $results = $options{custom}->office_get_sharepoint_site_usage(); + + foreach my $site (@{$results}) { + if (defined($self->{option_results}->{filter_url}) && $self->{option_results}->{filter_url} ne '' && + $site->{'Site URL'} !~ /$self->{option_results}->{filter_url}/) { + $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site URL'} . "': no matching filter name.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_id}) && $self->{option_results}->{filter_id} ne '' && + $site->{'Site Id'} !~ /$self->{option_results}->{filter_id}/) { + $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site Id'} . "': no matching filter name.", debug => 1); + next; + } + + $self->{sites}->{$site->{'Site Id'}} = { + id => $site->{'Site Id'}, + url => $site->{'Site URL'}, + } + } +} + +sub run { + my ($self, %options) = @_; + + $self->manage_selection(%options); + foreach my $site (sort keys %{$self->{sites}}) { + $self->{output}->output_add(long_msg => sprintf("[id = %s] [url = %s]", + $self->{sites}->{$site}->{id}, + $self->{sites}->{$site}->{url})); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List sites:'); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); + $self->{output}->exit(); +} + +sub disco_format { + my ($self, %options) = @_; + + $self->{output}->add_disco_format(elements => ['id', 'url']); +} + +sub disco_show { + my ($self, %options) = @_; + + $self->manage_selection(%options); + foreach my $site (sort keys %{$self->{sites}}) { + $self->{output}->add_disco_entry( + id => $self->{sites}->{$site}->{id}, + url => $self->{sites}->{$site}->{url}, + ); + } +} + +1; + +__END__ + +=head1 MODE + +List sites. + +=over 8 + +=item B<--filter-*> + +Filter sites. +Can be: 'url', 'id' (can be a regexp). + +=back + +=cut diff --git a/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/siteusage.pm b/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/siteusage.pm new file mode 100644 index 000000000..089c611ac --- /dev/null +++ b/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/siteusage.pm @@ -0,0 +1,246 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 cloud::microsoft::office365::sharepoint::mode::siteusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $instance_mode; + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + + $self->{output}->perfdata_add(label => 'used' . $extra_label, + unit => 'B', + value => $self->{result_values}->{used}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_usage_threshold { + my ($self, %options) = @_; + + my ($exit, $threshold_value); + $threshold_value = $self->{result_values}->{used}; + $threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free})); + if ($instance_mode->{option_results}->{units} eq '%') { + $threshold_value = $self->{result_values}->{prct_used}; + $threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free})); + } + $exit = $self->{perfdata}->threshold_check(value => $threshold_value, + threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, + { label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($free_value, $free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + my ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + + my $msg = sprintf("Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", + $total_value . " " . $total_unit, + $used_value . " " . $used_unit, $self->{result_values}->{prct_used}, + $free_value . " " . $free_unit, $self->{result_values}->{prct_free}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_id'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_storage_allocated'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_storage_used'}; + + if ($self->{result_values}->{total} != 0) { + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + } else { + $self->{result_values}->{free} = '0'; + $self->{result_values}->{prct_used} = '0'; + $self->{result_values}->{prct_free} = '0'; + } + + return 0; +} + +sub prefix_site_output { + my ($self, %options) = @_; + + return "Site '" . $options{instance_value}->{url} . "' [ID: " . $options{instance_value}->{id} . "] "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'sites', type => 1, cb_prefix_output => 'prefix_site_output', message_multiple => 'All sites usage are ok' }, + ]; + + $self->{maps_counters}->{sites} = [ + { label => 'usage', set => { + key_values => [ { name => 'storage_used' }, { name => 'storage_allocated' }, { name => 'url' }, { name => 'id' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + { label => 'file-count', set => { + key_values => [ { name => 'file_count' }, { name => 'url' }, { name => 'id' } ], + output_template => 'File Count: %d', + perfdatas => [ + { label => 'file_count', value => 'file_count_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'id_absolute' }, + ], + } + }, + { label => 'active-file-count', set => { + key_values => [ { name => 'active_file_count' }, { name => 'url' }, { name => 'id' } ], + output_template => 'Active File Count: %d', + perfdatas => [ + { label => 'active_file_count', value => 'active_file_count_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'id_absolute' }, + ], + } + }, + { label => 'visited-file-count', set => { + key_values => [ { name => 'visited_file_count' }, { name => 'url' }, { name => 'id' } ], + output_template => 'Visited File Count: %d', + perfdatas => [ + { label => 'visited_file_count', value => 'visited_file_count_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'id_absolute' }, + ], + } + }, + { label => 'page-view-count', set => { + key_values => [ { name => 'page_view_count' }, { name => 'url' }, { name => 'id' } ], + output_template => 'Page View Count: %d', + perfdatas => [ + { label => 'page_view_count', value => 'page_view_count_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'id_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-url:s" => { name => 'filter_url' }, + "filter-id:s" => { name => 'filter_id' }, + "units:s" => { name => 'units', default => '%' }, + "free" => { name => 'free' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{sites} = {}; + + my $results = $options{custom}->office_get_sharepoint_site_usage(); + + foreach my $site (@{$results}) { + if (defined($self->{option_results}->{filter_url}) && $self->{option_results}->{filter_url} ne '' && + $site->{'Site URL'} !~ /$self->{option_results}->{filter_url}/) { + $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site URL'} . "': no matching filter name.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_id}) && $self->{option_results}->{filter_id} ne '' && + $site->{'Site Id'} !~ /$self->{option_results}->{filter_id}/) { + $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site Id'} . "': no matching filter name.", debug => 1); + next; + } + + $self->{sites}->{$site->{'Site Id'}}->{id} = $site->{'Site Id'}; + $self->{sites}->{$site->{'Site Id'}}->{url} = $site->{'Site URL'}; + $self->{sites}->{$site->{'Site Id'}}->{file_count} = $site->{'File Count'}; + $self->{sites}->{$site->{'Site Id'}}->{active_file_count} = $site->{'Active File Count'}; + $self->{sites}->{$site->{'Site Id'}}->{visited_file_count} = $site->{'Visited Page Count'}; + $self->{sites}->{$site->{'Site Id'}}->{page_view_count} = $site->{'Page View Count'}; + $self->{sites}->{$site->{'Site Id'}}->{storage_used} = $site->{'Storage Used (Byte)'}; + $self->{sites}->{$site->{'Site Id'}}->{storage_allocated} = $site->{'Storage Allocated (Byte)'}; + } + + if (scalar(keys %{$self->{sites}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No entry found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check sites usage. + +(See link for details about metrics : +https://docs.microsoft.com/en-us/office365/admin/activity-reports/sharepoint-site-usage?view=o365-worldwide) + +=over 8 + +=item B<--filter-*> + +Filter sites. +Can be: 'url', 'id' (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'usage', 'file-count', 'active-file-count', +'visited-file-count', 'page-view-count'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'usage', 'file-count', 'active-file-count', +'visited-file-count', 'page-view-count'. + +=back + +=cut diff --git a/centreon-plugins/cloud/microsoft/office365/sharepoint/plugin.pm b/centreon-plugins/cloud/microsoft/office365/sharepoint/plugin.pm new file mode 100644 index 000000000..67ff64fa8 --- /dev/null +++ b/centreon-plugins/cloud/microsoft/office365/sharepoint/plugin.pm @@ -0,0 +1,50 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 cloud::microsoft::office365::sharepoint::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_custom); + +sub new { + my ( $class, %options ) = @_; + my $self = $class->SUPER::new( package => __PACKAGE__, %options ); + bless $self, $class; + + $self->{version} = '0.1'; + %{ $self->{modes} } = ( + 'list-sites' => 'cloud::microsoft::office365::sharepoint::mode::listsites', + 'site-usage' => 'cloud::microsoft::office365::sharepoint::mode::siteusage', + ); + + $self->{custom_modes}{graphapi} = 'cloud::microsoft::office365::custom::graphapi'; + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Microsoft Office 365. + +=cut From a464872341a21850cf13bcbb8718d99522ef3640 Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Mon, 24 Dec 2018 15:01:21 +0100 Subject: [PATCH 10/23] enh office365 graphapi custom mode --- .../microsoft/office365/custom/graphapi.pm | 75 +++++++++++++++++-- 1 file changed, 68 insertions(+), 7 deletions(-) diff --git a/centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm b/centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm index 42a2224ab..169a0ca0e 100644 --- a/centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm +++ b/centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm @@ -26,6 +26,8 @@ use DateTime; use centreon::plugins::http; use centreon::plugins::statefile; use JSON::XS; +use Text::CSV; +use Encode; use URI::Encode; use Digest::MD5 qw(md5_hex); @@ -184,7 +186,7 @@ sub get_access_token { return $access_token; } -sub request_api { +sub request_api_json { my ($self, %options) = @_; if (!defined($self->{access_token})) { @@ -213,20 +215,79 @@ sub request_api { return $decoded; } -sub office_get_active_users_set_url { +sub request_api_csv { my ($self, %options) = @_; - my $url = $self->{graph_endpoint} . "/v1.0/reports/getOffice365ActiveUserDetail(period='D7')"; + if (!defined($self->{access_token})) { + $self->{access_token} = $self->get_access_token(statefile => $self->{cache}); + } + + $self->settings(); + + my $content = $self->{http}->request(%options); + my $response = $self->{http}->get_response(); + + if ($response->code() != 200) { + my $decoded; + eval { + $decoded = JSON::XS->new->utf8->decode($content); + }; + if ($@) { + $self->{output}->output_add(long_msg => $content, debug => 1); + $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); + $self->{output}->option_exit(); + } + if (defined($decoded->{error})) { + $self->{output}->output_add(long_msg => "Error message : " . $decoded->{error}->{message}, debug => 1); + $self->{output}->add_option_msg(short_msg => "Graph endpoint API return error code '" . $decoded->{error}->{code} . "' (add --debug option for detailed message)"); + $self->{output}->option_exit(); + } + } + + my $decoded; + eval { + $decoded = decode('UTF-8', $content); + }; + if ($@) { + $self->{output}->output_add(long_msg => $content, debug => 1); + $self->{output}->add_option_msg(short_msg => "Cannot decode response: $@"); + $self->{output}->option_exit(); + } + $decoded =~ s/^\x{feff}//; + + my @rows; + eval { + open my $fh, '<', \$decoded; + my $csv = Text::CSV->new({ binary => 1 }); + $csv->column_names($csv->getline($fh)); + my $dummy = <$fh>; + while (my $row = $csv->getline_hr($fh)) { + push @rows, $row; + } + }; + if ($@) { + $self->{output}->output_add(long_msg => $content, debug => 1); + $self->{output}->add_option_msg(short_msg => "Cannot parse csv response: $@"); + $self->{output}->option_exit(); + } + + return \@rows; +} + +sub office_get_sharepoint_site_usage_set_url { + my ($self, %options) = @_; + + my $url = $self->{graph_endpoint} . "/v1.0/reports/getSharePointSiteUsageDetail(period='D7')"; return $url; } -sub office_get_active_users { +sub office_get_sharepoint_site_usage { my ($self, %options) = @_; - my $full_url = $self->office_get_active_users_set_url(%options); - my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => ''); - + my $full_url = $self->office_get_sharepoint_site_usage_set_url(%options); + my $response = $self->request_api_csv(method => 'GET', full_url => $full_url, hostname => ''); + return $response; } From bbe13d508c73db3b026d2c81114ec3cb8013b542 Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Mon, 24 Dec 2018 16:30:40 +0100 Subject: [PATCH 11/23] enh office365 sharepoint plugin --- .../office365/sharepoint/mode/siteusage.pm | 2 +- .../sharepoint/mode/usersactivity.pm | 175 ++++++++++++++++++ .../microsoft/office365/sharepoint/plugin.pm | 1 + 3 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 centreon-plugins/cloud/microsoft/office365/sharepoint/mode/usersactivity.pm diff --git a/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/siteusage.pm b/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/siteusage.pm index 089c611ac..8fe5af9ea 100644 --- a/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/siteusage.pm +++ b/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/siteusage.pm @@ -217,7 +217,7 @@ __END__ =head1 MODE -Check sites usage. +Check sites usage (reporting period over the last 7 days). (See link for details about metrics : https://docs.microsoft.com/en-us/office365/admin/activity-reports/sharepoint-site-usage?view=o365-worldwide) diff --git a/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/usersactivity.pm b/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/usersactivity.pm new file mode 100644 index 000000000..06b5db9ef --- /dev/null +++ b/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/usersactivity.pm @@ -0,0 +1,175 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 cloud::microsoft::office365::sharepoint::mode::usersactivity; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub prefix_user_output { + my ($self, %options) = @_; + + return "User '" . $options{instance_value}->{name} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'users', type => 1, cb_prefix_output => 'prefix_user_output', message_multiple => 'All users activity are ok' }, + ]; + + $self->{maps_counters}->{users} = [ + { label => 'viewed-edited-file-count', set => { + key_values => [ { name => 'viewed_edited_file_count' }, { name => 'name' } ], + output_template => 'Viewed or Edited File Count: %d', + perfdatas => [ + { label => 'viewed_edited_file_count', value => 'viewed_edited_file_count_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'name_absolute' }, + ], + } + }, + { label => 'file-count', set => { + key_values => [ { name => 'file_count' }, { name => 'name' } ], + output_template => 'File Count: %d', + perfdatas => [ + { label => 'file_count', value => 'file_count_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'name_absolute' }, + ], + } + }, + { label => 'shared-int-file-count', set => { + key_values => [ { name => 'shared_int_file_count' }, { name => 'name' } ], + output_template => 'Shared Internally File Count: %d', + perfdatas => [ + { label => 'shared_int_file_count', value => 'shared_int_file_count_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'name_absolute' }, + ], + } + }, + { label => 'shared-ext-file-count', set => { + key_values => [ { name => 'shared_ext_file_count' }, { name => 'name' } ], + output_template => 'Shared Externally File Count: %d', + perfdatas => [ + { label => 'shared_ext_file_count', value => 'shared_ext_file_count_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'name_absolute' }, + ], + } + }, + { label => 'visited-page-count', set => { + key_values => [ { name => 'visited_page_count' }, { name => 'name' } ], + output_template => 'Visited Page Count: %d', + perfdatas => [ + { label => 'visited_page_count', value => 'visited_page_count_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'name_absolute' }, + ], + } + }, + { label => 'last-activity', threshold => 0, set => { + key_values => [ { name => 'last_activity_date' }, { name => 'name' } ], + output_template => 'Last Activity: %s', + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-user:s" => { name => 'filter_user' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{users} = {}; + + my $results = $options{custom}->office_get_sharepoint_activity(); + use Data::Dumper; + print Dumper $results; + + foreach my $user (@{$results}) { + if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && + $user->{'User Principal Name'} !~ /$self->{option_results}->{filter_user}/) { + $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no matching filter name.", debug => 1); + next; + } + + $self->{users}->{$user->{'User Principal Name'}}->{name} = $user->{'User Principal Name'}; + $self->{users}->{$user->{'User Principal Name'}}->{viewed_edited_file_count} = $user->{'Viewed Or Edited File Count'}; + $self->{users}->{$user->{'User Principal Name'}}->{file_count} = $user->{'Synced File Count'}; + $self->{users}->{$user->{'User Principal Name'}}->{shared_int_file_count} = $user->{'Shared Internally File Count'}; + $self->{users}->{$user->{'User Principal Name'}}->{shared_ext_file_count} = $user->{'Shared Externally File Count'}; + $self->{users}->{$user->{'User Principal Name'}}->{visited_page_count} = $user->{'Visited Page Count'}; + $self->{users}->{$user->{'User Principal Name'}}->{last_activity_date} = $user->{'Last Activity Date'}; + } + + if (scalar(keys %{$self->{users}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No entry found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check users activity (reporting period over the last 7 days). + +(See link for details about metrics : +https://docs.microsoft.com/en-us/office365/admin/activity-reports/sharepoint-activity?view=o365-worldwide) + +=over 8 + +=item B<--filter-user> + +Filter users. + +=item B<--warning-*> + +Threshold warning. +Can be: 'viewed-edited-file-count', 'file-count', 'shared-int-file-count', +'shared-ext-file-count', 'visited-page-count'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'viewed-edited-file-count', 'file-count', 'shared-int-file-count', +'shared-ext-file-count', 'visited-page-count'. +=back + +=cut diff --git a/centreon-plugins/cloud/microsoft/office365/sharepoint/plugin.pm b/centreon-plugins/cloud/microsoft/office365/sharepoint/plugin.pm index 67ff64fa8..8a7d28078 100644 --- a/centreon-plugins/cloud/microsoft/office365/sharepoint/plugin.pm +++ b/centreon-plugins/cloud/microsoft/office365/sharepoint/plugin.pm @@ -33,6 +33,7 @@ sub new { %{ $self->{modes} } = ( 'list-sites' => 'cloud::microsoft::office365::sharepoint::mode::listsites', 'site-usage' => 'cloud::microsoft::office365::sharepoint::mode::siteusage', + 'users-activity' => 'cloud::microsoft::office365::sharepoint::mode::usersactivity', ); $self->{custom_modes}{graphapi} = 'cloud::microsoft::office365::custom::graphapi'; From f26d479e57f3ece25c0503c2e47bd361c4228bb9 Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Mon, 24 Dec 2018 16:31:10 +0100 Subject: [PATCH 12/23] enh office365 graphapi custom mode --- .../microsoft/office365/custom/graphapi.pm | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm b/centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm index 169a0ca0e..2e8f88319 100644 --- a/centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm +++ b/centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm @@ -226,7 +226,7 @@ sub request_api_csv { my $content = $self->{http}->request(%options); my $response = $self->{http}->get_response(); - + if ($response->code() != 200) { my $decoded; eval { @@ -260,7 +260,6 @@ sub request_api_csv { open my $fh, '<', \$decoded; my $csv = Text::CSV->new({ binary => 1 }); $csv->column_names($csv->getline($fh)); - my $dummy = <$fh>; while (my $row = $csv->getline_hr($fh)) { push @rows, $row; } @@ -291,6 +290,40 @@ sub office_get_sharepoint_site_usage { return $response; } +sub office_get_sharepoint_activity_set_url { + my ($self, %options) = @_; + + my $url = $self->{graph_endpoint} . "/v1.0/reports/getSharePointActivityUserDetail(period='D7')"; + + return $url; +} + +sub office_get_sharepoint_activity { + my ($self, %options) = @_; + + my $full_url = $self->office_get_sharepoint_activity_set_url(%options); + my $response = $self->request_api_csv(method => 'GET', full_url => $full_url, hostname => ''); + + return $response; +} + +sub office_get_onedrive_usage_set_url { + my ($self, %options) = @_; + + my $url = $self->{graph_endpoint} . "/v1.0/reports/getOneDriveUsageAccountDetail(period='D7')"; + + return $url; +} + +sub office_get_onedrive_usage { + my ($self, %options) = @_; + + my $full_url = $self->office_get_onedrive_usage_set_url(%options); + my $response = $self->request_api_csv(method => 'GET', full_url => $full_url, hostname => ''); + + return $response; +} + 1; __END__ From 785e07d1e53a150ef85c48053b5cce21a249a70b Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Mon, 24 Dec 2018 16:31:36 +0100 Subject: [PATCH 13/23] add office365 onedrive plugin --- .../office365/onedrive/mode/listsites.pm | 123 ++++++++++ .../office365/onedrive/mode/usage.pm | 230 ++++++++++++++++++ .../microsoft/office365/onedrive/plugin.pm | 49 ++++ 3 files changed, 402 insertions(+) create mode 100644 centreon-plugins/cloud/microsoft/office365/onedrive/mode/listsites.pm create mode 100644 centreon-plugins/cloud/microsoft/office365/onedrive/mode/usage.pm create mode 100644 centreon-plugins/cloud/microsoft/office365/onedrive/plugin.pm diff --git a/centreon-plugins/cloud/microsoft/office365/onedrive/mode/listsites.pm b/centreon-plugins/cloud/microsoft/office365/onedrive/mode/listsites.pm new file mode 100644 index 000000000..e77fd270c --- /dev/null +++ b/centreon-plugins/cloud/microsoft/office365/onedrive/mode/listsites.pm @@ -0,0 +1,123 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 cloud::microsoft::office365::sharepoint::mode::listsites; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-url:s" => { name => 'filter_url' }, + "filter-id:s" => { name => 'filter_id' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $results = $options{custom}->office_get_sharepoint_site_usage(); + + foreach my $site (@{$results}) { + if (defined($self->{option_results}->{filter_url}) && $self->{option_results}->{filter_url} ne '' && + $site->{'Site URL'} !~ /$self->{option_results}->{filter_url}/) { + $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site URL'} . "': no matching filter name.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_id}) && $self->{option_results}->{filter_id} ne '' && + $site->{'Site Id'} !~ /$self->{option_results}->{filter_id}/) { + $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site Id'} . "': no matching filter name.", debug => 1); + next; + } + + $self->{sites}->{$site->{'Site Id'}} = { + id => $site->{'Site Id'}, + url => $site->{'Site URL'}, + } + } +} + +sub run { + my ($self, %options) = @_; + + $self->manage_selection(%options); + foreach my $site (sort keys %{$self->{sites}}) { + $self->{output}->output_add(long_msg => sprintf("[id = %s] [url = %s]", + $self->{sites}->{$site}->{id}, + $self->{sites}->{$site}->{url})); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List sites:'); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); + $self->{output}->exit(); +} + +sub disco_format { + my ($self, %options) = @_; + + $self->{output}->add_disco_format(elements => ['id', 'url']); +} + +sub disco_show { + my ($self, %options) = @_; + + $self->manage_selection(%options); + foreach my $site (sort keys %{$self->{sites}}) { + $self->{output}->add_disco_entry( + id => $self->{sites}->{$site}->{id}, + url => $self->{sites}->{$site}->{url}, + ); + } +} + +1; + +__END__ + +=head1 MODE + +List sites. + +=over 8 + +=item B<--filter-*> + +Filter sites. +Can be: 'url', 'id' (can be a regexp). + +=back + +=cut diff --git a/centreon-plugins/cloud/microsoft/office365/onedrive/mode/usage.pm b/centreon-plugins/cloud/microsoft/office365/onedrive/mode/usage.pm new file mode 100644 index 000000000..b887b5f1f --- /dev/null +++ b/centreon-plugins/cloud/microsoft/office365/onedrive/mode/usage.pm @@ -0,0 +1,230 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 cloud::microsoft::office365::onedrive::mode::usage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $instance_mode; + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + + $self->{output}->perfdata_add(label => 'used' . $extra_label, + unit => 'B', + value => $self->{result_values}->{used}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_usage_threshold { + my ($self, %options) = @_; + + my ($exit, $threshold_value); + $threshold_value = $self->{result_values}->{used}; + $threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free})); + if ($instance_mode->{option_results}->{units} eq '%') { + $threshold_value = $self->{result_values}->{prct_used}; + $threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free})); + } + $exit = $self->{perfdata}->threshold_check(value => $threshold_value, + threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, + { label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($free_value, $free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + my ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + + my $msg = sprintf("Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", + $total_value . " " . $total_unit, + $used_value . " " . $used_unit, $self->{result_values}->{prct_used}, + $free_value . " " . $free_unit, $self->{result_values}->{prct_free}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_url'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_storage_allocated'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_storage_used'}; + + if ($self->{result_values}->{total} != 0) { + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + } else { + $self->{result_values}->{free} = '0'; + $self->{result_values}->{prct_used} = '0'; + $self->{result_values}->{prct_free} = '0'; + } + + return 0; +} + +sub prefix_site_output { + my ($self, %options) = @_; + + return "Site '" . $options{instance_value}->{url} . "' [Owner: " . $options{instance_value}->{owner} . "] "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'sites', type => 1, cb_prefix_output => 'prefix_site_output', message_multiple => 'All sites usage are ok' }, + ]; + + $self->{maps_counters}->{sites} = [ + { label => 'usage', set => { + key_values => [ { name => 'storage_used' }, { name => 'storage_allocated' }, { name => 'url' }, { name => 'owner' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + { label => 'file-count', set => { + key_values => [ { name => 'file_count' }, { name => 'url' }, { name => 'owner' } ], + output_template => 'File Count: %d', + perfdatas => [ + { label => 'file_count', value => 'file_count_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'url_absolute' }, + ], + } + }, + { label => 'active-file-count', set => { + key_values => [ { name => 'active_file_count' }, { name => 'url' }, { name => 'owner' } ], + output_template => 'Active File Count: %d', + perfdatas => [ + { label => 'active_file_count', value => 'active_file_count_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'url_absolute' }, + ], + } + }, + { label => 'last-activity', threshold => 0, set => { + key_values => [ { name => 'last_activity_date' }, { name => 'url' }, { name => 'owner' } ], + output_template => 'Last Activity: %s', + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-url:s" => { name => 'filter_url' }, + "filter-owner:s" => { name => 'filter_owner' }, + "units:s" => { name => 'units', default => '%' }, + "free" => { name => 'free' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{sites} = {}; + + my $results = $options{custom}->office_get_onedrive_usage(); + + foreach my $site (@{$results}) { + if (defined($self->{option_results}->{filter_url}) && $self->{option_results}->{filter_url} ne '' && + $site->{'Site URL'} !~ /$self->{option_results}->{filter_url}/) { + $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site URL'} . "': no matching filter name.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_owner}) && $self->{option_results}->{filter_owner} ne '' && + $site->{'Owner Display Name'} !~ /$self->{option_results}->{filter_owner}/) { + $self->{output}->output_add(long_msg => "skipping '" . $site->{'Owner Display Name'} . "': no matching filter name.", debug => 1); + next; + } + + $self->{sites}->{$site->{'Site URL'}}->{url} = $site->{'Site URL'}; + $self->{sites}->{$site->{'Site URL'}}->{owner} = $site->{'Owner Display Name'}; + $self->{sites}->{$site->{'Site URL'}}->{file_count} = $site->{'File Count'}; + $self->{sites}->{$site->{'Site URL'}}->{active_file_count} = $site->{'Active File Count'}; + $self->{sites}->{$site->{'Site URL'}}->{storage_used} = $site->{'Storage Used (Byte)'}; + $self->{sites}->{$site->{'Site URL'}}->{storage_allocated} = $site->{'Storage Allocated (Byte)'}; + $self->{sites}->{$site->{'Site URL'}}->{last_activity_date} = $site->{'Last Activity Date'}; + } + + if (scalar(keys %{$self->{sites}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No entry found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check usage (reporting period over the last 7 days). + +(See link for details about metrics : +https://docs.microsoft.com/en-us/office365/admin/activity-reports/onedrive-for-business-usage?view=o365-worldwide) + +=over 8 + +=item B<--filter-*> + +Filter sites. +Can be: 'url', 'owner' (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'usage', 'file-count', 'active-file-count'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'usage', 'file-count', 'active-file-count'. + +=back + +=cut diff --git a/centreon-plugins/cloud/microsoft/office365/onedrive/plugin.pm b/centreon-plugins/cloud/microsoft/office365/onedrive/plugin.pm new file mode 100644 index 000000000..1239bf308 --- /dev/null +++ b/centreon-plugins/cloud/microsoft/office365/onedrive/plugin.pm @@ -0,0 +1,49 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 cloud::microsoft::office365::onedrive::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_custom); + +sub new { + my ( $class, %options ) = @_; + my $self = $class->SUPER::new( package => __PACKAGE__, %options ); + bless $self, $class; + + $self->{version} = '0.1'; + %{ $self->{modes} } = ( + 'usage' => 'cloud::microsoft::office365::onedrive::mode::usage', + ); + + $self->{custom_modes}{graphapi} = 'cloud::microsoft::office365::custom::graphapi'; + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Microsoft Office 365. + +=cut From 1b6c8ed46b9c7f5d9e6df6a87150d59a2b2b5ac0 Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Mon, 24 Dec 2018 16:33:50 +0100 Subject: [PATCH 14/23] enh office365 onedrive plugin --- .../office365/onedrive/mode/listsites.pm | 24 +++++++++---------- .../microsoft/office365/onedrive/plugin.pm | 1 + 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/centreon-plugins/cloud/microsoft/office365/onedrive/mode/listsites.pm b/centreon-plugins/cloud/microsoft/office365/onedrive/mode/listsites.pm index e77fd270c..92a0b8298 100644 --- a/centreon-plugins/cloud/microsoft/office365/onedrive/mode/listsites.pm +++ b/centreon-plugins/cloud/microsoft/office365/onedrive/mode/listsites.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package cloud::microsoft::office365::sharepoint::mode::listsites; +package cloud::microsoft::office365::onedrive::mode::listsites; use base qw(centreon::plugins::templates::counter); @@ -34,7 +34,7 @@ sub new { $options{options}->add_options(arguments => { "filter-url:s" => { name => 'filter_url' }, - "filter-id:s" => { name => 'filter_id' }, + "filter-owner:s" => { name => 'filter_owner' }, }); return $self; @@ -48,7 +48,7 @@ sub check_options { sub manage_selection { my ($self, %options) = @_; - my $results = $options{custom}->office_get_sharepoint_site_usage(); + my $results = $options{custom}->office_get_onedrive_usage(); foreach my $site (@{$results}) { if (defined($self->{option_results}->{filter_url}) && $self->{option_results}->{filter_url} ne '' && @@ -56,14 +56,14 @@ sub manage_selection { $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site URL'} . "': no matching filter name.", debug => 1); next; } - if (defined($self->{option_results}->{filter_id}) && $self->{option_results}->{filter_id} ne '' && - $site->{'Site Id'} !~ /$self->{option_results}->{filter_id}/) { - $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site Id'} . "': no matching filter name.", debug => 1); + if (defined($self->{option_results}->{filter_owner}) && $self->{option_results}->{filter_owner} ne '' && + $site->{'Owner Display Name'} !~ /$self->{option_results}->{filter_owner}/) { + $self->{output}->output_add(long_msg => "skipping '" . $site->{'Owner Display Name'} . "': no matching filter name.", debug => 1); next; } - $self->{sites}->{$site->{'Site Id'}} = { - id => $site->{'Site Id'}, + $self->{sites}->{$site->{'Site URL'}} = { + owner => $site->{'Owner Display Name'}, url => $site->{'Site URL'}, } } @@ -74,8 +74,8 @@ sub run { $self->manage_selection(%options); foreach my $site (sort keys %{$self->{sites}}) { - $self->{output}->output_add(long_msg => sprintf("[id = %s] [url = %s]", - $self->{sites}->{$site}->{id}, + $self->{output}->output_add(long_msg => sprintf("[owner = %s] [url = %s]", + $self->{sites}->{$site}->{owner}, $self->{sites}->{$site}->{url})); } @@ -88,7 +88,7 @@ sub run { sub disco_format { my ($self, %options) = @_; - $self->{output}->add_disco_format(elements => ['id', 'url']); + $self->{output}->add_disco_format(elements => ['owner', 'url']); } sub disco_show { @@ -97,7 +97,7 @@ sub disco_show { $self->manage_selection(%options); foreach my $site (sort keys %{$self->{sites}}) { $self->{output}->add_disco_entry( - id => $self->{sites}->{$site}->{id}, + owner => $self->{sites}->{$site}->{owner}, url => $self->{sites}->{$site}->{url}, ); } diff --git a/centreon-plugins/cloud/microsoft/office365/onedrive/plugin.pm b/centreon-plugins/cloud/microsoft/office365/onedrive/plugin.pm index 1239bf308..ff045447d 100644 --- a/centreon-plugins/cloud/microsoft/office365/onedrive/plugin.pm +++ b/centreon-plugins/cloud/microsoft/office365/onedrive/plugin.pm @@ -31,6 +31,7 @@ sub new { $self->{version} = '0.1'; %{ $self->{modes} } = ( + 'list-sites' => 'cloud::microsoft::office365::onedrive::mode::listsites', 'usage' => 'cloud::microsoft::office365::onedrive::mode::usage', ); From a40ba56d5a9ca2f288e01b953575cfb794f02f2c Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Wed, 26 Dec 2018 12:05:40 +0100 Subject: [PATCH 15/23] fix snmp lib start/end checkup function (#1292) --- centreon-plugins/centreon/plugins/snmp.pm | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/centreon-plugins/centreon/plugins/snmp.pm b/centreon-plugins/centreon/plugins/snmp.pm index 27683b76c..9833c329d 100644 --- a/centreon-plugins/centreon/plugins/snmp.pm +++ b/centreon-plugins/centreon/plugins/snmp.pm @@ -410,7 +410,7 @@ sub get_multiple_table { my $base = $bases[$pos % $current_oids]; if ($complete_oid !~ /^$base\./ || (defined($working_oids->{ $bases[$pos % $current_oids] }->{end}) && - $self->check_oid_up($complete_oid, $working_oids->{ $bases[$pos % $current_oids] }->{end}) )) { + $self->check_oid_up(current => $complete_oid, end => $working_oids->{ $bases[$pos % $current_oids] }->{end}))) { delete $working_oids->{ $bases[$pos % $current_oids] }; next; } @@ -540,7 +540,7 @@ sub get_table { # Not in same table my $complete_oid = ${$entry}[0] . "." . ${$entry}[1]; if ($complete_oid !~ /^$main_indice\./ || - (defined($options{end}) && $self->check_oid_up($complete_oid, $options{end}) )) { + (defined($options{end}) && $self->check_oid_up(current => $complete_oid, end => $options{end}))) { $leave = 0; last; } @@ -615,8 +615,10 @@ sub clean_oid { } sub check_oid_up { - my ($self) = @_; - my ($current_oid, $end_oid) = @_; + my ($self, %options) = @_; + + my $current_oid = $options{current}; + my $end_oid = $options{end}; my @current_oid_splitted = split /\./, $current_oid; my @end_oid_splitted = split /\./, $end_oid; From 4248fa0ab8b9b2adf769949ace011fc20f830d16 Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Wed, 26 Dec 2018 17:08:12 +0100 Subject: [PATCH 16/23] enh fortinet fortigate plugin, add vdom modes (#1293) --- .../common/fortinet/fortigate/mode/vdomcpu.pm | 132 ++++++++++ .../fortinet/fortigate/mode/vdommemory.pm | 132 ++++++++++ .../fortinet/fortigate/mode/vdomsession.pm | 145 +++++++++++ .../fortinet/fortigate/mode/vdomstate.pm | 202 +++++++++++++++ .../fortinet/fortigate/mode/vdomusage.pm | 237 ++++++++++++++++++ .../network/fortinet/fortigate/plugin.pm | 5 + 6 files changed, 853 insertions(+) create mode 100644 centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomcpu.pm create mode 100644 centreon-plugins/centreon/common/fortinet/fortigate/mode/vdommemory.pm create mode 100644 centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomsession.pm create mode 100644 centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomstate.pm create mode 100644 centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomusage.pm diff --git a/centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomcpu.pm b/centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomcpu.pm new file mode 100644 index 000000000..14af2a37d --- /dev/null +++ b/centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomcpu.pm @@ -0,0 +1,132 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 centreon::common::fortinet::fortigate::mode::vdomcpu; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub prefix_vdom_output { + my ($self, %options) = @_; + + return "Virtual domain '" . $options{instance_value}->{fgVdEntName} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'vdoms', type => 1, cb_prefix_output => 'prefix_vdom_output', message_multiple => 'All cpu usage are ok' }, + ]; + $self->{maps_counters}->{vdoms} = [ + { label => 'usage', set => { + key_values => [ { name => 'fgVdEntCpuUsage' }, { name => 'fgVdEntName' } ], + output_template => 'CPU usage: %.2f%%', + perfdatas => [ + { label => 'cpu_usage', value => 'fgVdEntCpuUsage_absolute', template => '%.2f', + min => 0, min => 100, unit => '%', label_extra_instance => 1, instance_use => 'fgVdEntName_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); +} + +my $mapping = { + fgVdEntName => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.2' }, + fgVdEntCpuUsage => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.5' }, +}; + +my $oid_fgVdInfo = '.1.3.6.1.4.1.12356.101.3.2'; + +sub manage_selection { + my ($self, %options) = @_; + + $self->{vdoms} = {}; + + my $results = $options{snmp}->get_table(oid => $oid_fgVdInfo , nothing_quit => 1); + + foreach my $oid (keys %{$results}) { + next if ($oid !~ /^$mapping->{fgVdEntCpuUsage}->{oid}\.(\d+)/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $results, instance => $instance); + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{fgVdEntName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter name.", debug => 1); + next; + } + + $self->{vdoms}->{$result->{fgVdEntName}} = { + fgVdEntName => $result->{fgVdEntName}, + fgVdEntCpuUsage => $result->{fgVdEntCpuUsage}, + } + } + + if (scalar(keys %{$self->{vdoms}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No entry found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check virtual domains CPU usage. + +=over 8 + +=item B<--filter-name> + +Filter by virtual domain name (can be a regexp). + +=item B<--warning-usage> + +Threshold warning. + +=item B<--critical-usage> + +Threshold critical. + +=back + +=cut diff --git a/centreon-plugins/centreon/common/fortinet/fortigate/mode/vdommemory.pm b/centreon-plugins/centreon/common/fortinet/fortigate/mode/vdommemory.pm new file mode 100644 index 000000000..e276308f0 --- /dev/null +++ b/centreon-plugins/centreon/common/fortinet/fortigate/mode/vdommemory.pm @@ -0,0 +1,132 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 centreon::common::fortinet::fortigate::mode::vdommemory; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub prefix_vdom_output { + my ($self, %options) = @_; + + return "Virtual domain '" . $options{instance_value}->{fgVdEntName} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'vdoms', type => 1, cb_prefix_output => 'prefix_vdom_output', message_multiple => 'All memory usage are ok' }, + ]; + $self->{maps_counters}->{vdoms} = [ + { label => 'usage', set => { + key_values => [ { name => 'fgVdEntMemUsage' }, { name => 'fgVdEntName' } ], + output_template => 'memory usage: %.2f%%', + perfdatas => [ + { label => 'memory_usage', value => 'fgVdEntMemUsage_absolute', template => '%.2f', + min => 0, min => 100, unit => '%', label_extra_instance => 1, instance_use => 'fgVdEntName_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); +} + +my $mapping = { + fgVdEntName => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.2' }, + fgVdEntMemUsage => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.6' }, +}; + +my $oid_fgVdInfo = '.1.3.6.1.4.1.12356.101.3.2'; + +sub manage_selection { + my ($self, %options) = @_; + + $self->{vdoms} = {}; + + my $results = $options{snmp}->get_table(oid => $oid_fgVdInfo , nothing_quit => 1); + + foreach my $oid (keys %{$results}) { + next if ($oid !~ /^$mapping->{fgVdEntMemUsage}->{oid}\.(\d+)/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $results, instance => $instance); + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{fgVdEntName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter name.", debug => 1); + next; + } + + $self->{vdoms}->{$result->{fgVdEntName}} = { + fgVdEntName => $result->{fgVdEntName}, + fgVdEntMemUsage => $result->{fgVdEntMemUsage}, + } + } + + if (scalar(keys %{$self->{vdoms}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No entry found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check virtual domains memory usage. + +=over 8 + +=item B<--filter-name> + +Filter by virtual domain name (can be a regexp). + +=item B<--warning-usage> + +Threshold warning. + +=item B<--critical-usage> + +Threshold critical. + +=back + +=cut diff --git a/centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomsession.pm b/centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomsession.pm new file mode 100644 index 000000000..72e8d1db6 --- /dev/null +++ b/centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomsession.pm @@ -0,0 +1,145 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 centreon::common::fortinet::fortigate::mode::vdomsession; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub prefix_vdom_output { + my ($self, %options) = @_; + + return "Virtual domain '" . $options{instance_value}->{fgVdEntName} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'vdoms', type => 1, cb_prefix_output => 'prefix_vdom_output', message_multiple => 'All session metrics are ok' }, + ]; + $self->{maps_counters}->{vdoms} = [ + { label => 'active-session', set => { + key_values => [ { name => 'fgVdEntSesCount' }, { name => 'fgVdEntName' } ], + output_template => 'Active sessions: %d', + perfdatas => [ + { label => 'active_sessions', value => 'fgVdEntSesCount_absolute', template => '%d', + min => 0, unit => 'sessions', label_extra_instance => 1, instance_use => 'fgVdEntName_absolute' }, + ], + } + }, + { label => 'session-rate', set => { + key_values => [ { name => 'fgVdEntSesRate' }, { name => 'fgVdEntName' } ], + output_template => 'Session setup rate: %d sessions/s', + perfdatas => [ + { label => 'session_rate', value => 'fgVdEntSesRate_absolute', template => '%d', + min => 0, unit => 'sessions/s', label_extra_instance => 1, instance_use => 'fgVdEntName_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); +} + +my $mapping = { + fgVdEntName => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.2' }, + fgVdEntSesCount => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.7' }, + fgVdEntSesRate => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.8' }, +}; + +my $oid_fgVdInfo = '.1.3.6.1.4.1.12356.101.3.2'; + +sub manage_selection { + my ($self, %options) = @_; + + $self->{vdoms} = {}; + + my $results = $options{snmp}->get_table(oid => $oid_fgVdInfo , nothing_quit => 1); + + foreach my $oid (keys %{$results}) { + next if ($oid !~ /^$mapping->{fgVdEntSesCount}->{oid}\.(\d+)/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $results, instance => $instance); + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{fgVdEntName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter name.", debug => 1); + next; + } + + $self->{vdoms}->{$result->{fgVdEntName}} = { + fgVdEntName => $result->{fgVdEntName}, + fgVdEntSesCount => $result->{fgVdEntSesCount}, + fgVdEntSesRate => $result->{fgVdEntSesRate}, + } + } + + if (scalar(keys %{$self->{vdoms}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No entry found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check virtual domains active sessions count and session setup rate. + +=over 8 + +=item B<--filter-name> + +Filter by virtual domain name (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'active-session', 'session-rate'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'active-session', 'session-rate'. + +=back + +=cut diff --git a/centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomstate.pm b/centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomstate.pm new file mode 100644 index 000000000..d26a54a3b --- /dev/null +++ b/centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomstate.pm @@ -0,0 +1,202 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 centreon::common::fortinet::fortigate::mode::vdomstate; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = sprintf("Operation mode is '%s', HA cluster member state is '%s'", + $self->{result_values}->{op_mode}, $self->{result_values}->{ha_state}); + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{op_mode} = $options{new_datas}->{$self->{instance} . '_fgVdEntOpMode'}; + $self->{result_values}->{ha_state} = $options{new_datas}->{$self->{instance} . '_fgVdEntHaState'}; + return 0; +} + +sub prefix_vdom_output { + my ($self, %options) = @_; + + return "Virtual domain '" . $options{instance_value}->{fgVdEntName} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'vdoms', type => 1, cb_prefix_output => 'prefix_vdom_output', message_multiple => 'All states are ok' }, + ]; + $self->{maps_counters}->{vdoms} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'fgVdEntOpMode' }, { name => 'fgVdEntHaState' }, { name => 'fgVdEntName' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "warning-status:s" => { name => 'warning_status', default => '' }, + "critical-status:s" => { name => 'critical_status', default => '' }, + }); + return $self; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $self->change_macros(); + $instance_mode = $self; +} + +my %map_op_mode = ( + 1 => 'nat', + 2 => 'transparent', +); +my %map_ha_state = ( + 1 => 'master', + 2 => 'backup', + 3 => 'standalone', +); + +my $mapping = { + fgVdEntName => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.2' }, + fgVdEntOpMode => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.3', map => \%map_op_mode }, + fgVdEntHaState => { oid => '.1.3.6.1.4.1.12356.101.3.2.1.1.4', map => \%map_ha_state }, +}; + +my $oid_fgVdInfo = '.1.3.6.1.4.1.12356.101.3.2'; + +sub manage_selection { + my ($self, %options) = @_; + + $self->{vdoms} = {}; + + my $results = $options{snmp}->get_table(oid => $oid_fgVdInfo , nothing_quit => 1); + + foreach my $oid (keys %{$results}) { + next if ($oid !~ /^$mapping->{fgVdEntHaState}->{oid}\.(\d+)/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $results, instance => $instance); + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{fgVdEntName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter name.", debug => 1); + next; + } + + $self->{vdoms}->{$result->{fgVdEntName}} = { + fgVdEntName => $result->{fgVdEntName}, + fgVdEntOpMode => $result->{fgVdEntOpMode}, + fgVdEntHaState => $result->{fgVdEntHaState}, + } + } + + if (scalar(keys %{$self->{vdoms}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No entry found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check virtual domains operation mode and HA cluster member state. + +=over 8 + +=item B<--filter-name> + +Filter by virtual domain name (can be a regexp). + +=item B<--warning-status> + +Set warning threshold for status (Default: ''). +Can used special variables like: %{op_mode}, %{ha_state} + +=item B<--critical-status> + +Set critical threshold for status (Default: ''). +Can used special variables like: %{op_mode}, %{ha_state} + +=back + +=cut diff --git a/centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomusage.pm b/centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomusage.pm new file mode 100644 index 000000000..380a9e0c7 --- /dev/null +++ b/centreon-plugins/centreon/common/fortinet/fortigate/mode/vdomusage.pm @@ -0,0 +1,237 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 centreon::common::fortinet::fortigate::mode::vdomusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = sprintf("Virtual domains are '%s' on this device", $self->{result_values}->{state}); + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_fgVdEnabled'}; + return 0; +} + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + $self->{output}->perfdata_add(label => 'used', + value => $self->{result_values}->{used}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_usage_threshold { + my ($self, %options) = @_; + + my ($exit, $threshold_value); + $threshold_value = $self->{result_values}->{used}; + $threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free})); + if ($instance_mode->{option_results}->{units} eq '%') { + $threshold_value = $self->{result_values}->{prct_used}; + $threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free})); + } + $exit = $self->{perfdata}->threshold_check(value => $threshold_value, + threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, + { label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my $msg = sprintf("Number of virtual domains used: %s/%s (%.2f%%)", $self->{result_values}->{used}, + $self->{result_values}->{total}, $self->{result_values}->{prct_used}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_fgVdNumber'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_fgVdMaxVdoms'}; + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 }, + ]; + $self->{maps_counters}->{global} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'fgVdEnabled' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + { label => 'usage', set => { + key_values => [ { name => 'fgVdNumber' }, { name => 'fgVdMaxVdoms' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "warning-status:s" => { name => 'warning_status', default => '%{state} eq "disabled"' }, + "critical-status:s" => { name => 'critical_status', default => '' }, + "units:s" => { name => 'units', default => '%' }, + "free" => { name => 'free' }, + }); + return $self; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $self->change_macros(); + $instance_mode = $self; +} + +my %map_state = ( + 1 => 'disabled', + 2 => 'enabled', +); + +my $mapping = { + fgVdNumber => { oid => '.1.3.6.1.4.1.12356.101.3.1.1' }, + fgVdMaxVdoms => { oid => '.1.3.6.1.4.1.12356.101.3.1.2' }, + fgVdEnabled => { oid => '.1.3.6.1.4.1.12356.101.3.1.3', map => \%map_state }, +}; + +my $oid_fgVdInfo = '.1.3.6.1.4.1.12356.101.3.1'; + +sub manage_selection { + my ($self, %options) = @_; + + $self->{global} = {}; + + $self->{results} = $options{snmp}->get_table(oid => $oid_fgVdInfo , nothing_quit => 1); + + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $self->{results}, instance => 0); + + $self->{global} = {%{$result}}; +} + +1; + +__END__ + +=head1 MODE + +Check virtual domains activation and slots usage. + +=over 8 + +=item B<--warning-status> + +Set warning threshold for status (Default: '%{state} eq "disabled"'). +Can used special variables like: %{state} + +=item B<--critical-status> + +Set critical threshold for status (Default: ''). +Can used special variables like: %{state} + +=item B<--warning-usage> + +Threshold warning. + +=item B<--critical-usage> + +Threshold critical. + +=item B<--units> + +Units of thresholds (Default: '%') ('%', 'count'). + +=item B<--free> + +Thresholds are on free virtual domain slots. + +=back + +=cut diff --git a/centreon-plugins/network/fortinet/fortigate/plugin.pm b/centreon-plugins/network/fortinet/fortigate/plugin.pm index 1503b763a..6051afcd2 100644 --- a/centreon-plugins/network/fortinet/fortigate/plugin.pm +++ b/centreon-plugins/network/fortinet/fortigate/plugin.pm @@ -42,6 +42,11 @@ sub new { 'memory' => 'centreon::common::fortinet::fortigate::mode::memory', 'sessions' => 'centreon::common::fortinet::fortigate::mode::sessions', 'signatures' => 'centreon::common::fortinet::fortigate::mode::signatures', + 'vdom-cpu' => 'centreon::common::fortinet::fortigate::mode::vdomcpu', + 'vdom-memory' => 'centreon::common::fortinet::fortigate::mode::vdommemory', + 'vdom-session' => 'centreon::common::fortinet::fortigate::mode::vdomsession', + 'vdom-state' => 'centreon::common::fortinet::fortigate::mode::vdomstate', + 'vdom-usage' => 'centreon::common::fortinet::fortigate::mode::vdomusage', 'virus' => 'centreon::common::fortinet::fortigate::mode::virus', 'vpn' => 'centreon::common::fortinet::fortigate::mode::vpn', ); From 4dd2f32bbdf7bc47f35c2cb74106124d03699924 Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Thu, 27 Dec 2018 15:48:44 +0100 Subject: [PATCH 17/23] enh office365 sharepoint plugin --- .../cloud/microsoft/office365/sharepoint/mode/usersactivity.pm | 3 +-- .../cloud/microsoft/office365/sharepoint/plugin.pm | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/usersactivity.pm b/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/usersactivity.pm index 06b5db9ef..b5c532a8b 100644 --- a/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/usersactivity.pm +++ b/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/usersactivity.pm @@ -117,8 +117,6 @@ sub manage_selection { $self->{users} = {}; my $results = $options{custom}->office_get_sharepoint_activity(); - use Data::Dumper; - print Dumper $results; foreach my $user (@{$results}) { if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && @@ -170,6 +168,7 @@ Can be: 'viewed-edited-file-count', 'file-count', 'shared-int-file-count', Threshold critical. Can be: 'viewed-edited-file-count', 'file-count', 'shared-int-file-count', 'shared-ext-file-count', 'visited-page-count'. + =back =cut diff --git a/centreon-plugins/cloud/microsoft/office365/sharepoint/plugin.pm b/centreon-plugins/cloud/microsoft/office365/sharepoint/plugin.pm index 8a7d28078..428d405a9 100644 --- a/centreon-plugins/cloud/microsoft/office365/sharepoint/plugin.pm +++ b/centreon-plugins/cloud/microsoft/office365/sharepoint/plugin.pm @@ -46,6 +46,6 @@ __END__ =head1 PLUGIN DESCRIPTION -Check Microsoft Office 365. +Check Microsoft Office 365 SharePoint. =cut From 5f23db559e78785f78919f84b74050247464413f Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Thu, 27 Dec 2018 15:48:58 +0100 Subject: [PATCH 18/23] enh office365 onedrive plugin --- centreon-plugins/cloud/microsoft/office365/onedrive/plugin.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/centreon-plugins/cloud/microsoft/office365/onedrive/plugin.pm b/centreon-plugins/cloud/microsoft/office365/onedrive/plugin.pm index ff045447d..be049eec7 100644 --- a/centreon-plugins/cloud/microsoft/office365/onedrive/plugin.pm +++ b/centreon-plugins/cloud/microsoft/office365/onedrive/plugin.pm @@ -45,6 +45,6 @@ __END__ =head1 PLUGIN DESCRIPTION -Check Microsoft Office 365. +Check Microsoft Office 365 OneDrive. =cut From 8b81882ea404567406340dca5ccbdf98a50a4119 Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Thu, 27 Dec 2018 15:49:31 +0100 Subject: [PATCH 19/23] add office365 exchange plugin --- .../microsoft/office365/custom/graphapi.pm | 34 +++ .../office365/exchange/mode/emailactivity.pm | 152 +++++++++++++ .../office365/exchange/mode/mailboxusage.pm | 210 ++++++++++++++++++ .../microsoft/office365/exchange/plugin.pm | 50 +++++ 4 files changed, 446 insertions(+) create mode 100644 centreon-plugins/cloud/microsoft/office365/exchange/mode/emailactivity.pm create mode 100644 centreon-plugins/cloud/microsoft/office365/exchange/mode/mailboxusage.pm create mode 100644 centreon-plugins/cloud/microsoft/office365/exchange/plugin.pm diff --git a/centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm b/centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm index 2e8f88319..274652950 100644 --- a/centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm +++ b/centreon-plugins/cloud/microsoft/office365/custom/graphapi.pm @@ -324,6 +324,40 @@ sub office_get_onedrive_usage { return $response; } +sub office_get_exchange_activity_set_url { + my ($self, %options) = @_; + + my $url = $self->{graph_endpoint} . "/v1.0/reports/getEmailActivityUserDetail(period='D7')"; + + return $url; +} + +sub office_get_exchange_activity { + my ($self, %options) = @_; + + my $full_url = $self->office_get_exchange_activity_set_url(%options); + my $response = $self->request_api_csv(method => 'GET', full_url => $full_url, hostname => ''); + + return $response; +} + +sub office_get_exchange_mailbox_usage_set_url { + my ($self, %options) = @_; + + my $url = $self->{graph_endpoint} . "/v1.0/reports/getMailboxUsageDetail(period='D7')"; + + return $url; +} + +sub office_get_exchange_mailbox_usage { + my ($self, %options) = @_; + + my $full_url = $self->office_get_exchange_mailbox_usage_set_url(%options); + my $response = $self->request_api_csv(method => 'GET', full_url => $full_url, hostname => ''); + + return $response; +} + 1; __END__ diff --git a/centreon-plugins/cloud/microsoft/office365/exchange/mode/emailactivity.pm b/centreon-plugins/cloud/microsoft/office365/exchange/mode/emailactivity.pm new file mode 100644 index 000000000..26d90e713 --- /dev/null +++ b/centreon-plugins/cloud/microsoft/office365/exchange/mode/emailactivity.pm @@ -0,0 +1,152 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 cloud::microsoft::office365::exchange::mode::emailactivity; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub prefix_user_output { + my ($self, %options) = @_; + + return "User '" . $options{instance_value}->{name} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'users', type => 1, cb_prefix_output => 'prefix_user_output', message_multiple => 'All email activity are ok' }, + ]; + + $self->{maps_counters}->{users} = [ + { label => 'send-count', set => { + key_values => [ { name => 'send_count' }, { name => 'name' } ], + output_template => 'Send Count: %d', + perfdatas => [ + { label => 'send_count', value => 'send_count_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'name_absolute' }, + ], + } + }, + { label => 'receive-count', set => { + key_values => [ { name => 'receive_count' }, { name => 'name' } ], + output_template => 'Receive Count: %d', + perfdatas => [ + { label => 'receive_count', value => 'receive_count_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'name_absolute' }, + ], + } + }, + { label => 'read-count', set => { + key_values => [ { name => 'read_count' }, { name => 'name' } ], + output_template => 'Read Count: %d', + perfdatas => [ + { label => 'read_count', value => 'read_count_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'name_absolute' }, + ], + } + }, + { label => 'last-activity', threshold => 0, set => { + key_values => [ { name => 'last_activity_date' }, { name => 'name' } ], + output_template => 'Last Activity: %s', + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-user:s" => { name => 'filter_user' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{users} = {}; + + my $results = $options{custom}->office_get_exchange_activity(); + + foreach my $user (@{$results}) { + if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && + $user->{'User Principal Name'} !~ /$self->{option_results}->{filter_user}/) { + $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no matching filter name.", debug => 1); + next; + } + + $self->{users}->{$user->{'User Principal Name'}}->{name} = $user->{'User Principal Name'}; + $self->{users}->{$user->{'User Principal Name'}}->{send_count} = $user->{'Send Count'}; + $self->{users}->{$user->{'User Principal Name'}}->{receive_count} = $user->{'Receive Count'}; + $self->{users}->{$user->{'User Principal Name'}}->{read_count} = $user->{'Read Count'}; + $self->{users}->{$user->{'User Principal Name'}}->{last_activity_date} = $user->{'Last Activity Date'}; + } + + if (scalar(keys %{$self->{users}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No entry found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check email activity (reporting period over the last 7 days). + +(See link for details about metrics : +https://docs.microsoft.com/en-us/office365/admin/activity-reports/email-activity?view=o365-worldwide) + +=over 8 + +=item B<--filter-user> + +Filter users. + +=item B<--warning-*> + +Threshold warning. +Can be: 'send-count', 'receive-count', 'read-count'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'send-count', 'receive-count', 'read-count'. + +=back + +=cut diff --git a/centreon-plugins/cloud/microsoft/office365/exchange/mode/mailboxusage.pm b/centreon-plugins/cloud/microsoft/office365/exchange/mode/mailboxusage.pm new file mode 100644 index 000000000..76eb6b7c0 --- /dev/null +++ b/centreon-plugins/cloud/microsoft/office365/exchange/mode/mailboxusage.pm @@ -0,0 +1,210 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 cloud::microsoft::office365::exchange::mode::mailboxusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $instance_mode; + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + + $self->{output}->perfdata_add(label => 'used' . $extra_label, + unit => 'B', + value => $self->{result_values}->{used}, + min => 0); +} + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($issue_warning_quota_value, $issue_warning_quota_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{issue_warning_quota}); + my ($prohibit_send_quota_value, $prohibit_send_quota_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{prohibit_send_quota}); + my ($prohibit_send_receive_quota_value, $prohibit_send_receive_quota_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{prohibit_send_receive_quota}); + + my $msg = sprintf("Used: %s Issue Warning Quota: %s Prohibit Send Quota: %s Prohibit Send/Receive Quota: %s", + $used_value . " " . $used_unit, + $issue_warning_quota_value . " " . $issue_warning_quota_unit, + $prohibit_send_quota_value . " " . $prohibit_send_quota_unit, + $prohibit_send_receive_quota_value . " " . $prohibit_send_receive_quota_unit); + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_storage_used'}; + $self->{result_values}->{issue_warning_quota} = $options{new_datas}->{$self->{instance} . '_issue_warning_quota'}; + $self->{result_values}->{prohibit_send_quota} = $options{new_datas}->{$self->{instance} . '_prohibit_send_quota'}; + $self->{result_values}->{prohibit_send_receive_quota} = $options{new_datas}->{$self->{instance} . '_prohibit_send_receive_quota'}; + return 0; +} + +sub prefix_user_output { + my ($self, %options) = @_; + + return "User '" . $options{instance_value}->{name} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'users', type => 1, cb_prefix_output => 'prefix_user_output', message_multiple => 'All mailbox usage are ok' }, + ]; + + $self->{maps_counters}->{users} = [ + { label => 'usage', set => { + key_values => [ { name => 'storage_used' }, { name => 'issue_warning_quota' }, + { name => 'prohibit_send_quota' }, { name => 'prohibit_send_receive_quota' }, { name => 'name' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-user:s" => { name => 'filter_user' }, + "warning-status:s" => { name => 'warning_status', default => '%{storage_used} > %{issue_warning_quota}' }, + "critical-status:s" => { name => 'critical_status', default => '%{storage_used} > %{prohibit_send_quota}' }, + }); + + return $self; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{users} = {}; + + my $results = $options{custom}->office_get_exchange_mailbox_usage(); + + foreach my $user (@{$results}) { + if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && + $user->{'User Principal Name'} !~ /$self->{option_results}->{filter_user}/) { + $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no matching filter name.", debug => 1); + next; + } + + $self->{users}->{$user->{'User Principal Name'}}->{name} = $user->{'User Principal Name'}; + $self->{users}->{$user->{'User Principal Name'}}->{storage_used} = $user->{'Storage Used (Byte)'}; + $self->{users}->{$user->{'User Principal Name'}}->{issue_warning_quota} = $user->{'Issue Warning Quota (Byte)'}; + $self->{users}->{$user->{'User Principal Name'}}->{prohibit_send_quota} = $user->{'Prohibit Send Quota (Byte)'}; + $self->{users}->{$user->{'User Principal Name'}}->{prohibit_send_receive_quota} = $user->{'Prohibit Send/Receive Quota (Byte)'}; + $self->{users}->{$user->{'User Principal Name'}}->{last_activity_date} = $user->{'Last Activity Date'}; + } + + if (scalar(keys %{$self->{users}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No entry found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check mailbox usage (reporting period over the last 7 days). + +(See link for details about metrics : +https://docs.microsoft.com/en-us/office365/admin/activity-reports/mailbox-usage?view=o365-worldwide) + +=over 8 + +=item B<--filter-user> + +Filter users. + +=item B<--warning-status> + +Set warning threshold for status (Default: '%{storage_used} > %{issue_warning_quota}'). +Can used special variables like: %{used}, %{issue_warning_quota}, %{prohibit_send_quota}, %{prohibit_send_receive_quota} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{storage_used} > %{prohibit_send_quota}'). +Can used special variables like: %{used}, %{issue_warning_quota}, %{prohibit_send_quota}, %{prohibit_send_receive_quota} + +=back + +=cut diff --git a/centreon-plugins/cloud/microsoft/office365/exchange/plugin.pm b/centreon-plugins/cloud/microsoft/office365/exchange/plugin.pm new file mode 100644 index 000000000..c0ffe81c1 --- /dev/null +++ b/centreon-plugins/cloud/microsoft/office365/exchange/plugin.pm @@ -0,0 +1,50 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 cloud::microsoft::office365::exchange::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_custom); + +sub new { + my ( $class, %options ) = @_; + my $self = $class->SUPER::new( package => __PACKAGE__, %options ); + bless $self, $class; + + $self->{version} = '0.1'; + %{ $self->{modes} } = ( + 'email-activity' => 'cloud::microsoft::office365::exchange::mode::emailactivity', + 'mailbox-usage' => 'cloud::microsoft::office365::exchange::mode::mailboxusage', + ); + + $self->{custom_modes}{graphapi} = 'cloud::microsoft::office365::custom::graphapi'; + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Microsoft Office 365 Exchange. + +=cut From ec0c5e2aebad6a38ee2478f65c48dc81a0cba1ae Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Fri, 28 Dec 2018 10:56:02 +0100 Subject: [PATCH 20/23] fix template counter short output handling --- centreon-plugins/centreon/plugins/templates/counter.pm | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/centreon-plugins/centreon/plugins/templates/counter.pm b/centreon-plugins/centreon/plugins/templates/counter.pm index 6d44a1695..c6c060d21 100644 --- a/centreon-plugins/centreon/plugins/templates/counter.pm +++ b/centreon-plugins/centreon/plugins/templates/counter.pm @@ -293,7 +293,7 @@ sub run_instances { $prefix_output = '' if (!defined($prefix_output)); $suffix_output = $self->call_object_callback(method_name => $options{config}->{cb_suffix_output}) if (defined($options{config}->{cb_suffix_output})); $suffix_output = '' if (!defined($suffix_output)); - + my $exit = $self->{output}->get_most_critical(status => [ @exits ]); # in mode grouped, we don't display 'ok' my $debug = 0; @@ -312,9 +312,7 @@ sub run_instances { ); } - if ($self->{multiple_lvl1} == 0 && $multiple_lvl2 == 0 && !$options{multi}) { - $self->{output}->output_add(short_msg => $prefix_output . $long_msg . $suffix_output); - } + $self->{output}->output_add(short_msg => $prefix_output . $long_msg . $suffix_output) unless ($self->{multiple_lvl1} == 1 || ($multiple_lvl2 == 1 && !defined($options{multi}))); if ($options{multi}) { foreach my $counter (@{$options{config}->{counters}}) { From 64c62076287960040a79be4852cac1fcf9328fec Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Fri, 28 Dec 2018 11:32:27 +0100 Subject: [PATCH 21/23] enh office365 plugins (#1296) * enh office365 plugins, add active-only option, fix exchange plugin * small typo in help * fix wrong key in debug --- .../office365/exchange/mode/emailactivity.pm | 43 +++++++------ .../office365/exchange/mode/mailboxusage.pm | 60 ++++++++++++------- .../office365/onedrive/mode/usage.pm | 9 +++ .../office365/sharepoint/mode/siteusage.pm | 17 +++++- .../sharepoint/mode/usersactivity.pm | 9 +++ 5 files changed, 97 insertions(+), 41 deletions(-) diff --git a/centreon-plugins/cloud/microsoft/office365/exchange/mode/emailactivity.pm b/centreon-plugins/cloud/microsoft/office365/exchange/mode/emailactivity.pm index 26d90e713..e64fe8843 100644 --- a/centreon-plugins/cloud/microsoft/office365/exchange/mode/emailactivity.pm +++ b/centreon-plugins/cloud/microsoft/office365/exchange/mode/emailactivity.pm @@ -25,7 +25,7 @@ use base qw(centreon::plugins::templates::counter); use strict; use warnings; -sub prefix_user_output { +sub prefix_mailbox_output { my ($self, %options) = @_; return "User '" . $options{instance_value}->{name} . "' "; @@ -35,10 +35,10 @@ sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ - { name => 'users', type => 1, cb_prefix_output => 'prefix_user_output', message_multiple => 'All email activity are ok' }, + { name => 'mailboxes', type => 1, cb_prefix_output => 'prefix_mailbox_output', message_multiple => 'All email activity are ok' }, ]; - $self->{maps_counters}->{users} = [ + $self->{maps_counters}->{mailboxes} = [ { label => 'send-count', set => { key_values => [ { name => 'send_count' }, { name => 'name' } ], output_template => 'Send Count: %d', @@ -82,7 +82,8 @@ sub new { $self->{version} = '1.0'; $options{options}->add_options(arguments => { - "filter-user:s" => { name => 'filter_user' }, + "filter-mailbox:s" => { name => 'filter_mailbox' }, + "active-only" => { name => 'active_only' }, }); return $self; @@ -96,25 +97,29 @@ sub check_options { sub manage_selection { my ($self, %options) = @_; - $self->{users} = {}; + $self->{mailboxes} = {}; my $results = $options{custom}->office_get_exchange_activity(); - foreach my $user (@{$results}) { - if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && - $user->{'User Principal Name'} !~ /$self->{option_results}->{filter_user}/) { - $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no matching filter name.", debug => 1); + foreach my $mailbox (@{$results}) { + if (defined($self->{option_results}->{filter_mailbox}) && $self->{option_results}->{filter_mailbox} ne '' && + $mailbox->{'User Principal Name'} !~ /$self->{option_results}->{filter_mailbox}/) { + $self->{output}->output_add(long_msg => "skipping '" . $mailbox->{'User Principal Name'} . "': no matching filter name.", debug => 1); + next; + } + if ($self->{option_results}->{active_only} && defined($mailbox->{'Last Activity Date'}) && $mailbox->{'Last Activity Date'} eq '') { + $self->{output}->output_add(long_msg => "skipping '" . $mailbox->{'User Principal Name'} . "': no activity.", debug => 1); next; } - $self->{users}->{$user->{'User Principal Name'}}->{name} = $user->{'User Principal Name'}; - $self->{users}->{$user->{'User Principal Name'}}->{send_count} = $user->{'Send Count'}; - $self->{users}->{$user->{'User Principal Name'}}->{receive_count} = $user->{'Receive Count'}; - $self->{users}->{$user->{'User Principal Name'}}->{read_count} = $user->{'Read Count'}; - $self->{users}->{$user->{'User Principal Name'}}->{last_activity_date} = $user->{'Last Activity Date'}; + $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{name} = $mailbox->{'User Principal Name'}; + $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{send_count} = $mailbox->{'Send Count'}; + $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{receive_count} = $mailbox->{'Receive Count'}; + $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{read_count} = $mailbox->{'Read Count'}; + $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{last_activity_date} = $mailbox->{'Last Activity Date'}; } - if (scalar(keys %{$self->{users}}) <= 0) { + if (scalar(keys %{$self->{mailboxes}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No entry found."); $self->{output}->option_exit(); } @@ -133,9 +138,9 @@ https://docs.microsoft.com/en-us/office365/admin/activity-reports/email-activity =over 8 -=item B<--filter-user> +=item B<--filter-mailbox> -Filter users. +Filter mailboxes. =item B<--warning-*> @@ -147,6 +152,10 @@ Can be: 'send-count', 'receive-count', 'read-count'. Threshold critical. Can be: 'send-count', 'receive-count', 'read-count'. +=item B<--active-only> + +Filter only active entries ('Last Activity' set). + =back =cut diff --git a/centreon-plugins/cloud/microsoft/office365/exchange/mode/mailboxusage.pm b/centreon-plugins/cloud/microsoft/office365/exchange/mode/mailboxusage.pm index 76eb6b7c0..46e690813 100644 --- a/centreon-plugins/cloud/microsoft/office365/exchange/mode/mailboxusage.pm +++ b/centreon-plugins/cloud/microsoft/office365/exchange/mode/mailboxusage.pm @@ -90,20 +90,20 @@ sub custom_status_calc { return 0; } -sub prefix_user_output { +sub prefix_mailbox_output { my ($self, %options) = @_; - return "User '" . $options{instance_value}->{name} . "' "; + return "Mailbox '" . $options{instance_value}->{name} . "' "; } sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ - { name => 'users', type => 1, cb_prefix_output => 'prefix_user_output', message_multiple => 'All mailbox usage are ok' }, + { name => 'mailboxes', type => 1, cb_prefix_output => 'prefix_mailbox_output', message_multiple => 'All mailboxes usage are ok' }, ]; - $self->{maps_counters}->{users} = [ + $self->{maps_counters}->{mailboxes} = [ { label => 'usage', set => { key_values => [ { name => 'storage_used' }, { name => 'issue_warning_quota' }, { name => 'prohibit_send_quota' }, { name => 'prohibit_send_receive_quota' }, { name => 'name' } ], @@ -113,6 +113,11 @@ sub set_counters { closure_custom_threshold_check => $self->can('custom_status_threshold'), } }, + { label => 'last-activity', threshold => 0, set => { + key_values => [ { name => 'last_activity_date' }, { name => 'name' } ], + output_template => 'Last Activity: %s', + } + }, ]; } @@ -124,9 +129,10 @@ sub new { $self->{version} = '1.0'; $options{options}->add_options(arguments => { - "filter-user:s" => { name => 'filter_user' }, - "warning-status:s" => { name => 'warning_status', default => '%{storage_used} > %{issue_warning_quota}' }, - "critical-status:s" => { name => 'critical_status', default => '%{storage_used} > %{prohibit_send_quota}' }, + "filter-mailbox:s" => { name => 'filter_mailbox' }, + "warning-status:s" => { name => 'warning_status', default => '%{used} > %{issue_warning_quota}' }, + "critical-status:s" => { name => 'critical_status', default => '%{used} > %{prohibit_send_quota}' }, + "active-only" => { name => 'active_only' }, }); return $self; @@ -153,26 +159,30 @@ sub check_options { sub manage_selection { my ($self, %options) = @_; - $self->{users} = {}; + $self->{mailboxes} = {}; my $results = $options{custom}->office_get_exchange_mailbox_usage(); - foreach my $user (@{$results}) { - if (defined($self->{option_results}->{filter_user}) && $self->{option_results}->{filter_user} ne '' && - $user->{'User Principal Name'} !~ /$self->{option_results}->{filter_user}/) { - $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no matching filter name.", debug => 1); + foreach my $mailbox (@{$results}) { + if (defined($self->{option_results}->{filter_mailbox}) && $self->{option_results}->{filter_mailbox} ne '' && + $mailbox->{'User Principal Name'} !~ /$self->{option_results}->{filter_mailbox}/) { + $self->{output}->output_add(long_msg => "skipping '" . $mailbox->{'User Principal Name'} . "': no matching filter name.", debug => 1); + next; + } + if ($self->{option_results}->{active_only} && defined($mailbox->{'Last Activity Date'}) && $mailbox->{'Last Activity Date'} eq '') { + $self->{output}->output_add(long_msg => "skipping '" . $mailbox->{'User Principal Name'} . "': no activity.", debug => 1); next; } - $self->{users}->{$user->{'User Principal Name'}}->{name} = $user->{'User Principal Name'}; - $self->{users}->{$user->{'User Principal Name'}}->{storage_used} = $user->{'Storage Used (Byte)'}; - $self->{users}->{$user->{'User Principal Name'}}->{issue_warning_quota} = $user->{'Issue Warning Quota (Byte)'}; - $self->{users}->{$user->{'User Principal Name'}}->{prohibit_send_quota} = $user->{'Prohibit Send Quota (Byte)'}; - $self->{users}->{$user->{'User Principal Name'}}->{prohibit_send_receive_quota} = $user->{'Prohibit Send/Receive Quota (Byte)'}; - $self->{users}->{$user->{'User Principal Name'}}->{last_activity_date} = $user->{'Last Activity Date'}; + $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{name} = $mailbox->{'User Principal Name'}; + $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{storage_used} = ($mailbox->{'Storage Used (Byte)'} ne '') ? $mailbox->{'Storage Used (Byte)'} : 0; + $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{issue_warning_quota} = $mailbox->{'Issue Warning Quota (Byte)'}; + $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{prohibit_send_quota} = $mailbox->{'Prohibit Send Quota (Byte)'}; + $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{prohibit_send_receive_quota} = $mailbox->{'Prohibit Send/Receive Quota (Byte)'}; + $self->{mailboxes}->{$mailbox->{'User Principal Name'}}->{last_activity_date} = $mailbox->{'Last Activity Date'}; } - if (scalar(keys %{$self->{users}}) <= 0) { + if (scalar(keys %{$self->{mailboxes}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No entry found."); $self->{output}->option_exit(); } @@ -191,20 +201,24 @@ https://docs.microsoft.com/en-us/office365/admin/activity-reports/mailbox-usage? =over 8 -=item B<--filter-user> +=item B<--filter-mailbox> -Filter users. +Filter mailboxes. =item B<--warning-status> -Set warning threshold for status (Default: '%{storage_used} > %{issue_warning_quota}'). +Set warning threshold for status (Default: '%{used} > %{issue_warning_quota}'). Can used special variables like: %{used}, %{issue_warning_quota}, %{prohibit_send_quota}, %{prohibit_send_receive_quota} =item B<--critical-status> -Set critical threshold for status (Default: '%{storage_used} > %{prohibit_send_quota}'). +Set critical threshold for status (Default: '%{used} > %{prohibit_send_quota}'). Can used special variables like: %{used}, %{issue_warning_quota}, %{prohibit_send_quota}, %{prohibit_send_receive_quota} +=item B<--active-only> + +Filter only active entries ('Last Activity' set). + =back =cut diff --git a/centreon-plugins/cloud/microsoft/office365/onedrive/mode/usage.pm b/centreon-plugins/cloud/microsoft/office365/onedrive/mode/usage.pm index b887b5f1f..af9da5a3c 100644 --- a/centreon-plugins/cloud/microsoft/office365/onedrive/mode/usage.pm +++ b/centreon-plugins/cloud/microsoft/office365/onedrive/mode/usage.pm @@ -151,6 +151,7 @@ sub new { "filter-owner:s" => { name => 'filter_owner' }, "units:s" => { name => 'units', default => '%' }, "free" => { name => 'free' }, + "active-only" => { name => 'active_only' }, }); return $self; @@ -181,6 +182,10 @@ sub manage_selection { $self->{output}->output_add(long_msg => "skipping '" . $site->{'Owner Display Name'} . "': no matching filter name.", debug => 1); next; } + if ($self->{option_results}->{active_only} && defined($site->{'Last Activity Date'}) && $site->{'Last Activity Date'} eq '') { + $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site URL'} . "': no activity.", debug => 1); + next; + } $self->{sites}->{$site->{'Site URL'}}->{url} = $site->{'Site URL'}; $self->{sites}->{$site->{'Site URL'}}->{owner} = $site->{'Owner Display Name'}; @@ -225,6 +230,10 @@ Can be: 'usage', 'file-count', 'active-file-count'. Threshold critical. Can be: 'usage', 'file-count', 'active-file-count'. +=item B<--active-only> + +Filter only active entries ('Last Activity' set). + =back =cut diff --git a/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/siteusage.pm b/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/siteusage.pm index 8fe5af9ea..a36ff4019 100644 --- a/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/siteusage.pm +++ b/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/siteusage.pm @@ -149,6 +149,11 @@ sub set_counters { ], } }, + { label => 'last-activity', threshold => 0, set => { + key_values => [ { name => 'last_activity_date' }, { name => 'url' }, { name => 'id' } ], + output_template => 'Last Activity: %s', + } + }, ]; } @@ -164,6 +169,7 @@ sub new { "filter-id:s" => { name => 'filter_id' }, "units:s" => { name => 'units', default => '%' }, "free" => { name => 'free' }, + "active-only" => { name => 'active_only' }, }); return $self; @@ -194,7 +200,11 @@ sub manage_selection { $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site Id'} . "': no matching filter name.", debug => 1); next; } - + if ($self->{option_results}->{active_only} && defined($site->{'Last Activity Date'}) && $site->{'Last Activity Date'} eq '') { + $self->{output}->output_add(long_msg => "skipping '" . $site->{'Site URL'} . "': no activity.", debug => 1); + next; + } + $self->{sites}->{$site->{'Site Id'}}->{id} = $site->{'Site Id'}; $self->{sites}->{$site->{'Site Id'}}->{url} = $site->{'Site URL'}; $self->{sites}->{$site->{'Site Id'}}->{file_count} = $site->{'File Count'}; @@ -203,6 +213,7 @@ sub manage_selection { $self->{sites}->{$site->{'Site Id'}}->{page_view_count} = $site->{'Page View Count'}; $self->{sites}->{$site->{'Site Id'}}->{storage_used} = $site->{'Storage Used (Byte)'}; $self->{sites}->{$site->{'Site Id'}}->{storage_allocated} = $site->{'Storage Allocated (Byte)'}; + $self->{sites}->{$site->{'Site Id'}}->{last_activity_date} = $site->{'Last Activity Date'}; } if (scalar(keys %{$self->{sites}}) <= 0) { @@ -241,6 +252,10 @@ Threshold critical. Can be: 'usage', 'file-count', 'active-file-count', 'visited-file-count', 'page-view-count'. +=item B<--active-only> + +Filter only active entries ('Last Activity' set). + =back =cut diff --git a/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/usersactivity.pm b/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/usersactivity.pm index b5c532a8b..bf1c1ba3e 100644 --- a/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/usersactivity.pm +++ b/centreon-plugins/cloud/microsoft/office365/sharepoint/mode/usersactivity.pm @@ -101,6 +101,7 @@ sub new { $options{options}->add_options(arguments => { "filter-user:s" => { name => 'filter_user' }, + "active-only" => { name => 'active_only' }, }); return $self; @@ -124,6 +125,10 @@ sub manage_selection { $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no matching filter name.", debug => 1); next; } + if ($self->{option_results}->{active_only} && defined($user->{'Last Activity Date'}) && $user->{'Last Activity Date'} eq '') { + $self->{output}->output_add(long_msg => "skipping '" . $user->{'User Principal Name'} . "': no activity.", debug => 1); + next; + } $self->{users}->{$user->{'User Principal Name'}}->{name} = $user->{'User Principal Name'}; $self->{users}->{$user->{'User Principal Name'}}->{viewed_edited_file_count} = $user->{'Viewed Or Edited File Count'}; @@ -169,6 +174,10 @@ Threshold critical. Can be: 'viewed-edited-file-count', 'file-count', 'shared-int-file-count', 'shared-ext-file-count', 'visited-page-count'. +=item B<--active-only> + +Filter only active entries ('Last Activity' set). + =back =cut From 0d0fe5610b84801d2a6151e6db0e04bff8317afe Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Fri, 28 Dec 2018 14:58:13 +0100 Subject: [PATCH 22/23] enh juniper mseries plugin --- .../common/junos/mode/ldpsessionstatus.pm | 233 ++++++++++++++++ .../juniper/common/junos/mode/lspstatus.pm | 256 ++++++++++++++++++ .../common/junos/mode/rsvpsessionstatus.pm | 219 +++++++++++++++ .../network/juniper/mseries/plugin.pm | 7 +- 4 files changed, 713 insertions(+), 2 deletions(-) create mode 100644 centreon-plugins/network/juniper/common/junos/mode/ldpsessionstatus.pm create mode 100644 centreon-plugins/network/juniper/common/junos/mode/lspstatus.pm create mode 100644 centreon-plugins/network/juniper/common/junos/mode/rsvpsessionstatus.pm diff --git a/centreon-plugins/network/juniper/common/junos/mode/ldpsessionstatus.pm b/centreon-plugins/network/juniper/common/junos/mode/ldpsessionstatus.pm new file mode 100644 index 000000000..5d44d3ede --- /dev/null +++ b/centreon-plugins/network/juniper/common/junos/mode/ldpsessionstatus.pm @@ -0,0 +1,233 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 network::juniper::common::junos::mode::ldpsessionstatus; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = "status is '" . $self->{result_values}->{state} . "'"; + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_jnxMplsLdpSesState'}; + return 0; +} + +sub prefix_session_output { + my ($self, %options) = @_; + + return "Session between LDP entity '" . $options{instance_value}->{jnxMplsLdpEntityLdpId} . "' and LDP peer '" . $options{instance_value}->{jnxMplsLdpPeerLdpId} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'sessions', type => 1, cb_prefix_output => 'prefix_session_output', message_multiple => 'All sessions status are ok' }, + ]; + + $self->{maps_counters}->{sessions} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'jnxMplsLdpSesState' }, { name => 'jnxMplsLdpEntityLdpId' }, + { name => 'jnxMplsLdpPeerLdpId' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + { label => 'last-change', set => { + key_values => [ { name => 'jnxMplsLdpSesStateLastChangeHuman' }, { name => 'jnxMplsLdpSesStateLastChange' }, + { name => 'label' } ], + output_template => 'Last change: %s', + perfdatas => [ + { label => 'last_change', value => 'jnxMplsLdpSesStateLastChange_absolute', template => '%d', + min => 0, unit => 's', label_extra_instance => 1, instance_use => 'label_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-entity:s" => { name => 'filter_entity' }, + "filter-peer:s" => { name => 'filter_peer' }, + "warning-status:s" => { name => 'warning_status' }, + "critical-status:s" => { name => 'critical_status', default => '%{state} !~ /operational/i' }, + }); + + return $self; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +my %map_state = ( + 1 => 'nonexistent', + 2 => 'initialized', + 3 => 'openrec', + 4 => 'opensent', + 5 => 'operational', +); + +my $mapping = { + jnxMplsLdpSesStateLastChange => { oid => '.1.3.6.1.4.1.2636.3.36.1.3.3.1.1' }, + jnxMplsLdpSesState => { oid => '.1.3.6.1.4.1.2636.3.36.1.3.3.1.2', map => \%map_state }, +}; + +my $oid_jnxMplsLdpSessionEntry = '.1.3.6.1.4.1.2636.3.36.1.3.3.1'; + +sub manage_selection { + my ($self, %options) = @_; + + $self->{sessions} = {}; + + my $results = $options{snmp}->get_table(oid => $oid_jnxMplsLdpSessionEntry, start => $mapping->{jnxMplsLdpSesStateLastChange}->{oid}, + end => $mapping->{jnxMplsLdpSesState}->{oid}, nothing_quit => 1); + + foreach my $oid (keys %{$results}) { + next if ($oid !~ /^$mapping->{jnxMplsLdpSesState}->{oid}\.(.*)/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $results, instance => $instance); + + $instance =~ /^(\d+\.\d+\.\d+\.\d+)\.(\d+)\.\d+\.\d+\.(\d+\.\d+\.\d+\.\d+)\.(\d+)\.\d+$/; + my $ldp_entity = $1 . ':' . $2; + my $ldp_peer = $3 . ':' . $4; + + if (defined($self->{option_results}->{filter_entity}) && $self->{option_results}->{filter_entity} ne '' && + $ldp_entity !~ /$self->{option_results}->{filter_entity}/) { + $self->{output}->output_add(long_msg => "skipping entity '" . $ldp_entity . "': no matching filter name.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_peer}) && $self->{option_results}->{filter_peer} ne '' && + $ldp_peer !~ /$self->{option_results}->{filter_peer}/) { + $self->{output}->output_add(long_msg => "skipping peer '" . $ldp_peer . "': no matching filter name.", debug => 1); + next; + } + + $self->{sessions}->{$instance} = { + jnxMplsLdpSesStateLastChange => $result->{jnxMplsLdpSesStateLastChange} / 100, + jnxMplsLdpSesStateLastChangeHuman => centreon::plugins::misc::change_seconds(value => $result->{jnxMplsLdpSesStateLastChange} / 100), + jnxMplsLdpSesState => $result->{jnxMplsLdpSesState}, + jnxMplsLdpEntityLdpId => $ldp_entity, + jnxMplsLdpPeerLdpId => $ldp_peer, + label => $ldp_entity . "_". $ldp_peer, + } + } + + if (scalar(keys %{$self->{sessions}}) <= 0) { + $self->{output}->add_option_msg(short_msg => 'No sessions found.'); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check sessions status between the LDP entities and LDP peers. + +=over 8 + +=item B<--filter-*> + +Filter entities and/or peer. +Can be: 'entity', 'peer' (can be a regexp). + +=item B<--warning-status> + +Set warning threshold for status (Default: ''). +Can used special variables like: %{state} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{state} !~ /operational/i'). +Can used special variables like: %{state} + +=item B<--warning-last-change> + +Threshold warning in seconds. + +=item B<--critical-last-change> + +Threshold critical in seconds. + +=back + +=cut diff --git a/centreon-plugins/network/juniper/common/junos/mode/lspstatus.pm b/centreon-plugins/network/juniper/common/junos/mode/lspstatus.pm new file mode 100644 index 000000000..eb9f34307 --- /dev/null +++ b/centreon-plugins/network/juniper/common/junos/mode/lspstatus.pm @@ -0,0 +1,256 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 network::juniper::common::junos::mode::lspstatus; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = "status is '" . $self->{result_values}->{state} . "'"; + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_mplsLspState'}; + return 0; +} + +sub prefix_session_output { + my ($self, %options) = @_; + + return "LSP '" . $options{instance_value}->{mplsLspName} . "' [From '" . $options{instance_value}->{mplsLspFrom} . "' to '" . $options{instance_value}->{mplsLspTo} . "'] "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'lsps', type => 1, cb_prefix_output => 'prefix_session_output', message_multiple => 'All LSP status are ok' }, + ]; + + $self->{maps_counters}->{lsps} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'mplsLspState' }, { name => 'mplsLspFrom' }, + { name => 'mplsLspTo' }, { name => 'mplsLspName' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + { label => 'transition-count', set => { + key_values => [ { name => 'mplsLspInfoTransitions' }, { name => 'mplsLspName' } ], + output_template => 'Transition count: %d', + perfdatas => [ + { label => 'transition_count', value => 'mplsLspInfoTransitions_absolute', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'mplsLspName_absolute' }, + ], + } + }, + { label => 'last-transition', set => { + key_values => [ { name => 'mplsLspInfoLastTransitionHuman' }, { name => 'mplsLspInfoLastTransition' }, + { name => 'mplsLspName' } ], + output_template => 'Last transition: %s', + perfdatas => [ + { label => 'last_transition', value => 'mplsLspInfoLastTransition_absolute', template => '%d', + min => 0, unit => 's', label_extra_instance => 1, instance_use => 'mplsLspName_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "filter-from:s" => { name => 'filter_from' }, + "filter-to:s" => { name => 'filter_to' }, + "warning-status:s" => { name => 'warning_status' }, + "critical-status:s" => { name => 'critical_status', default => '%{state} !~ /up/i' }, + }); + + return $self; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +my %map_state = ( + 1 => 'unknown', + 2 => 'up', + 3 => 'down', + 4 => 'notInService', + 5 => 'backupActive', +); + +my $mapping = { + mplsLspState => { oid => '.1.3.6.1.4.1.2636.3.2.5.1.2', map => \%map_state }, + mplsLspInfoTransitions => { oid => '.1.3.6.1.4.1.2636.3.2.5.1.8' }, + mplsLspInfoLastTransition => { oid => '.1.3.6.1.4.1.2636.3.2.5.1.9' }, + mplsLspFrom => { oid => '.1.3.6.1.4.1.2636.3.2.5.1.15' }, + mplsLspTo => { oid => '.1.3.6.1.4.1.2636.3.2.5.1.16' }, +}; + +my $oid_mplsLspEntry = '.1.3.6.1.4.1.2636.3.2.5.1'; + +sub manage_selection { + my ($self, %options) = @_; + + $self->{lsps} = {}; + + my $results = $options{snmp}->get_table(oid => $oid_mplsLspEntry, start => $mapping->{mplsLspState}->{oid}, + end => $mapping->{mplsLspTo}->{oid}, nothing_quit => 1); + + foreach my $oid (keys %{$results}) { + next if ($oid !~ /^$mapping->{mplsLspState}->{oid}\.(.*)/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $results, instance => $instance); + + my $mplsLspName = ''; + foreach (split /\./, $instance) { + $mplsLspName .= chr if ($_ >= 32 && $_ <= 126); + } + $mplsLspName = centreon::plugins::misc::trim($mplsLspName); + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $mplsLspName !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping session '" . $mplsLspName . "': no matching filter name.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_from}) && $self->{option_results}->{filter_from} ne '' && + $result->{mplsLspFrom} !~ /$self->{option_results}->{filter_from}/) { + $self->{output}->output_add(long_msg => "skipping session '" . $result->{mplsLspFrom} . "': no matching filter from.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_to}) && $self->{option_results}->{filter_to} ne '' && + $result->{mplsLspTo} !~ /$self->{option_results}->{filter_to}/) { + $self->{output}->output_add(long_msg => "skipping peer '" . $result->{mplsLspTo} . "': no matching filter to.", debug => 1); + next; + } + + $self->{lsps}->{$instance} = { + mplsLspName => $mplsLspName, + mplsLspState => $result->{mplsLspState}, + mplsLspInfoTransitions => $result->{mplsLspInfoTransitions}, + mplsLspInfoLastTransition => $result->{mplsLspInfoLastTransition} / 100, + mplsLspInfoLastTransitionHuman => centreon::plugins::misc::change_seconds(value => $result->{mplsLspInfoLastTransition} / 100), + mplsLspFrom => $result->{mplsLspFrom}, + mplsLspTo => $result->{mplsLspTo}, + } + } + + if (scalar(keys %{$self->{lsps}}) <= 0) { + $self->{output}->add_option_msg(short_msg => 'No entries found.'); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check LSPs (Label Switched Path) status. + +=over 8 + +=item B<--filter-*> + +Filter LSPs. +Can be: 'name', 'from', 'to' (can be a regexp). + +=item B<--warning-status> + +Set warning threshold for status (Default: ''). +Can used special variables like: %{state} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{state} !~ /up/i'). +Can used special variables like: %{state} + +=item B<--warning-*> + +Threshold warning. +Can be: 'transition-count', 'last-transition' (seconds). + +=item B<--critical-*> + +Threshold critical. +Can be: 'transition-count', 'last-transition' (seconds). + +=back + +=cut diff --git a/centreon-plugins/network/juniper/common/junos/mode/rsvpsessionstatus.pm b/centreon-plugins/network/juniper/common/junos/mode/rsvpsessionstatus.pm new file mode 100644 index 000000000..f6bc88917 --- /dev/null +++ b/centreon-plugins/network/juniper/common/junos/mode/rsvpsessionstatus.pm @@ -0,0 +1,219 @@ +# +# Copyright 2018 Centreon (http://www.centreon.com/) +# +# 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 network::juniper::common::junos::mode::rsvpsessionstatus; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = "status is '" . $self->{result_values}->{state} . "'"; + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_jnxRsvpSessionState'}; + return 0; +} + +sub prefix_session_output { + my ($self, %options) = @_; + + return "Session '" . $options{instance_value}->{jnxRsvpSessionName} . "' [From '" . $options{instance_value}->{jnxRsvpSessionFrom} . "' to '" . $options{instance_value}->{jnxRsvpSessionTo} . "'] "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'sessions', type => 1, cb_prefix_output => 'prefix_session_output', message_multiple => 'All sessions status are ok' }, + ]; + + $self->{maps_counters}->{sessions} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'jnxRsvpSessionState' }, { name => 'jnxRsvpSessionFrom' }, + { name => 'jnxRsvpSessionTo' }, { name => 'jnxRsvpSessionName' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "filter-from:s" => { name => 'filter_from' }, + "filter-to:s" => { name => 'filter_to' }, + "warning-status:s" => { name => 'warning_status' }, + "critical-status:s" => { name => 'critical_status', default => '%{state} !~ /up/i' }, + }); + + return $self; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +my %map_state = ( + 1 => 'up', + 2 => 'down', +); + +my $mapping = { + jnxRsvpSessionState => { oid => '.1.3.6.1.4.1.2636.3.30.1.1.1.3', map => \%map_state }, + jnxRsvpSessionFrom => { oid => '.1.3.6.1.4.1.2636.3.30.1.1.1.4' }, + jnxRsvpSessionTo => { oid => '.1.3.6.1.4.1.2636.3.30.1.1.1.5' }, +}; + +my $oid_JnxRsvpSessionEntry = '.1.3.6.1.4.1.2636.3.30.1.1.1'; + +sub manage_selection { + my ($self, %options) = @_; + + $self->{sessions} = {}; + + my $results = $options{snmp}->get_table(oid => $oid_JnxRsvpSessionEntry, start => $mapping->{jnxRsvpSessionState}->{oid}, + end => $mapping->{jnxRsvpSessionTo}->{oid}, nothing_quit => 1); + + foreach my $oid (keys %{$results}) { + next if ($oid !~ /^$mapping->{jnxRsvpSessionState}->{oid}\.(.*)/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $results, instance => $instance); + + my $jnxRsvpSessionName = ''; + foreach (split /\./, $instance) { + $jnxRsvpSessionName .= chr if ($_ >= 32 && $_ <= 126); + } + $jnxRsvpSessionName = centreon::plugins::misc::trim($jnxRsvpSessionName); + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $jnxRsvpSessionName !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping session '" . $jnxRsvpSessionName . "': no matching filter name.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_from}) && $self->{option_results}->{filter_from} ne '' && + $result->{jnxRsvpSessionFrom} !~ /$self->{option_results}->{filter_from}/) { + $self->{output}->output_add(long_msg => "skipping session '" . $result->{jnxRsvpSessionFrom} . "': no matching filter from.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_to}) && $self->{option_results}->{filter_to} ne '' && + $result->{jnxRsvpSessionTo} !~ /$self->{option_results}->{filter_to}/) { + $self->{output}->output_add(long_msg => "skipping peer '" . $result->{jnxRsvpSessionTo} . "': no matching filter to.", debug => 1); + next; + } + + $self->{sessions}->{$instance} = { + jnxRsvpSessionName => $jnxRsvpSessionName, + jnxRsvpSessionState => $result->{jnxRsvpSessionState}, + jnxRsvpSessionFrom => $result->{jnxRsvpSessionFrom}, + jnxRsvpSessionTo => $result->{jnxRsvpSessionTo}, + } + } + + if (scalar(keys %{$self->{sessions}}) <= 0) { + $self->{output}->add_option_msg(short_msg => 'No sessions found.'); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check RSVP sessions status. + +=over 8 + +=item B<--filter-*> + +Filter sessions. +Can be: 'name', 'from', 'to' (can be a regexp). + +=item B<--warning-status> + +Set warning threshold for status (Default: ''). +Can used special variables like: %{state} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{state} !~ /up/i'). +Can used special variables like: %{state} + +=back + +=cut diff --git a/centreon-plugins/network/juniper/mseries/plugin.pm b/centreon-plugins/network/juniper/mseries/plugin.pm index ce71c95ce..cff8418e9 100644 --- a/centreon-plugins/network/juniper/mseries/plugin.pm +++ b/centreon-plugins/network/juniper/mseries/plugin.pm @@ -31,12 +31,15 @@ sub new { $self->{version} = '1.0'; %{$self->{modes}} = ( - 'hardware' => 'network::juniper::common::junos::mode::hardware', 'cpu-routing' => 'network::juniper::common::junos::mode::cpurouting', # routing engine - 'memory-routing' => 'network::juniper::common::junos::mode::memoryrouting', # routing engine + 'hardware' => 'network::juniper::common::junos::mode::hardware', 'interfaces' => 'snmp_standard::mode::interfaces', + 'ldp-session-status' => 'network::juniper::common::junos::mode::ldpsessionstatus', + 'lsp-status' => 'network::juniper::common::junos::mode::lspstatus', 'list-interfaces' => 'snmp_standard::mode::listinterfaces', 'list-storages' => 'snmp_standard::mode::liststorages', + 'memory-routing' => 'network::juniper::common::junos::mode::memoryrouting', # routing engine + 'rsvp-session-status' => 'network::juniper::common::junos::mode::rsvpsessionstatus', 'storage' => 'snmp_standard::mode::storage', ); From 0fbd72ee94382612d1584b895ea762c3b685c7b3 Mon Sep 17 00:00:00 2001 From: Colin Gagnaire Date: Fri, 28 Dec 2018 18:00:50 +0100 Subject: [PATCH 23/23] enh juniper mseries hardware by adding cache --- .../common/junos/mode/components/fru.pm | 42 +++---- .../common/junos/mode/components/operating.pm | 32 ++--- .../juniper/common/junos/mode/hardware.pm | 109 +++++++++++++++++- 3 files changed, 135 insertions(+), 48 deletions(-) diff --git a/centreon-plugins/network/juniper/common/junos/mode/components/fru.pm b/centreon-plugins/network/juniper/common/junos/mode/components/fru.pm index 28fb137f9..a33b17221 100644 --- a/centreon-plugins/network/juniper/common/junos/mode/components/fru.pm +++ b/centreon-plugins/network/juniper/common/junos/mode/components/fru.pm @@ -65,22 +65,6 @@ my %map_fru_states = ( 10 => 'standby', ); -# In MIB 'mib-jnx-chassis' -my $mapping = { - jnxFruName => { oid => '.1.3.6.1.4.1.2636.3.1.15.1.5' }, - jnxFruType => { oid => '.1.3.6.1.4.1.2636.3.1.15.1.6', map => \%map_fru_type }, - jnxFruState => { oid => '.1.3.6.1.4.1.2636.3.1.15.1.8', map => \%map_fru_states }, - jnxFruTemp => { oid => '.1.3.6.1.4.1.2636.3.1.15.1.9' }, - jnxFruOfflineReason => { oid => '.1.3.6.1.4.1.2636.3.1.15.1.10', map => \%map_fru_offline }, -}; -my $oid_jnxFruEntry = '.1.3.6.1.4.1.2636.3.1.15.1'; - -sub load { - my ($self) = @_; - - push @{$self->{request}}, { oid => $oid_jnxFruEntry, start => $mapping->{jnxFruName}->{oid}, end => $mapping->{jnxFruOfflineReason}->{oid} }; -} - sub check { my ($self) = @_; @@ -88,23 +72,31 @@ sub check { $self->{components}->{fru} = {name => 'frus', total => 0, skip => 0}; return if ($self->check_filter(section => 'fru')); - foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_jnxFruEntry}})) { - next if ($oid !~ /^$mapping->{jnxFruName}->{oid}\.(.*)$/); - my $instance = $1; - my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_jnxFruEntry}, instance => $instance); + my $mapping = { + jnxFruState => { oid => '.1.3.6.1.4.1.2636.3.1.15.1.8', map => \%map_fru_states }, + jnxFruTemp => { oid => '.1.3.6.1.4.1.2636.3.1.15.1.9' }, + jnxFruOfflineReason => { oid => '.1.3.6.1.4.1.2636.3.1.15.1.10', map => \%map_fru_offline }, + }; + + my $results = $self->{snmp}->get_table(oid => $self->{oids_fru}->{jnxFruEntry}, start => $mapping->{jnxFruState}->{oid}, end => $mapping->{jnxFruOfflineReason}->{oid}); + + foreach my $instance (sort $self->get_instances(oid_entry => $self->{oids_fru}->{jnxFruEntry}, oid_name => $self->{oids_fru}->{jnxFruName})) { + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $results, instance => $instance); next if ($self->check_filter(section => 'fru', instance => $instance)); next if ($result->{jnxFruState} =~ /empty/i && $self->absent_problem(section => 'fru', instance => $instance)); $self->{components}->{fru}->{total}++; + my $name = $self->get_cache(oid_entry => $self->{oids_fru}->{jnxFruEntry}, oid_name => $self->{oids_fru}->{jnxFruName}, instance => $instance); + my $type = $self->get_cache(oid_entry => $self->{oids_fru}->{jnxFruEntry}, oid_name => $self->{oids_fru}->{jnxFruType}, instance => $instance); $self->{output}->output_add(long_msg => sprintf("Fru '%s' state is %s [instance: %s, type: %s, offline reason: %s]", - $result->{jnxFruName}, $result->{jnxFruState}, - $instance, $result->{jnxFruType}, $result->{jnxFruOfflineReason})); + $name, $result->{jnxFruState}, + $instance, $map_fru_type{$type}, $result->{jnxFruOfflineReason})); my $exit = $self->get_severity(section => 'fru', value => $result->{jnxFruState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Fru '%s' state is %s [offline reason: %s]", $result->{jnxFruName}, $result->{jnxFruState}, + short_msg => sprintf("Fru '%s' state is %s [offline reason: %s]", $name, $result->{jnxFruState}, $result->{jnxFruOfflineReason})); } @@ -112,9 +104,9 @@ sub check { my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fru-temperature', instance => $instance, value => $result->{jnxFruTemp}); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit2, - short_msg => sprintf("Fru '%s' temperature is %s degree centigrade", $result->{jnxFruName}, $result->{jnxFruTemp})); + short_msg => sprintf("Fru '%s' temperature is %s degree centigrade", $name, $result->{jnxFruTemp})); } - $self->{output}->perfdata_add(label => "temp_" . $result->{jnxFruName}, unit => 'C', + $self->{output}->perfdata_add(label => "temp_" . $name, unit => 'C', value => $result->{jnxFruTemp}, warning => $warn, critical => $crit); diff --git a/centreon-plugins/network/juniper/common/junos/mode/components/operating.pm b/centreon-plugins/network/juniper/common/junos/mode/components/operating.pm index 248f58e48..1a1ca3c70 100644 --- a/centreon-plugins/network/juniper/common/junos/mode/components/operating.pm +++ b/centreon-plugins/network/juniper/common/junos/mode/components/operating.pm @@ -33,19 +33,6 @@ my %map_operating_states = ( 7 => 'standby', ); -# In MIB 'mib-jnx-chassis' -my $mapping = { - jnxOperatingDescr => { oid => '.1.3.6.1.4.1.2636.3.1.13.1.5' }, - jnxOperatingState => { oid => '.1.3.6.1.4.1.2636.3.1.13.1.6', map => \%map_operating_states }, -}; -my $oid_jnxOperatingEntry = '.1.3.6.1.4.1.2636.3.1.13.1'; - -sub load { - my ($self) = @_; - - push @{$self->{request}}, { oid => $oid_jnxOperatingEntry, start => $mapping->{jnxOperatingDescr}->{oid}, end => $mapping->{jnxOperatingState}->{oid} }; -} - sub check { my ($self) = @_; @@ -53,21 +40,26 @@ sub check { $self->{components}->{operating} = {name => 'operatings', total => 0, skip => 0}; return if ($self->check_filter(section => 'operating')); - foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_jnxOperatingEntry}})) { - next if ($oid !~ /^$mapping->{jnxOperatingDescr}->{oid}\.(.*)$/); - my $instance = $1; - my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_jnxOperatingEntry}, instance => $instance); + my $mapping = { + jnxOperatingState => { oid => '.1.3.6.1.4.1.2636.3.1.13.1.6', map => \%map_operating_states }, + }; + + my $results = $self->{snmp}->get_table(oid => $self->{oids_operating}->{jnxOperatingEntry}, start => $mapping->{jnxOperatingState}->{oid}, end => $mapping->{jnxOperatingState}->{oid}); + + foreach my $instance (sort $self->get_instances(oid_entry => $self->{oids_operating}->{jnxOperatingEntry}, oid_name => $self->{oids_operating}->{jnxOperatingDescr})) { + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $results, instance => $instance); next if ($self->check_filter(section => 'operating', instance => $instance)); $self->{components}->{operating}->{total}++; - + + my $desc = $self->get_cache(oid_entry => $self->{oids_operating}->{jnxOperatingEntry}, oid_name => $self->{oids_operating}->{jnxOperatingDescr}, instance => $instance); $self->{output}->output_add(long_msg => sprintf("Operating '%s' state is %s [instance: %s]", - $result->{jnxOperatingDescr}, $result->{jnxOperatingState}, $instance)); + $desc, $result->{jnxOperatingState}, $instance)); my $exit = $self->get_severity(section => 'operating', value => $result->{jnxOperatingState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Operating '%s' state is %s", - $result->{jnxOperatingDescr}, $result->{jnxOperatingState})); + $desc, $result->{jnxOperatingState})); } } } diff --git a/centreon-plugins/network/juniper/common/junos/mode/hardware.pm b/centreon-plugins/network/juniper/common/junos/mode/hardware.pm index 40183fe68..e7a9e590d 100644 --- a/centreon-plugins/network/juniper/common/junos/mode/hardware.pm +++ b/centreon-plugins/network/juniper/common/junos/mode/hardware.pm @@ -24,6 +24,7 @@ use base qw(centreon::plugins::templates::hardware); use strict; use warnings; +use centreon::plugins::statefile; sub set_system { my ($self, %options) = @_; @@ -31,9 +32,10 @@ sub set_system { $self->{regexp_threshold_overload_check_section_option} = '^(fru|operating)$'; $self->{regexp_threshold_numeric_check_section_option} = '^(fru-temperature)$'; - $self->{cb_hook1} = 'get_type'; + $self->{cb_hook1} = 'init_cache'; $self->{cb_hook2} = 'snmp_execute'; - + $self->{cb_hook3} = 'get_type'; + $self->{thresholds} = { fru => [ ['unknown', 'UNKNOWN'], @@ -67,6 +69,7 @@ sub snmp_execute { $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); + $self->write_cache(); } sub new { @@ -77,11 +80,81 @@ sub new { $self->{version} = '1.0'; $options{options}->add_options(arguments => { + "reload-cache-time:s" => { name => 'reload_cache_time', default => 180 }, }); + $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $self->{statefile_cache}->check_options(%options); +} + +sub init_cache { + my ($self, %options) = @_; + + $self->{hostname} = $options{snmp}->get_hostname(); + $self->{snmp_port} = $options{snmp}->get_port(); + + $self->{oids_fru} = { + jnxFruEntry => '.1.3.6.1.4.1.2636.3.1.15.1', + jnxFruName => '.1.3.6.1.4.1.2636.3.1.15.1.5', + jnxFruType => '.1.3.6.1.4.1.2636.3.1.15.1.6', + }; + $self->{oids_operating} = { + jnxOperatingEntry => '.1.3.6.1.4.1.2636.3.1.13.1', + jnxOperatingDescr => '.1.3.6.1.4.1.2636.3.1.13.1.5', + }; + + $self->{write_cache} = 0; + my $has_cache_file = $self->{statefile_cache}->read(statefile => 'cache_juniper_mseries_' . $self->{hostname} . '_' . $self->{snmp_port}); + my $timestamp_cache = $self->{statefile_cache}->get(name => 'last_timestamp'); + if ($has_cache_file == 0 || + !defined($timestamp_cache) || ((time() - $timestamp_cache) > (($self->{option_results}->{reload_cache_time}) * 60)) && $self->{option_results}->{reload_cache_time} != '-1') { + push @{$self->{request}}, { oid => $self->{oids_fru}->{jnxFruEntry}, start => $self->{oids_fru}->{jnxFruName}, end => $self->{oids_fru}->{jnxFruType} }; + push @{$self->{request}}, { oid => $self->{oids_operating}->{jnxOperatingEntry}, start => $self->{oids_operating}->{jnxOperatingDescr}, end => $self->{oids_operating}->{jnxOperatingDescr} }; + $self->{write_cache} = 1; + } +} + +sub write_cache { + my ($self, %options) = @_; + + if ($self->{write_cache} == 1) { + my $datas = {}; + $datas->{last_timestamp} = time(); + $datas->{$self->{oids_fru}->{jnxFruEntry}} = $self->{results}->{$self->{oids_fru}->{jnxFruEntry}}; + $datas->{$self->{oids_operating}->{jnxOperatingEntry}} = $self->{results}->{$self->{oids_operating}->{jnxOperatingEntry}}; + $self->{statefile_cache}->write(data => $datas); + } else { + $self->{results}->{$self->{oids_fru}->{jnxFruEntry}} = $self->{statefile_cache}->get(name => $self->{oids_fru}->{jnxFruEntry}); + $self->{results}->{$self->{oids_operating}->{jnxOperatingEntry}} = $self->{statefile_cache}->get(name => $self->{oids_operating}->{jnxOperatingEntry}); + } +} + +sub get_cache { + my ($self, %options) = @_; + + return $self->{results}->{$options{oid_entry}}->{$options{oid_name} . '.' . $options{instance}}; +} + +sub get_instances { + my ($self, %options) = @_; + + my @instances = (); + foreach (keys %{$self->{results}->{$options{oid_entry}}}) { + if (/^$options{oid_name}\.(.*)/) { + push @instances, $1; + } + } + + return @instances; +} + sub get_type { my ($self, %options) = @_; @@ -93,13 +166,38 @@ sub get_type { $self->{output}->output_add(long_msg => sprintf("Environment type: %s", $self->{env_type})); } +sub load_components { + my ($self, %options) = @_; + + foreach (@{$self->{components_module}}) { + if (/$self->{option_results}->{component}/) { + my $mod_name = $self->{components_path} . "::$_"; + centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $mod_name, + error_msg => "Cannot load module '$mod_name'.") if ($self->{load_components} == 1); + $self->{loaded} = 1; + } + } +} + +sub exec_components { + my ($self, %options) = @_; + + foreach (@{$self->{components_module}}) { + if (/$self->{option_results}->{component}/) { + my $mod_name = $self->{components_path} . "::$_"; + my $func = $mod_name->can('check'); + $func->($self); + } + } +} + 1; __END__ =head1 MODE -Check Hardware (mib-jnx-chassis) (frus, operating). +Check Hardware (JUNIPER-MIB) (frus, operating). =over 8 @@ -139,6 +237,11 @@ Example: --warning='fru-temperature,.*,30' Set critical threshold for fru temperatures (syntax: type,regexp,threshold) Example: --critical='fru-temperature,.*,40' +=item B<--reload-cache-time> + +Time in minutes before reloading cache file (Default: 180). +Use '-1' to disable cache reload. + =back =cut