diff --git a/database/sap/hana/mode/blockedtransactions.pm b/database/sap/hana/mode/blockedtransactions.pm new file mode 100644 index 000000000..6c639512c --- /dev/null +++ b/database/sap/hana/mode/blockedtransactions.pm @@ -0,0 +1,96 @@ +# +# Copyright 2017 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::sap::hana::mode::blockedtransactions; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 }, + ]; + $self->{maps_counters}->{global} = [ + { label => 'blocked-transactions', set => { + key_values => [ { name => 'total' } ], + output_template => 'Current Total Blocked Transactions : %s', + perfdatas => [ + { label => 'total_blocked_transactions', value => 'total_absolute', template => '%s', min => 0 }, + ], + } + }, + ]; +} + +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 => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + $options{sql}->connect(); + + my $query = q{ + SELECT COUNT(*) AS total FROM M_BLOCKED_TRANSACTIONS + }; + $options{sql}->query(query => $query); + + $self->{global} = { total => 0 }; + if (my $row = $options{sql}->fetchrow_hashref()) { + $self->{global}->{total} = $row->{total} if (defined($row->{total})); + } +} + +1; + +__END__ + +=head1 MODE + +Check total blocked transactions. + +=over 8 + +=item B<--warning-*> + +Threshold warning. +Can be: 'blocked-transactions'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'blocked-transactions'. + +=back + +=cut \ No newline at end of file diff --git a/database/sap/hana/mode/connectedusers.pm b/database/sap/hana/mode/connectedusers.pm new file mode 100644 index 000000000..b7e310afa --- /dev/null +++ b/database/sap/hana/mode/connectedusers.pm @@ -0,0 +1,123 @@ +# +# Copyright 2017 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::sap::hana::mode::connectedusers; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'host', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All connected users are ok' }, + ]; + $self->{maps_counters}->{host} = [ + { label => 'users', set => { + key_values => [ { name => 'total' }, { name => 'display' } ], + output_template => 'Connected Users : %s', + perfdatas => [ + { label => 'users', value => 'total_absolute', template => '%s', min => 0, + label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub prefix_output { + my ($self, %options) = @_; + + return "Host '" . $options{instance_value}->{display} . "' "; +} + +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-username:s" => { name => 'filter_username' }, + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + $options{sql}->connect(); + + my $query = q{ + SELECT * FROM SYS.M_CONNECTIONS WHERE CONNECTION_TYPE IN ('Remote') + }; + $options{sql}->query(query => $query); + + $self->{host} = {}; + while ((my $row = $options{sql}->fetchrow_hashref())) { + my $name = $row->{HOST} . ':' . $row->{PORT}; + + $self->{host}->{$name} = { total => 0, display => $name } if (!defined($self->{host}->{$name})); + + if (defined($self->{option_results}->{filter_username}) && $self->{option_results}->{filter_username} ne '' && + $row->{USER_NAME} !~ /$self->{option_results}->{filter_username}/) { + $self->{output}->output_add(long_msg => "skipping '" . $name . '/' . $row->{USER_NAME} . "': no matching filter.", debug => 1); + next; + } + + $self->{host}->{$name}->{total}++; + } + + if (scalar(keys %{$self->{host}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No host found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check connected users. + +=over 8 + +=item B<--filter-username> + +Filter connected username. (Can be a regex) + +=item B<--warning-*> + +Threshold warning. +Can be: 'users'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'users'. + +=back + +=cut \ No newline at end of file diff --git a/database/sap/hana/mode/diskusage.pm b/database/sap/hana/mode/diskusage.pm new file mode 100644 index 000000000..c9436687f --- /dev/null +++ b/database/sap/hana/mode/diskusage.pm @@ -0,0 +1,206 @@ +# +# Copyright 2017 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::sap::hana::mode::diskusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $instance_mode; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'disk', type => 1, cb_prefix_output => 'prefix_volume_output', message_multiple => 'All disks are ok' }, + ]; + + $self->{maps_counters}->{disk} = [ + { label => 'usage', set => { + key_values => [ { name => 'used' }, { name => 'total' }, { name => 'display' } ], + 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 custom_usage_perfdata { + my ($self, %options) = @_; + + my $label = 'used_' . $self->{result_values}->{display}; + my $value_perf = $self->{result_values}->{used}; + if (defined($instance_mode->{option_results}->{free})) { + $label = 'free_' . $self->{result_values}->{display}; + $value_perf = $self->{result_values}->{free}; + } + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + my %total_options = (); + if ($instance_mode->{option_results}->{units} eq '%') { + $total_options{total} = $self->{result_values}->{total}; + $total_options{cast_int} = 1; + } + + $self->{output}->perfdata_add(label => $label . $extra_label, unit => 'B', + value => $value_perf, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options), + 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 ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + my $msg = sprintf("Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, + $total_free_value . " " . $total_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} . '_display'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; + $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 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' }, + "units:s" => { name => 'units', default => '%' }, + "free" => { name => 'free' }, + }); + return $self; +} + +sub prefix_disk_output { + my ($self, %options) = @_; + + return "Disk '" . $options{instance_value}->{display} . "' "; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +sub manage_selection { + my ($self, %options) = @_; + $options{sql}->connect(); + + my $query = q{ + SELECT * FROM SYS.M_DISKS + }; + $options{sql}->query(query => $query); + $self->{disk} = {}; + + while ((my $row = $options{sql}->fetchrow_hashref())) { + my $name = $row->{HOST} . ':' . $row->{PATH}; + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $name !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); + next; + } + + $self->{disk}->{$name} = { + used => $row->{USED_SIZE}, + total => $row->{TOTAL_SIZE}, + display => $name + }; + } + + if (scalar(keys %{$self->{disk}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No disk found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check disk usages. + +=over 8 + +=item B<--warning-usage> + +Threshold warning. + +=item B<--critical-usage> + +Threshold critical. + +=item B<--filter-name> + +Filter disk name. (Can be a regex) + +=item B<--units> + +Default is '%', can be 'B' + +=item B<--free> + +Thresholds are on free space left. + +=back + +=cut diff --git a/database/sap/hana/mode/hostcpu.pm b/database/sap/hana/mode/hostcpu.pm new file mode 100644 index 000000000..0652b9afb --- /dev/null +++ b/database/sap/hana/mode/hostcpu.pm @@ -0,0 +1,166 @@ +# +# Copyright 2017 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::sap::hana::mode::hostcpu; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'cpu', type => 1, cb_prefix_output => 'prefix_cpu_output', message_multiple => 'All cpu usages are ok' }, + ]; + $self->{maps_counters}->{cpu} = [ + { label => 'user', set => { + key_values => [ { name => 'total', diff => 1 }, { name => 'user', diff => 1 }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_data_calc'), closure_custom_calc_extra_options => { label_ref => 'user' }, + output_template => 'User %.2f %%', output_use => 'user_prct', threshold_use => 'user_prct', + perfdatas => [ + { label => 'user', value => 'user_prct', template => '%.2f', min => 0, max => 100, unit => '%', + label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'sys', set => { + key_values => [ { name => 'total', diff => 1 }, { name => 'sys', diff => 1 }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_data_calc'), closure_custom_calc_extra_options => { label_ref => 'sys' }, + output_template => 'System %.2f %%', output_use => 'sys_prct', threshold_use => 'sys_prct', + perfdatas => [ + { label => 'sys', value => 'sys_prct', template => '%.2f', min => 0, max => 100, unit => '%', + label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'wait', set => { + key_values => [ { name => 'total', diff => 1 }, { name => 'wait', diff => 1 }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_data_calc'), closure_custom_calc_extra_options => { label_ref => 'wait' }, + output_template => 'Wait %.2f %%', output_use => 'wait_prct', threshold_use => 'wait_prct', + perfdatas => [ + { label => 'wait', value => 'wait_prct', template => '%.2f', min => 0, max => 100, unit => '%', + label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'idle', set => { + key_values => [ { name => 'total', diff => 1 }, { name => 'idle', diff => 1 }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_data_calc'), closure_custom_calc_extra_options => { label_ref => 'idle' }, + output_template => 'Idle %.2f %%', output_use => 'idle_prct', threshold_use => 'idle_prct', + perfdatas => [ + { label => 'idle', value => 'idle_prct', template => '%.2f', min => 0, max => 100, unit => '%', + label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub custom_data_calc { + my ($self, %options) = @_; + + my $label = $options{extra_options}->{label_ref}; + my $delta_value = $options{new_datas}->{$self->{instance} . '_' . $label} - $options{old_datas}->{$self->{instance} . '_' . $label}; + my $delta_total = $options{new_datas}->{$self->{instance} . '_total'} - $options{old_datas}->{$self->{instance} . '_total'}; + + $self->{result_values}->{$label . '_prct'} = 0; + if ($delta_total > 0) { + $self->{result_values}->{$label . '_prct'} = $delta_value * 100 / $delta_total; + } + return 0; +} + +sub prefix_cpu_output { + my ($self, %options) = @_; + + return "CPU '" . $options{instance_value}->{display} . "' Usage : "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + $options{sql}->connect(); + + my $query = q{ + SELECT * FROM SYS.M_HOST_RESOURCE_UTILIZATION + }; + $options{sql}->query(query => $query); + + $self->{cache_name} = "sap_hana_db_" . $self->{mode} . '_' . $options{sql}->get_unique_id4save() . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); + + $self->{cpu} = {}; + while ((my $row = $options{sql}->fetchrow_hashref())) { + my $name = $row->{HOST}; + + $self->{cpu}->{$name} = { + display => $name, + total => $row->{TOTAL_CPU_SYSTEM_TIME} + $row->{TOTAL_CPU_USER_TIME} + $row->{TOTAL_CPU_IDLE_TIME} + $row->{TOTAL_CPU_WIO_TIME}, + sys => $row->{TOTAL_CPU_SYSTEM_TIME}, + user => $row->{TOTAL_CPU_USER_TIME}, + idle => $row->{TOTAL_CPU_IDLE_TIME}, + wait => $row->{TOTAL_CPU_WIO_TIME}, + }; + } +} + +1; + +__END__ + +=head1 MODE + +Check system CPUs. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example : --filter-counters='^idle$' + +=item B<--warning-*> + +Threshold warning. +Can be: 'user', 'sys', 'idle', 'wait'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'user', 'sys', 'idle', 'wait'. + +=back + +=cut \ No newline at end of file diff --git a/database/sap/hana/mode/hostmemory.pm b/database/sap/hana/mode/hostmemory.pm new file mode 100644 index 000000000..992b0d64b --- /dev/null +++ b/database/sap/hana/mode/hostmemory.pm @@ -0,0 +1,183 @@ +# +# Copyright 2017 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::sap::hana::mode::hostmemory; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +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 => $self->{result_values}->{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 = $self->{perfdata}->threshold_check(value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{result_values}->{label} . '-usage', exit_litteral => 'critical' }, { label => 'warning-' . $self->{result_values}->{label} . '-usage', exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + + my $msg = sprintf("Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, + $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{label} = $options{extra_options}->{label_ref}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_used'} + $options{new_datas}->{$self->{instance} . '_free'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; + $self->{result_values}->{free} = $options{new_datas}->{$self->{instance} . '_free'}; + $self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'memory', type => 1, cb_prefix_output => 'prefix_memory_output', message_multiple => 'All physical memories are ok' }, + { name => 'swap', type => 1, cb_prefix_output => 'prefix_swap_output', message_multiple => 'All swap memories are ok' }, + ]; + + $self->{maps_counters}->{memory} = [ + { label => 'physical-usage', set => { + key_values => [ { name => 'free' }, { name => 'used' }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'physical' }, + 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'), + } + }, + ]; + $self->{maps_counters}->{swap} = [ + { label => 'swap-usage', set => { + key_values => [ { name => 'free' }, { name => 'used' }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'swap' }, + 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 prefix_memory_output { + my ($self, %options) = @_; + + return "Physical memory '" . $options{instance_value}->{display} . "' "; +} + +sub prefix_swap_output { + my ($self, %options) = @_; + + return "Swap memory '" . $options{instance_value}->{display} . "' "; +} + +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 => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + $options{sql}->connect(); + + my $query = q{ + SELECT * FROM SYS.M_HOST_RESOURCE_UTILIZATION + }; + $options{sql}->query(query => $query); + $self->{swap} = {}; + $self->{memory} = {}; + + while ((my $row = $options{sql}->fetchrow_hashref())) { + my $name = $row->{HOST}; + + $self->{memory}->{$name} = { + display => $name, + free => $row->{FREE_PHYSICAL_MEMORY}, + used => $row->{USED_PHYSICAL_MEMORY}, + }; + $self->{swap}->{$name} = { + display => $name, + free => $row->{FREE_SWAP_SPACE}, + used => $row->{USED_SWAP_SPACE}, + }; + } +} + +1; + +__END__ + +=head1 MODE + +Check memory usages. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example : --filter-counters='^physical-usage$' + +=item B<--warning-*> + +Threshold warning. +Can be: 'physical-usage' (%), 'swap-usage' (%). + +=item B<--critical-*> + +Threshold critical. +Can be: 'physical-usage' (%), 'swap-usage' (%). + +=back + +=cut diff --git a/database/sap/hana/mode/volumeusage.pm b/database/sap/hana/mode/volumeusage.pm new file mode 100644 index 000000000..55f432a31 --- /dev/null +++ b/database/sap/hana/mode/volumeusage.pm @@ -0,0 +1,206 @@ +# +# Copyright 2017 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::sap::hana::mode::volumeusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $instance_mode; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'volume', type => 1, cb_prefix_output => 'prefix_volume_output', message_multiple => 'All data volumes are ok' }, + ]; + + $self->{maps_counters}->{volume} = [ + { label => 'usage', set => { + key_values => [ { name => 'used' }, { name => 'total' }, { name => 'display' } ], + 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 custom_usage_perfdata { + my ($self, %options) = @_; + + my $label = 'used_' . $self->{result_values}->{display}; + my $value_perf = $self->{result_values}->{used}; + if (defined($instance_mode->{option_results}->{free})) { + $label = 'free_' . $self->{result_values}->{display}; + $value_perf = $self->{result_values}->{free}; + } + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + my %total_options = (); + if ($instance_mode->{option_results}->{units} eq '%') { + $total_options{total} = $self->{result_values}->{total}; + $total_options{cast_int} = 1; + } + + $self->{output}->perfdata_add(label => $label . $extra_label, unit => 'B', + value => $value_perf, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options), + 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 ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + my $msg = sprintf("Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, + $total_free_value . " " . $total_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} . '_display'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; + $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 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' }, + "units:s" => { name => 'units', default => '%' }, + "free" => { name => 'free' }, + }); + return $self; +} + +sub prefix_volume_output { + my ($self, %options) = @_; + + return "Volume '" . $options{instance_value}->{display} . "' "; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +sub manage_selection { + my ($self, %options) = @_; + $options{sql}->connect(); + + my $query = q{ + SELECT * FROM SYS.M_VOLUME_FILES WHERE FILE_TYPE = 'DATA' + }; + $options{sql}->query(query => $query); + $self->{volume} = {}; + + while ((my $row = $options{sql}->fetchrow_hashref())) { + my $volume_name = $row->{HOST} . ':' . $row->{FILE_NAME}; + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $volume_name !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $volume_name . "': no matching filter.", debug => 1); + next; + } + + $self->{volume}->{$volume_name} = { + used => $row->{USED_SIZE}, + total => $row->{TOTAL_SIZE}, + display => $volume_name + }; + } + + if (scalar(keys %{$self->{volume}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No volume found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check data volume usages. + +=over 8 + +=item B<--warning-usage> + +Threshold warning. + +=item B<--critical-usage> + +Threshold critical. + +=item B<--filter-name> + +Filter volume name. (Can be a regex) + +=item B<--units> + +Default is '%', can be 'B' + +=item B<--free> + +Thresholds are on free space left. + +=back + +=cut diff --git a/database/sap/hana/plugin.pm b/database/sap/hana/plugin.pm new file mode 100644 index 000000000..7fec8ade0 --- /dev/null +++ b/database/sap/hana/plugin.pm @@ -0,0 +1,120 @@ +# +# Copyright 2017 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::sap::hana::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_sql); + +sub new { + my ($class, %options) = @_; + + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '0.1'; + %{$self->{modes}} = ( + 'blocked-transactions' => 'database::sap::hana::mode::blockedtransactions', + 'connected-users' => 'database::sap::hana::mode::connectedusers', + 'connection-time' => 'centreon::common::protocols::sql::mode::connectiontime', + 'disk-usage' => 'database::sap::hana::mode::diskusage', + 'host-memory' => 'database::sap::hana::mode::hostmemory', + 'host-cpu' => 'database::sap::hana::mode::hostcpu', + 'sql' => 'centreon::common::protocols::sql::mode::sql', + 'volume-usage' => 'database::sap::hana::mode::volumeusage', + ); + + return $self; +} + +sub init { + my ($self, %options) = @_; + + $self->{options}->add_options( + arguments => { + 'servernode:s@' => { name => 'servernode' }, + 'port:s@' => { name => 'port' }, + 'database:s' => { name => 'database' }, + } + ); + $self->{options}->parse_options(); + my $options_result = $self->{options}->get_options(); + $self->{options}->clean(); + + if (defined($options_result->{servernode})) { + @{$self->{sqldefault}->{dbi}} = (); + for (my $i = 0; $i < scalar(@{$options_result->{servernode}}); $i++) { + $self->{sqldefault}->{dbi}[$i] = { data_source => 'ODBC:DRIVER={HDBODBC};SERVERNODE=' . $options_result->{servernode}[$i] }; + if (defined($options_result->{port}[$i])) { + $self->{sqldefault}->{dbi}[$i]->{data_source} .= ':' . $options_result->{port}[$i]; + } else { + $self->{sqldefault}->{dbi}[$i]->{data_source} .= ':30013'; + } + if ((defined($options_result->{database})) && ($options_result->{database} ne '')) { + $self->{sqldefault}->{dbi}[$i]->{data_source} .= ';DATABASENAME=' . $options_result->{database}; + } + } + } + $self->SUPER::init(%options); +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check SAP Hana DB Server. +Prerequisite on the system: + +=over 8 + +=item * SAP Hana client for Linux/Unix + +=item * unixODBC and perl DBD::ODBC + +=item * Add in file /etc/odbcinst.ini + +[HDBODBC] +Description = "SmartCloudPT HANA" +Driver=/usr/sap/hdbclient/libodbcHDB.so + +=item * Use option --connect-options="LongReadLen=1000000,LongTruncOk=1" + +=back + +=over 8 + +=item B<--servernode> + +Hostname to query. + +=item B<--port> + +Database Server Port (default: 30013). + +=item B<--database> + +Database name to connect. + +=back + +=cut