From 35cea137a2a55b97a8df489f7c5c9c803eab0f64 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Tue, 20 Oct 2020 17:14:08 +0200 Subject: [PATCH] Enhance exchange (#2269) --- .../exchange/2010/local/mode/databases.pm | 295 ++++++++++++++++-- .../apps/exchange/2010/local/mode/queues.pm | 127 ++++++-- .../2010/local/mode/resources/types.pm | 90 ++++++ .../apps/exchange/2010/local/plugin.pm | 9 +- .../powershell/exchange/2010/databases.pm | 224 ++----------- .../common/powershell/exchange/2010/queues.pm | 84 +---- .../centreon/common/powershell/functions.pm | 2 +- 7 files changed, 497 insertions(+), 334 deletions(-) create mode 100644 centreon-plugins/apps/exchange/2010/local/mode/resources/types.pm diff --git a/centreon-plugins/apps/exchange/2010/local/mode/databases.pm b/centreon-plugins/apps/exchange/2010/local/mode/databases.pm index 0f639e068..638ac08bf 100644 --- a/centreon-plugins/apps/exchange/2010/local/mode/databases.pm +++ b/centreon-plugins/apps/exchange/2010/local/mode/databases.pm @@ -20,16 +20,239 @@ package apps::exchange::2010::local::mode::databases; -use base qw(centreon::plugins::mode); +use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use centreon::common::powershell::exchange::2010::databases; +use apps::exchange::2010::local::mode::resources::types qw($copystatus_contentindexstate); +use JSON::XS; + +sub custom_mailflow_latency_perfdata { + my ($self, %options) = @_; + + $self->{output}->perfdata_add( + nlabel => $self->{nlabel}, + unit => 's', + instances => [$self->{result_values}->{server}, $self->{result_values}->{database}], + value => sprintf('%.3f', $self->{result_values}->{mailflow_latency}), + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}) + ); +} + +sub custom_space_size_perfdata { + my ($self, %options) = @_; + + $self->{output}->perfdata_add( + nlabel => $self->{nlabel}, + unit => 'B', + instances => [$self->{result_values}->{server}, $self->{result_values}->{database}], + value => $self->{result_values}->{size}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}) + ); +} + +sub custom_space_available_perfdata { + my ($self, %options) = @_; + + $self->{output}->perfdata_add( + nlabel => $self->{nlabel}, + unit => 'B', + instances => [$self->{result_values}->{server}, $self->{result_values}->{database}], + value => $self->{result_values}->{asize}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}) + ); +} + +sub custom_mapi_output { + my ($self, %options) = @_; + + return 'mapi test connectivity is ' . $self->{result_values}->{mapi_result}; +} + +sub custom_mailflow_output { + my ($self, %options) = @_; + + return 'mapi test result is ' . $self->{result_values}->{mailflow_result}; +} + +sub custom_copystatus_output { + my ($self, %options) = @_; + + return sprintf( + "copystatus state is %s [error: %s]", + $self->{result_values}->{copystatus_indexstate}, + $self->{result_values}->{copystatus_content_index_error_message} + ); +} + +sub custom_status_output { + my ($self, %options) = @_; + + return sprintf( + '%s mounted', + $self->{result_values}->{mounted} == 0 ? 'not' : 'is' + ); +} + +sub database_long_output { + my ($self, %options) = @_; + + return "checking database '" . $options{instance_value}->{database} . "' server '" . $options{instance_value}->{server} . "'"; +} + +sub prefix_database_output { + my ($self, %options) = @_; + + return "Database '" . $options{instance_value}->{database} . "' server '" . $options{instance_value}->{server} . "'"; +} + +sub prefix_mailflow_output { + my ($self, %options) = @_; + + return 'mailflow '; +} + +sub prefix_global_output { + my ($self, %options) = @_; + + return 'Databases '; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, + { name => 'databases', type => 3, cb_prefix_output => 'prefix_database_output', cb_long_output => 'database_long_output', indent_long_output => ' ', message_multiple => 'All databases are ok', + group => [ + { name => 'db_global', type => 0, skipped_code => { -10 => 1 } }, + { name => 'space', type => 0, skipped_code => { -10 => 1 } }, + { name => 'mapi', type => 0, skipped_code => { -10 => 1 } }, + { name => 'mailflow', type => 0, cb_prefix_output => 'prefix_mailflow_output', skipped_code => { -10 => 1 } }, + { name => 'copystatus', type => 0, skipped_code => { -10 => 1 } }, + ] + } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'databases-space-size', nlabel => 'databases.space.size.bytes', set => { + key_values => [ { name => 'size' } ], + output_template => 'space size: %s %s', + output_change_bytes => 1, + perfdatas => [ + { template => '%d', unit => 'B', min => 0 } + ] + } + }, + { label => 'databases-space-available', nlabel => 'databases.space.available.bytes', set => { + key_values => [ { name => 'asize' } ], + output_template => 'space available: %s %s', + output_change_bytes => 1, + perfdatas => [ + { template => '%d', unit => 'B', min => 0 } + ] + } + } + ]; + + $self->{maps_counters}->{db_global} = [ + { + label => 'status', + type => 2, + critical_default => '%{mounted} == 0', + set => { + key_values => [ + { name => 'mounted' }, { name => 'database' }, { name => 'server' } + ], + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + } + ]; + + $self->{maps_counters}->{space} = [ + { label => 'database-space-size', nlabel => 'database.space.size.bytes', set => { + key_values => [ { name => 'size' }, { name => 'database' }, { name => 'server' } ], + output_template => 'space size: %s %s', + output_change_bytes => 1, + closure_custom_perfdata => $self->can('custom_space_size_perfdata') + } + }, + { label => 'database-space-available', nlabel => 'database.space.available.bytes', set => { + key_values => [ { name => 'asize' }, { name => 'database' }, { name => 'server' } ], + output_template => 'space available: %s %s', + output_change_bytes => 1, + closure_custom_perfdata => $self->can('custom_space_asize_perfdata') + } + } + ]; + + $self->{maps_counters}->{mapi} = [ + { + label => 'mapi', + type => 2, + critical_default => '%{mapi_result} !~ /Success/i', + set => { + key_values => [ + { name => 'mapi_result' }, { name => 'database' }, { name => 'server' } + ], + closure_custom_output => $self->can('custom_mapi_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + } + ]; + + $self->{maps_counters}->{mailflow} = [ + { + label => 'mailflow', + type => 2, + critical_default => '%{mailflow_result} !~ /Success/i', + set => { + key_values => [ + { name => 'mailflow_result' }, { name => 'database' }, { name => 'server' } + ], + closure_custom_output => $self->can('custom_mailflow_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + }, + { label => 'mailflow-latency', nlabel => 'database.mailflow.latency.seconds', display_ok => 0, set => { + key_values => [ { name => 'mailflow_latency' }, { name => 'database' }, { name => 'server' } ], + output_template => 'latency: %.3f %%', + closure_custom_perfdata => $self->can('custom_mailflow_latency_perfdata') + } + } + ]; + + $self->{maps_counters}->{copystatus} = [ + { + label => 'copystatus', + type => 2, + critical_default => '%{copystatus_indexstate} !~ /Healthy/i', + set => { + key_values => [ + { name => 'copystatus_indexstate' }, { name => 'copystatus_content_index_error_message' }, + { name => 'database' }, { name => 'server' } + ], + closure_custom_output => $self->can('custom_copystatus_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + } + ]; +} sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { @@ -47,36 +270,13 @@ sub new { 'ps-exec-only' => { name => 'ps_exec_only' }, 'ps-display' => { name => 'ps_display' }, 'ps-database-filter:s' => { name => 'ps_database_filter' }, - 'ps-database-test-filter:s' => { name => 'ps_database_test_filter' }, - 'warning-mapi:s' => { name => 'warning_mapi' }, - 'critical-mapi:s' => { name => 'critical_mapi', default => '%{mapi_result} !~ /Success/i' }, - 'warning-mailflow:s' => { name => 'warning_mailflow' }, - 'critical-mailflow:s' => { name => 'critical_mailflow', default => '%{mailflow_result} !~ /Success/i' }, - 'warning-copystatus:s' => { name => 'warning_copystatus' }, - 'critical-copystatus:s' => { name => 'critical_copystatus', default => '%{copystatus_indexstate} !~ /Healthy/i' }, + 'ps-database-test-filter:s' => { name => 'ps_database_test_filter' } }); return $self; } -sub change_macros { - my ($self, %options) = @_; - - foreach (('warning_mapi', 'critical_mapi', 'warning_mailflow', 'critical_mailflow', 'warning_copystatus', 'critical_copystatus')) { - if (defined($self->{option_results}->{$_})) { - $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{data}->{$1}/g; - } - } -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - $self->change_macros(); -} - -sub run { +sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { @@ -117,10 +317,35 @@ sub run { $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } - centreon::common::powershell::exchange::2010::databases::check($self, stdout => $stdout); - $self->{output}->display(); - $self->{output}->exit(); + my $decoded; + eval { + $decoded = JSON::XS->new->decode($stdout); + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); + $self->{output}->option_exit(); + } + + $self->{global} = { size => 0, asize => 0 }; + $self->{databases} = {}; + foreach my $db (@$decoded) { + $db->{mounted} = $db->{mounted} =~ /True|1/i ? 1 : 0; + $db->{copystatus_indexstate} = $copystatus_contentindexstate->{ $db->{copystatus_indexstate} } + if (defined($db->{copystatus_indexstate})); + + $self->{databases}->{ $db->{database} . ':' . $db->{server} } = { + database => $db->{database}, + server => $db->{server}, + db_global => $db, + space => $db, + mapi => $db, + mailflow => $db, + copystatus => $db + }; + $self->{global}->{size} += $db->{size}; + $self->{global}->{asize} += $db->{asize}; + } } 1; @@ -194,6 +419,16 @@ Filter database (only wilcard '*' can be used. In Powershell). Skip mapi/mailflow test (regexp can be used. In Powershell). +=item B<--warning-status> + +Set warning threshold. +Can used special variables like: %{mounted}, %{database}, %{server} + +=item B<--critical-status> + +Set critical threshold (Default: '%{mounted} == 0'). +Can used special variables like: %{mounted}, %{database}, %{server} + =item B<--warning-mapi> Set warning threshold. diff --git a/centreon-plugins/apps/exchange/2010/local/mode/queues.pm b/centreon-plugins/apps/exchange/2010/local/mode/queues.pm index d1eefd639..da19a05e6 100644 --- a/centreon-plugins/apps/exchange/2010/local/mode/queues.pm +++ b/centreon-plugins/apps/exchange/2010/local/mode/queues.pm @@ -20,12 +20,58 @@ package apps::exchange::2010::local::mode::queues; -use base qw(centreon::plugins::mode); +use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::misc; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use centreon::common::powershell::exchange::2010::queues; +use apps::exchange::2010::local::mode::resources::types qw($queue_status $queue_delivery_type); +use JSON::XS; + +sub custom_status_output { + my ($self, %options) = @_; + + return sprintf( + 'status: %s [last error: %s] [delivery type: %s] [identity: %s] [message count: %s]', + $self->{result_values}->{status}, + $self->{result_values}->{last_error}, + $self->{result_values}->{delivery_type}, + $self->{result_values}->{identity}, + $self->{result_values}->{message_count} + ); +} + +sub prefix_queue_output { + my ($self, %options) = @_; + + return "Queue '" . $options{instance_value}->{nexthopdomain} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'queues', type => 1, cb_prefix_output => 'prefix_queue_output', message_multiple => 'All queues are ok', skipped_code => { -11 => 1 } } + ]; + + $self->{maps_counters}->{queues} = [ + { label => 'status', type => 2, critical_default => '%{status} !~ /Ready|Active/i', set => { + key_values => [ + { name => 'nexthopdomain' }, { name => 'identity' }, + { name => 'is_valid' }, { name => 'isvalid' }, + { name => 'delivery_type' }, { name => 'deliverytype' }, + { name => 'message_count' }, { name => 'messagecount' }, + { name => 'status' }, { name => 'last_error' } + ], + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + }, + ]; +} sub new { my ($class, %options) = @_; @@ -42,32 +88,13 @@ sub new { 'command-path:s' => { name => 'command_path' }, 'command-options:s' => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' }, 'ps-exec-only' => { name => 'ps_exec_only' }, - 'ps-display' => { name => 'ps_display' }, - 'warning:s' => { name => 'warning' }, - 'critical:s' => { name => 'critical', default => '%{status} !~ /Ready|Active/i' }, + 'ps-display' => { name => 'ps_display' } }); return $self; } -sub change_macros { - my ($self, %options) = @_; - - foreach (('warning', 'critical')) { - if (defined($self->{option_results}->{$_})) { - $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{data}->{$1}/g; - } - } -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - $self->change_macros(); -} - -sub run { +sub manage_selection { my ($self, %options) = @_; if (!defined($self->{option_results}->{no_ps})) { @@ -103,10 +130,52 @@ sub run { $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } - centreon::common::powershell::exchange::2010::queues::check($self, stdout => $stdout); - $self->{output}->display(); - $self->{output}->exit(); + my $decoded; + eval { + $decoded = JSON::XS->new->decode($stdout); + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); + $self->{output}->option_exit(); + } + + my $perfdatas_queues = {}; + + $self->{queues} = {}; + foreach my $queue (@$decoded) { + $queue->{is_valid} = $queue->{is_valid} =~ /True|1/i ? 1 : 0; + $queue->{status} = $queue_status->{ $queue->{status} } + if (defined($queue->{status})); + $queue->{delivery_type} = $queue_delivery_type->{ $queue->{delivery_type} } + if (defined($queue->{delivery_type})); + + $self->{queues}->{ $queue->{identity} } = { + %$queue, + deliverytype => $queue->{delivery_type}, + isvalid => $queue->{is_valid}, + messagecount => $queue->{message_count} + }; + + if ($queue->{message_count} =~ /^(\d+)/) { + my $num = $1; + my $identity = $queue->{identity}; + + $identity = $1 if ($queue->{identity} =~ /^(.*\/)[0-9]+$/); + $perfdatas_queues->{$identity} = 0 if (!defined($perfdatas_queues->{$identity})); + $perfdatas_queues->{$identity} += $num; + } + } + + foreach (keys %$perfdatas_queues) { + $self->{output}->perfdata_add( + label => 'queue_length', + nlabel => 'queue.length.count', + instances => $_, + value => $perfdatas_queues->{$_}, + min => 0 + ); + } } 1; @@ -160,15 +229,15 @@ Display powershell script. Print powershell output. -=item B<--warning> +=item B<--warning-status> Set warning threshold. -Can used special variables like: %{status}, %{identity}, %{isvalid}, %{deliverytype}, %{messagecount} +Can used special variables like: %{status}, %{identity}, %{is_valid}, %{delivery_type}, %{message_count} -=item B<--critical> +=item B<--critical-status> Set critical threshold (Default: '%{status} !~ /Ready|Active/i'). -Can used special variables like: %{status}, %{identity}, %{isvalid}, %{deliverytype}, %{messagecount} +Can used special variables like: %{status}, %{identity}, %{is_valid}, %{delivery_type}, %{message_count} =back diff --git a/centreon-plugins/apps/exchange/2010/local/mode/resources/types.pm b/centreon-plugins/apps/exchange/2010/local/mode/resources/types.pm new file mode 100644 index 000000000..b83160c42 --- /dev/null +++ b/centreon-plugins/apps/exchange/2010/local/mode/resources/types.pm @@ -0,0 +1,90 @@ +# +# Copyright 2020 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 apps::exchange::2010::local::mode::resources::types; + +use strict; +use warnings; +use Exporter; + +our $queue_status; +our $queue_delivery_type; +our $copystatus_contentindexstate; + +our @ISA = qw(Exporter); +our @EXPORT_OK = qw( + $queue_status $queue_delivery_type + $copystatus_contentindexstate +); + +$queue_status = { + 0 => 'None', + 1 => 'Active', + 2 => 'Ready', + 3 => 'Retry', + 4 => 'Suspended', + 5 => 'Connecting', + 6 => 'Throttled' +}; + +$queue_delivery_type = { + 0 => 'Undefined', + 1 => 'DnsConnectorDelivery', + 2 => 'MapiDelivery', + 3 => 'NonSmtpGatewayDelivery', + 4 => 'SmartHostConnectorDelivery', + 5 => 'SmtpRelayToRemoteAdSite', + 6 => 'SmtpRelayToTiRg', + 7 => 'SmtpRelayWithinAdSite', + 8 => 'SmtpRelayWithinAdSiteToEdge', + 9 => 'Unreachable', + 10 => 'ShadowRedundancy', + 11 => 'Heartbeat', + 12 => 'DeliveryAgent', + 13 => 'SmtpDeliveryToMailbox', + 14 => 'SmtpRelayToDag', + 15 => 'SmtpRelayToMailboxDeliveryGroup', + 16 => 'SmtpRelayToConnectorSourceServers', + 17 => 'SmtpRelayToServers', + 18 => 'SmtpRelayToRemoteForest', + 19 => 'SmtpDeliveryToExo', + 20 => 'HttpDeliveryToMailbox', + 21 => 'HttpDeliveryToExo', + 22 => 'Delay', + 23 => 'SmtpSubmissionToEop', + 24 => 'SmtpSubmissionToExo', + 25 => 'HttpDeliveryToApp' +}; + +$copystatus_contentindexstate = { + 0 => 'Unknown', + 1 => 'Healthy', + 2 => 'Crawling', + 3 => 'Failed', + 4 => 'Seeding', + 5 => 'FailedAndSuspended', + 6 => 'Suspended', + 7 => 'Disabled', + 8 => 'AutoSuspended', + 9 => 'HealthyAndUpgrading', + 10 => 'DiskUnavailable' +}; + +1; diff --git a/centreon-plugins/apps/exchange/2010/local/plugin.pm b/centreon-plugins/apps/exchange/2010/local/plugin.pm index efda96835..91d4f7526 100644 --- a/centreon-plugins/apps/exchange/2010/local/plugin.pm +++ b/centreon-plugins/apps/exchange/2010/local/plugin.pm @@ -30,7 +30,7 @@ sub new { bless $self, $class; $self->{version} = '0.1'; - %{$self->{modes}} = ( + $self->{modes} = { 'activesync-mailbox' => 'apps::exchange::2010::local::mode::activesyncmailbox', 'databases' => 'apps::exchange::2010::local::mode::databases', 'list-databases' => 'apps::exchange::2010::local::mode::listdatabases', @@ -40,8 +40,8 @@ sub new { 'owa-mailbox' => 'apps::exchange::2010::local::mode::owamailbox', 'queues' => 'apps::exchange::2010::local::mode::queues', 'replication-health' => 'apps::exchange::2010::local::mode::replicationhealth', - 'services' => 'apps::exchange::2010::local::mode::services', - ); + 'services' => 'apps::exchange::2010::local::mode::services' + }; return $self; } @@ -52,7 +52,6 @@ __END__ =head1 PLUGIN DESCRIPTION -Check Windows Exchange 2010 locally. -!!! Experimental system !!! +Check Windows Exchange 2010/2016 locally. =cut diff --git a/centreon-plugins/centreon/common/powershell/exchange/2010/databases.pm b/centreon-plugins/centreon/common/powershell/exchange/2010/databases.pm index 710151f74..5e8d1d52e 100644 --- a/centreon-plugins/centreon/common/powershell/exchange/2010/databases.pm +++ b/centreon-plugins/centreon/common/powershell/exchange/2010/databases.pm @@ -22,8 +22,8 @@ package centreon::common::powershell::exchange::2010::databases; use strict; use warnings; -use centreon::plugins::misc; use centreon::common::powershell::exchange::2010::powershell; +use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; @@ -33,7 +33,9 @@ sub get_powershell { my $no_copystatus = (defined($options{no_copystatus})) ? 1 : 0; my $ps = centreon::common::powershell::exchange::2010::powershell::powershell_init(%options); - + $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); + $ps .= centreon::common::powershell::functions::convert_to_json(%options); + $ps .= ' # Check to make sure all databases are mounted try { @@ -55,15 +57,21 @@ try { Write-Host $Error[0].Exception exit 1 } + +$items = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($DB in $MountedDB) { - Write-Host "[name=" $DB.Name "][server=" $DB.Server "][mounted=" $DB.Mounted "][size=" $DB.DatabaseSize "][asize=" $DB.AvailableNewMailboxSpace "]" -NoNewline - + $item = @{} + + $item.database = $DB.Name + $item.server = $DB.Server.Name + $item.mounted = $DB.Mounted + $item.size = $DB.DatabaseSize.ToBytes().ToString() + $item.asize = $DB.AvailableNewMailboxSpace.ToBytes().ToString() '; if (defined($options{filter_database_test}) && $options{filter_database_test} ne '') { $ps .= ' if (!($DB.Name -match "' . $options{filter_database_test} . '")) { - Write-Host "[Skip extra test]" continue } '; @@ -77,7 +85,7 @@ Foreach ($DB in $MountedDB) { $ps .= ' # Test Mapi Connectivity $MapiResult = test-mapiconnectivity -Database $DB.Name - Write-Host "[mapi=" $MapiResult.Result "]" -NoNewline + $item.mapi_result = $MapiResult.Result '; } @@ -85,7 +93,8 @@ Foreach ($DB in $MountedDB) { $ps .= ' # Test Mailflow $MailflowResult = Test-mailflow -Targetdatabase $DB.Name - Write-Host "[mailflow=" $MailflowResult.testmailflowresult "][latency=" $MailflowResult.MessageLatencyTime.TotalMilliseconds "]" -NoNewline + $item.mailflow_result = $MailflowResult.testmailflowresult + $item.mailflow_latency = $MailflowResult.MessageLatencyTime.TotalMilliseconds '; } if ($no_copystatus == 0) { @@ -93,214 +102,25 @@ Foreach ($DB in $MountedDB) { # Test CopyStatus $tmp_name = $DB.Name + "\" + $DB.Server $CopyStatusResult = Get-MailboxDatabaseCopyStatus -Identity $tmp_name - Write-Host "[contentindexstate=" $CopyStatusResult.ContentIndexState "][[contentindexerrormessage=" $CopyStatusResult.ContentIndexErrorMessage "]]" -NoNewline + $item.copystatus_indexstate = $CopyStatusResult.ContentIndexState.value__ + $item.copystatus_content_index_error_message = $CopyStatusResult.ContentIndexErrorMessage '; } $ps .= ' } - Write-Host "" + + $items.Add($item) } +$jsonString = $items | ConvertTo-JSON-20 -forceArray $true +Write-Host $jsonString exit 0 '; return $ps; } -sub check_mapi { - my ($self, %options) = @_; - - if (defined($self->{option_results}->{no_mapi})) { - $self->{output}->output_add(long_msg => ' Skip MAPI test connectivity'); - return ; - } - - if ($options{line} !~ /\[mapi=(.*?)\]/) { - $self->{output}->output_add(long_msg => ' Skip MAPI test connectivity (information not found)'); - return ; - } - - $self->{data}->{mapi_result} = centreon::plugins::misc::trim($1); - $self->{output}->output_add(long_msg => " MAPI Test connectivity: " . $self->{data}->{mapi_result}); - - my ($status, $message) = ('ok'); - eval { - local $SIG{__WARN__} = sub { $message = $_[0]; }; - local $SIG{__DIE__} = sub { $message = $_[0]; }; - - if (defined($self->{option_results}->{critical_mapi}) && $self->{option_results}->{critical_mapi} ne '' && - eval "$self->{option_results}->{critical_mapi}") { - $status = 'critical'; - } elsif (defined($self->{option_results}->{warning_mapi}) && $self->{option_results}->{warning_mapi} ne '' && - eval "$self->{option_results}->{warning_mapi}") { - $status = 'warning'; - } - }; - if (defined($message)) { - $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); - } - if (!$self->{output}->is_status(value => $status, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $status, - short_msg => sprintf("Server '%s' Database '%s' MAPI connectivity is %s", - $self->{data}->{server}, $self->{data}->{database}, $self->{data}->{mapi_result})); - } -} - -sub check_mailflow { - my ($self, %options) = @_; - - if (defined($self->{option_results}->{no_mailflow})) { - $self->{output}->output_add(long_msg => ' Skip Mailflow test'); - return ; - } - - if ($options{line} !~ /\[mailflow=(.*?)\]\[latency=(.*?)\]/) { - $self->{output}->output_add(long_msg => ' Skip Mailflow test (information not found)'); - return ; - } - - $self->{data}->{mailflow_result} = centreon::plugins::misc::trim($1); - my $latency = centreon::plugins::misc::trim($2); - $self->{output}->output_add(long_msg => " Mailflow Test: " . $self->{data}->{mailflow_result}); - - my ($status, $message) = ('ok'); - eval { - local $SIG{__WARN__} = sub { $message = $_[0]; }; - local $SIG{__DIE__} = sub { $message = $_[0]; }; - - if (defined($self->{option_results}->{critical_mailflow}) && $self->{option_results}->{critical_mailflow} ne '' && - eval "$self->{option_results}->{critical_mailflow}") { - $status = 'critical'; - } elsif (defined($self->{option_results}->{warning_mailflow}) && $self->{option_results}->{warning_mailflow} ne '' && - eval "$self->{option_results}->{warning_mailflow}") { - $status = 'warning'; - } - }; - if (defined($message)) { - $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); - } - if (!$self->{output}->is_status(value => $status, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $status, - short_msg => sprintf("Server '%s' Database '%s' Mailflow test is %s", - $self->{data}->{server}, $self->{data}->{database}, $self->{data}->{mailflow_result})); - } - - if ($latency =~ /^(\d+)/) { - $self->{output}->perfdata_add(label => 'latency_' . $self->{data}->{server} . '_' . $self->{data}->{database}, unit => 's', - value => sprintf("%.3f", $1 / 1000), - min => 0); - } -} - -sub check_copystatus { - my ($self, %options) = @_; - - if (defined($self->{option_results}->{no_copystatus})) { - $self->{output}->output_add(long_msg => ' Skip copy status test'); - return ; - } - - if ($options{line} !~ /\[contentindexstate=(.*?)\]\[\[contentindexerrormessage=(.*?)\]\]/) { - $self->{output}->output_add(long_msg => ' Skip copystatus test (information not found)'); - return ; - } - - ($self->{data}->{copystatus_indexstate}, $self->{data}->{copystatus_indexerror}) = (centreon::plugins::misc::trim($1), centreon::plugins::misc::trim($2)); - $self->{output}->output_add(long_msg => " Copystatus state : " . $self->{data}->{copystatus_indexstate}); - - my ($status, $message) = ('ok'); - eval { - local $SIG{__WARN__} = sub { $message = $_[0]; }; - local $SIG{__DIE__} = sub { $message = $_[0]; }; - - if (defined($self->{option_results}->{critical_copystatus}) && $self->{option_results}->{critical_copystatus} ne '' && - eval "$self->{option_results}->{critical_copystatus}") { - $status = 'critical'; - } elsif (defined($self->{option_results}->{warning_copystatus}) && $self->{option_results}->{warning_copystatus} ne '' && - eval "$self->{option_results}->{warning_copystatus}") { - $status = 'warning'; - } - }; - if (defined($message)) { - $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); - } - if (!$self->{output}->is_status(value => $status, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $status, - short_msg => sprintf("Server '%s' Database '%s' copystatus state is %s [error: %s]", - $self->{data}->{server}, $self->{data}->{database}, $self->{data}->{copystatus_indexstate}, $self->{data}->{copystatus_indexerror})); - } -} - -sub check { - my ($self, %options) = @_; - # options: stdout - - # Following output: - #[name= Mailbox Database 0975194476 ][server= SRVI-WIN-TEST ][mounted= True ][size= 136.1 MB (142,671,872 bytes) ][asize= 124.4 MB (130,482,176 bytes) ][mapi= Success ][mailflow= Success ][latency= 50,00 ] - #... - - $self->{output}->output_add(severity => 'OK', - short_msg => 'Databases are mounted'); - if (!defined($self->{option_results}->{no_mapi})) { - $self->{output}->output_add(severity => 'OK', - short_msg => 'MAPI Connectivities are ok'); - } - if (!defined($self->{option_results}->{no_mailflow})) { - $self->{output}->output_add(severity => 'OK', - short_msg => 'Mailflow test are ok'); - } - - my $checked = 0; - foreach my $line (split /\n/, $options{stdout}) { - next if ($line !~ /^\[name=(.*?)\]\[server=(.*?)\]\[mounted=(.*?)\]\[size=(.*?)\]\[asize=(.*?)\]/); - $checked++; - $self->{data} = {}; - ($self->{data}->{database}, $self->{data}->{server}, $self->{data}->{mounted}, $self->{data}->{size}, $self->{data}->{asize}) = (centreon::plugins::misc::trim($1), centreon::plugins::misc::trim($2), - centreon::plugins::misc::trim($3), centreon::plugins::misc::trim($4), centreon::plugins::misc::trim($5)); - - $self->{output}->output_add(long_msg => sprintf("Test database '%s' server '%s':", $self->{data}->{database}, $self->{data}->{server})); - if ($self->{data}->{asize} =~ /\((.*?)\s*bytes/) { - my $free_bytes = $1; - $free_bytes =~ s/[.,]//g; - - my $total_bytes; - if ($self->{data}->{size} =~ /\((.*?)\s*bytes/) { - $total_bytes = $1; - $total_bytes =~ s/[.,]//g; - my ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $total_bytes); - $self->{output}->output_add(long_msg => sprintf(" Size %s", $total_value . ' ' . $total_unit)); - } - my $used_bytes = $total_bytes - $free_bytes; - - $self->{output}->perfdata_add(label => 'used_' . $self->{data}->{database}, unit => 'B', - value => $used_bytes, - min => 0, max => $total_bytes); - my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $used_bytes); - $self->{output}->output_add(long_msg => sprintf(" Used Size %s", $used_value . ' ' . $used_unit)); - } - - - # Check mounted - if ($self->{data}->{mounted} =~ /False/i) { - $self->{output}->output_add(long_msg => sprintf(" not mounted\n Skip mapi/mailflow test")); - $self->{output}->output_add(severity => 'CRITICAL', - short_msg => sprintf("Database '%s' server '%s' is not mounted", $self->{data}->{database}, $self->{data}->{server})); - next; - } - $self->{output}->output_add(long_msg => sprintf(" mounted")); - - check_mapi($self, line => $line); - check_mailflow($self, line => $line); - check_copystatus($self, line => $line); - } - - if ($checked == 0) { - $self->{output}->output_add(severity => 'UNKNOWN', - short_msg => 'Cannot find informations'); - } -} - 1; __END__ diff --git a/centreon-plugins/centreon/common/powershell/exchange/2010/queues.pm b/centreon-plugins/centreon/common/powershell/exchange/2010/queues.pm index 0d3e1f350..3819f6511 100644 --- a/centreon-plugins/centreon/common/powershell/exchange/2010/queues.pm +++ b/centreon-plugins/centreon/common/powershell/exchange/2010/queues.pm @@ -22,13 +22,15 @@ package centreon::common::powershell::exchange::2010::queues; use strict; use warnings; -use centreon::plugins::misc; use centreon::common::powershell::exchange::2010::powershell; +use centreon::common::powershell::functions; sub get_powershell { my (%options) = @_; my $ps = centreon::common::powershell::exchange::2010::powershell::powershell_init(%options); + $ps .= centreon::common::powershell::functions::escape_jsonstring(%options); + $ps .= centreon::common::powershell::functions::convert_to_json(%options); $ps .= ' try { @@ -39,80 +41,28 @@ try { exit 1 } +$items = New-Object System.Collections.Generic.List[Hashtable]; Foreach ($result in $results) { - Write-Host "[identity=" $result.Identity "][nexthopdomain=" $result.NextHopDomain "][deliverytype=" $result.DeliveryType "][status=" $result.Status "][isvalid=" $result.IsValid "][messagecount=" $result.MessageCount "][[error=" $result.LastError "]]" + $item = @{} + + $item.identity = $result.Identity.ToString().Replace("\\", "/") + $item.nexthopdomain = $result.NextHopDomain + $item.delivery_type = $result.DeliveryType.value__ + $item.status = $result.Status.value__ + $item.is_valid = $result.IsValid + $item.message_count = $result.MessageCount + $item.last_error = $result.LastError + $items.Add($item) } + +$jsonString = $items | ConvertTo-JSON-20 -forceArray $true +Write-Host $jsonString exit 0 '; return $ps; } -sub check { - my ($self, %options) = @_; - # options: stdout - - # Following output: - #[identity= ][nexthopdomain= xxxx][deliverytype= SmtpRelayWithinAdSite][status= Active ][isvalid= Yes][messagecount= 1 ][[error=...]] - $self->{output}->output_add(severity => 'OK', - short_msg => "All Queues are ok."); - - my $checked = 0; - $self->{output}->output_add(long_msg => $options{stdout}); - - $self->{perfdatas_queues} = {}; - while ($options{stdout} =~ /\[identity=(.*?)\]\[nexthopdomain=(.*?)\]\[deliverytype=(.*?)\]\[status=(.*?)\]\[isvalid=(.*?)\]\[messagecount=(.*?)\]\[\[error=(.*?)\]\]/msg) { - $self->{data} = {}; - ($self->{data}->{identity}, $self->{data}->{nexthopdomain}, $self->{data}->{deliverytype}, $self->{data}->{status}, $self->{data}->{isvalid}, $self->{data}->{messagecount}, $self->{data}->{error}) = - ($self->{output}->to_utf8($1), centreon::plugins::misc::trim($2), - centreon::plugins::misc::trim($3), centreon::plugins::misc::trim($4), centreon::plugins::misc::trim($5), centreon::plugins::misc::trim($6), centreon::plugins::misc::trim($7)); - - $checked++; - - my ($status, $message) = ('ok'); - eval { - local $SIG{__WARN__} = sub { $message = $_[0]; }; - local $SIG{__DIE__} = sub { $message = $_[0]; }; - - if (defined($self->{option_results}->{critical}) && $self->{option_results}->{critical} ne '' && - eval "$self->{option_results}->{critical}") { - $status = 'critical'; - } elsif (defined($self->{option_results}->{warning}) && $self->{option_results}->{warning} ne '' && - eval "$self->{option_results}->{warning}") { - $status = 'warning'; - } - }; - if (defined($message)) { - $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); - } - if (!$self->{output}->is_status(value => $status, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $status, - short_msg => sprintf("Queue '%s' status is '%s' [last error: %s]", - $self->{data}->{nexthopdomain}, $self->{data}->{status}, $self->{data}->{error})); - } - - if ($self->{data}->{messagecount} =~ /^(\d+)/) { - my $num = $1; - my $identity = $self->{data}->{identity}; - - $identity = $1 if ($self->{data}->{identity} =~ /^(.*\\)[0-9]+$/); - $self->{perfdatas_queues}->{$identity} = 0 if (!defined($self->{perfdatas_queues}->{$identity})); - $self->{perfdatas_queues}->{$identity} += $num; - } - } - - foreach (keys %{$self->{perfdatas_queues}}) { - $self->{output}->perfdata_add(label => 'queue_length_' . $_, - value => $self->{perfdatas_queues}->{$_}, - min => 0); - } - - if ($checked == 0) { - $self->{output}->output_add(severity => 'UNKNOWN', - short_msg => 'Cannot find informations'); - } -} - 1; __END__ diff --git a/centreon-plugins/centreon/common/powershell/functions.pm b/centreon-plugins/centreon/common/powershell/functions.pm index e7caf0ec6..14452388d 100644 --- a/centreon-plugins/centreon/common/powershell/functions.pm +++ b/centreon-plugins/centreon/common/powershell/functions.pm @@ -67,7 +67,7 @@ function ConvertTo-JSON-20($maxDepth = 4,$forceArray = $false) { return "`"{0}`"" -f (Escape-JSONString $value ) } '(System\.)?DateTime' {return "`"{0:yyyy-MM-dd}T{0:HH:mm:ss}`"" -f $value} - 'Int32|Double' {return "$value"} + 'Int16|Int32|Double' {return "$value"} 'Boolean' {return "$value".ToLower()} '(System\.)?Object\[\]' { # array