diff --git a/database/oracle/mode/tablespaceusage.pm b/database/oracle/mode/tablespaceusage.pm index 8816414d3..7a1068d6d 100644 --- a/database/oracle/mode/tablespaceusage.pm +++ b/database/oracle/mode/tablespaceusage.pm @@ -117,10 +117,11 @@ sub new { bless $self, $class; $options{options}->add_options(arguments => { - "filter-tablespace:s" => { name => 'filter_tablespace' }, - "units:s" => { name => 'units', default => '%' }, - "free" => { name => 'free' }, - "skip" => { name => 'skip' }, + 'filter-tablespace:s' => { name => 'filter_tablespace' }, + 'units:s' => { name => 'units', default => '%' }, + 'free' => { name => 'free' }, + 'skip' => { name => 'skip' }, + 'notemp' => { name => 'notemp' }, }); return $self; @@ -134,77 +135,34 @@ sub prefix_tablespace_output { sub manage_selection { my ($self, %options) = @_; - # $options{sql} = sqlmode object + $self->{sql} = $options{sql}; $self->{sql}->connect(); - + + # request from check_oracle_health. my $query; - if ($self->{sql}->is_version_minimum(version => '11')) { - $query = q{ + if ($self->{sql}->is_version_minimum(version => '9')) { + my $tbs_sql_undo = q{ SELECT - tum.tablespace_name "Tablespace", - t.status "Status", - t.contents "Type", - t.extent_management "Extent Mgmt", - tum.used_space*t.block_size bytes, - tum.tablespace_size*t.block_size bytes_max + tablespace_name, bytes_expired FROM - DBA_TABLESPACE_USAGE_METRICS tum - INNER JOIN - dba_tablespaces t on tum.tablespace_name=t.tablespace_name + ( + SELECT + a.tablespace_name, + SUM (a.bytes) bytes_expired, + a.status + FROM + dba_undo_extents a + GROUP BY + tablespace_name, status + ) WHERE - t.contents<>'UNDO' - OR (t.contents='UNDO' AND t.tablespace_name =(SELECT value FROM v$parameter WHERE name='undo_tablespace')) + status = 'EXPIRED' }; - } elsif ($self->{sql}->is_version_minimum(version => '9')) { - $query = q{ - SELECT - a.tablespace_name "Tablespace", - b.status "Status", - b.contents "Type", - b.extent_management "Extent Mgmt", - a.bytes bytes, - a.maxbytes bytes_max, - c.bytes_free + NVL(d.bytes_expired,0) bytes_free - FROM - ( - SELECT - a.tablespace_name, - SUM(a.bytes) bytes, - SUM(DECODE(a.autoextensible, 'YES', CASE WHEN (a.bytes > a.maxbytes) THEN 0 ELSE a.maxbytes END, 'NO', a.bytes)) maxbytes - FROM - dba_data_files a - GROUP BY - tablespace_name - ) a, - sys.dba_tablespaces b, - ( - SELECT - a.tablespace_name, - SUM(a.bytes) bytes_free - FROM - dba_free_space a - GROUP BY - tablespace_name - ) c, - ( - SELECT - a.tablespace_name, - SUM(a.bytes) bytes_expired - FROM - dba_undo_extents a - WHERE - status = 'EXPIRED' - GROUP BY - tablespace_name - ) d - WHERE - a.tablespace_name = c.tablespace_name (+) - AND a.tablespace_name = b.tablespace_name - AND a.tablespace_name = d.tablespace_name (+) - AND (b.contents = 'PERMANENT' - OR (b.contents <> 'PERMANENT' - AND a.tablespace_name=(select value from v$parameter where name='undo_tablespace'))) + my $tbs_sql_undo_empty = q{ + SELECT NULL AS tablespace_name, NULL AS bytes_expired FROM DUAL + }; + my $tbs_sql_temp = q{ UNION ALL SELECT d.tablespace_name "Tablespace", @@ -212,7 +170,7 @@ sub manage_selection { b.contents "Type", b.extent_management "Extent Mgmt", sum(a.bytes_free + a.bytes_used) bytes, -- allocated - SUM(DECODE(d.autoextensible, 'YES', CASE WHEN (d.bytes > d.maxbytes) THEN 0 ELSE d.maxbytes END, 'NO', d.bytes)) bytes_max, + SUM(DECODE(d.autoextensible, 'YES', d.maxbytes, 'NO', d.bytes)) bytes_max, SUM(a.bytes_free + a.bytes_used - NVL(c.bytes_used, 0)) bytes_free FROM sys.v_$TEMP_SPACE_HEADER a, @@ -233,6 +191,58 @@ sub manage_selection { ORDER BY 1 }; + + $query = sprintf( + q{ + SELECT /*+ opt_param('optimizer_adaptive_features','false') */ + a.tablespace_name "Tablespace", + b.status "Status", + b.contents "Type", + b.extent_management "Extent Mgmt", + a.bytes bytes, + a.maxbytes bytes_max, + c.bytes_free + NVL(d.bytes_expired,0) bytes_free + FROM + ( + -- belegter und maximal verfuegbarer platz pro datafile + -- nach tablespacenamen zusammengefasst + -- => bytes + -- => maxbytes + SELECT + a.tablespace_name, + SUM(a.bytes) bytes, + SUM(DECODE(a.autoextensible, 'YES', a.maxbytes, 'NO', a.bytes)) maxbytes + FROM + dba_data_files a + GROUP BY + tablespace_name + ) a, + sys.dba_tablespaces b, + ( + -- freier platz pro tablespace + -- => bytes_free + SELECT + a.tablespace_name, + SUM(a.bytes) bytes_free + FROM + dba_free_space a + GROUP BY + tablespace_name + ) c, + ( + %s + ) d + WHERE + a.tablespace_name = c.tablespace_name (+) + AND a.tablespace_name = b.tablespace_name + AND a.tablespace_name = d.tablespace_name (+) + %s + %s + }, + defined($self->{option_results}->{notemp}) ? $tbs_sql_undo_empty : $tbs_sql_undo, + defined($self->{option_results}->{notemp}) ? "AND (b.contents != 'TEMPORARY' AND b.contents != 'UNDO')" : '', + defined($self->{option_results}->{notemp}) ? "" : $tbs_sql_temp + ); } elsif ($self->{sql}->is_version_minimum(version => '8')) { $query = q{SELECT a.tablespace_name "Tablespace", @@ -305,7 +315,8 @@ sub manage_selection { 1 }; } else { - $query = q{SELECT + $query = q{ + SELECT a.tablespace_name "Tablespace", b.status "Status", b.contents "Type", @@ -354,9 +365,13 @@ sub manage_selection { foreach my $row (@$result) { my ($name, $status, $type, $extentmgmt, $bytes, $bytes_max, $bytes_free) = @$row; + if (defined($self->{option_results}->{notemp}) && ($type eq 'UNDO' || $type eq 'TEMPORARY')) { + $self->{output}->output_add(long_msg => "skipping '" . $name . "': temporary or undo.", debug => 1); + next; + } if (defined($self->{option_results}->{filter_tablespace}) && $self->{option_results}->{filter_tablespace} ne '' && $name !~ /$self->{option_results}->{filter_tablespace}/) { - $self->{output}->output_add(long_msg => "Skipping '" . $name . "': no matching filter.", debug => 1); + $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; } if (!defined($bytes)) { @@ -365,7 +380,7 @@ sub manage_selection { next; } if (defined($self->{option_results}->{skip}) && $status eq 'OFFLINE') { - $self->{output}->output_add(long_msg => "Skipping '" . $name . "': tbs is offline", debug => 1); + $self->{output}->output_add(long_msg => "skipping '" . $name . "': tbs is offline", debug => 1); next; } @@ -432,6 +447,10 @@ Default is '%', can be 'B' Perfdata show free space +=item B<--notemp> + +skip temporary or undo tablespaces. + =item B<--skip> Skip offline tablespaces. diff --git a/database/oracle/mode/temptablespace.pm b/database/oracle/mode/temptablespace.pm deleted file mode 100644 index b11808831..000000000 --- a/database/oracle/mode/temptablespace.pm +++ /dev/null @@ -1,195 +0,0 @@ -# -# Copyright 2019 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::oracle::mode::temptablespace; - -use base qw(centreon::plugins::templates::counter); - -use strict; -use warnings; -use Digest::MD5 qw(md5_hex); - -sub custom_usage_perfdata { - my ($self, %options) = @_; - - my $label = 'used'; - my $value_perf = $self->{result_values}->{used}; - if (defined($self->{instance_mode}->{option_results}->{free})) { - $label = 'free'; - $value_perf = $self->{result_values}->{free}; - } - - my %total_options = (); - if ($self->{instance_mode}->{option_results}->{units} eq '%') { - $total_options{total} = $self->{result_values}->{total}; - $total_options{cast_int} = 1; - } - - $self->{output}->perfdata_add( - label => $label, - value => $value_perf, unit => 'B', - 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($self->{instance_mode}->{option_results}->{free})); - if ($self->{instance_mode}->{option_results}->{units} eq '%') { - $threshold_value = $self->{result_values}->{prct_used}; - $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{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("Total: %s%s Used: %s%s (%.2f%%) Free: %s%s (%.2f%%)", - $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), - $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, - $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free}); - return $msg; -} - -sub custom_usage_calc { - my ($self, %options) = @_; - - $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; - $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; - $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; - $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; - $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; - - return 0; -} - -sub set_counters { - my ($self, %options) = @_; - - $self->{maps_counters_type} = [ - { name => 'tmptablespace', type => 1, cb_prefix_output => 'prefix_tablespace_output', message_multiple => 'All temporary tablespaces are OK' }, - ]; - - $self->{maps_counters}->{tmptablespace} = [ - { label => 'usage', set => { - key_values => [ { name => 'used' }, { name => 'total' }, { name => 'display' } ], - closure_custom_calc => \&custom_usage_calc, - closure_custom_output => \&custom_usage_output, - closure_custom_perfdata => \&custom_usage_perfdata, - closure_custom_threshold_check => \&custom_usage_threshold, - } - }, - ]; -} - -sub prefix_tablespace_output { - my ($self, %options) = @_; - - return "Temp Tablespace '" . $options{instance_value}->{display} . "' "; -} - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $options{options}->add_options(arguments => { - "units:s" => { name => 'units', default => '%' }, - "free" => { name => 'free' }, - }); - - return $self; -} - -sub manage_selection { - my ($self, %options) = @_; - $self->{sql} = $options{sql}; - $self->{sql}->connect(); - - my $query = q{ - WITH - TMP as - ( - SELECT - B.name, - C.block_size, - SUM (C.bytes) b_total - FROM - v$tablespace B join - v$tempfile C - using ( ts#) - GROUP BY - B.name, C.block_size - ) - SELECT - A.tablespace_name tablespace, TMP.b_total, - SUM (A.used_blocks * TMP.block_size) b_used, - TMP.b_total - SUM (A.used_blocks * TMP.block_size) / 1024 b_free - FROM - v$sort_segment A join TMP on A.tablespace_name = TMP.name - GROUP by - A.tablespace_name, TMP.b_total - }; - - $self->{sql}->query(query => $query); - - while (my $result = $self->{sql}->fetchrow_hashref()) { - $self->{tmptablespace}->{$result->{TABLESPACE}} = { used => $result->{B_USED}, total => $result->{B_TOTAL}, display => lc $result->{TABLESPACE} }; - } - - $self->{sql}->disconnect(); -} - -1; - -__END__ - -=head1 MODE - -Check Oracle TEMP tablespaces - -=over 8 - -=item B<--units> - -Unit of thresholds (Can be : '%' (default) or 'B') - -=item B<--free> - -Threshold are on free space left - -=item B<--warning-usage> - -Threshold warning. - -=item B<--critical-usage> - -Threshold critical. - -=back - -=cut diff --git a/database/oracle/mode/undotablespace.pm b/database/oracle/mode/undotablespace.pm deleted file mode 100644 index 0528dd1c3..000000000 --- a/database/oracle/mode/undotablespace.pm +++ /dev/null @@ -1,200 +0,0 @@ -# -# Copyright 2019 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::oracle::mode::undotablespace; - -use base qw(centreon::plugins::templates::counter); - -use strict; -use warnings; -use Digest::MD5 qw(md5_hex); - -sub custom_usage_perfdata { - my ($self, %options) = @_; - - my $label = 'used'; - my $value_perf = $self->{result_values}->{used}; - if (defined($self->{instance_mode}->{option_results}->{free})) { - $label = 'free'; - $value_perf = $self->{result_values}->{free}; - } - - my %total_options = (); - if ($self->{instance_mode}->{option_results}->{units} eq '%') { - $total_options{total} = $self->{result_values}->{total}; - $total_options{cast_int} = 1; - } - - $self->{output}->perfdata_add(label => $label, - value => $value_perf, unit => 'B', - 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($self->{instance_mode}->{option_results}->{free})); - if ($self->{instance_mode}->{option_results}->{units} eq '%') { - $threshold_value = $self->{result_values}->{prct_used}; - $threshold_value = $self->{result_values}->{prct_free} if (defined($self->{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("Total: %s%s Used: %s%s (%.2f%%) Free: %s%s (%.2f%%)", - $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}), - $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}), $self->{result_values}->{prct_used}, - $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}), $self->{result_values}->{prct_free}); - return $msg; -} - -sub custom_usage_calc { - my ($self, %options) = @_; - - $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; - $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; - $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; - $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; - $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; - - return 0; -} - -sub set_counters { - my ($self, %options) = @_; - - $self->{maps_counters_type} = [ - { name => 'undotablespace', type => 1, cb_prefix_output => 'prefix_tablespace_output', message_multiple => 'All undo tablespaces are OK' }, - ]; - - $self->{maps_counters}->{undotablespace} = [ - { label => 'usage', set => { - key_values => [ { name => 'used' }, { name => 'total' }, { name => 'display' } ], - closure_custom_calc => \&custom_usage_calc, - closure_custom_output => \&custom_usage_output, - closure_custom_perfdata => \&custom_usage_perfdata, - closure_custom_threshold_check => \&custom_usage_threshold, - } - }, - ]; -} - -sub prefix_tablespace_output { - my ($self, %options) = @_; - - return "Undo Tablespace '" . $options{instance_value}->{display} . "' "; -} - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $options{options}->add_options(arguments => { - "units:s" => { name => 'units', default => '%' }, - "free" => { name => 'free' }, - }); - - return $self; -} - -sub manage_selection { - my ($self, %options) = @_; - $self->{sql} = $options{sql}; - $self->{sql}->connect(); - - my $query = q{ - WITH - UND as - ( - SELECT - a.tablespace_name, - nvl(sum(bytes),0) used_bytes - FROM - dba_undo_extents a - WHERE - tablespace_name in (select upper(value) from gv$parameter where name='undo_tablespace') and status in ('ACTIVE','UNEXPIRED') -group by a.tablespace_name - ), - DF as - ( - SELECT - b.tablespace_name, - round(SUM(decode(B.maxbytes, 0, B.BYTES/(1024*1024), B.maxbytes))) total_bytes - FROM - dba_data_files b - WHERE - tablespace_name in (select upper(value) from gv$parameter where name='undo_tablespace') group by b.tablespace_name - ) - SELECT - UND.tablespace_name, - UND.used_bytes, - DF.total_bytes - FROM UND left outer join DF - on (UND.tablespace_name=DF.tablespace_name) - order by DF.tablespace_name - }; - - $self->{sql}->query(query => $query); - - while (my $result = $self->{sql}->fetchrow_hashref()) { - $self->{undotablespace}->{$result->{TABLESPACE_NAME}} = { used => $result->{USED_BYTES}, total => $result->{TOTAL_BYTES}, display => lc $result->{TABLESPACE_NAME} }; - } - - $self->{sql}->disconnect(); -} - -1; - -__END__ - -=head1 MODE - -Check Oracle UNDO tablespaces - -=over 8 - -=item B<--units> - -Unit of threshold (Can be : '%' (default) or 'B') - -=item B<--free> - -Threshold are on free space left - -=item B<--warning-usage> - -Threshold warning. - -=item B<--critical-usage> - -Threshold critical. - -=back - -=cut diff --git a/database/oracle/plugin.pm b/database/oracle/plugin.pm index 015e4d7e4..3d346bdf0 100644 --- a/database/oracle/plugin.pm +++ b/database/oracle/plugin.pm @@ -56,9 +56,7 @@ sub new { 'sql' => 'centreon::common::protocols::sql::mode::sql', 'sql-string' => 'centreon::common::protocols::sql::mode::sqlstring', 'tablespace-usage' => 'database::oracle::mode::tablespaceusage', - 'temp-tablespace' => 'database::oracle::mode::temptablespace', 'tnsping' => 'database::oracle::mode::tnsping', - 'undo-tablespace' => 'database::oracle::mode::undotablespace', ); $self->{sql_modes}{dbi} = 'database::oracle::dbi';