(plugin) os::windows::wsman - add modes (#3451)

This commit is contained in:
qgarnier 2022-02-01 15:36:52 +01:00 committed by GitHub
parent e6e642f85d
commit 1ccb6b7c7c
16 changed files with 2467 additions and 20 deletions

View File

@ -0,0 +1,187 @@
#
# Copyright 2022 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 os::windows::wsman::mode::cpu;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use Digest::MD5 qw(md5_hex);
sub custom_cpu_avg_calc {
my ($self, %options) = @_;
my ($skipped, $buffer) = (1, 1);
my ($count, $total_cpu) = (0, 0);
foreach (keys %{$options{new_datas}}) {
if (/^(.*?cpu\d+)_PercentProcessorTime/) {
my $prefix = $1;
$skipped = 0;
next if (!defined($options{old_datas}->{$_}));
$buffer = 0;
#
#Cal Method ref: http://technet.microsoft.com/en-us/library/cc757283%28WS.10%29.aspx
#
$total_cpu += (1 - ( $options{new_datas}->{$prefix . '_PercentProcessorTime'} - $options{old_datas}->{$prefix . '_PercentProcessorTime'} ) /
( $options{new_datas}->{$prefix . '_Timestamp_Sys100NS'} - $options{old_datas}->{$prefix . '_Timestamp_Sys100NS'} ) ) * 100;
$count++;
}
}
return -10 if ($skipped == 1);
if ($buffer == 1) {
$self->{error_msg} = "Buffer creation";
return -1;
}
$self->{result_values}->{prct_used} = $total_cpu / $count;
return 0;
}
sub custom_cpu_core_calc {
my ($self, %options) = @_;
#
#Core Calc: (1 - (270377812500 - 247044062500) /
# (132846755243261461 - 132846731625406368) ) * 100 = 1.20292504074261
#
my $core_usage = (1 - ( $options{new_datas}->{$self->{instance} . '_PercentProcessorTime'} - $options{old_datas}->{$self->{instance} . '_PercentProcessorTime'} ) /
( $options{new_datas}->{$self->{instance} . '_Timestamp_Sys100NS'} - $options{old_datas}->{$self->{instance} . '_Timestamp_Sys100NS'} ) ) * 100;
$self->{result_values}->{prct_used} = $core_usage;
return 0;
}
sub prefix_cpu_core_output {
my ($self, %options) = @_;
return "CPU '" . $options{instance_value}->{display} . "' ";
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'cpu_avg', type => 0 },
{ name => 'cpu_core', type => 1, cb_prefix_output => 'prefix_cpu_core_output' }
];
$self->{maps_counters}->{cpu_avg} = [
{ label => 'average', nlabel => 'cpu.utilization.percentage', set => {
key_values => [],
closure_custom_calc => $self->can('custom_cpu_avg_calc'),
manual_keys => 1,
output_template => 'CPU(s) average usage is %.2f %%',
output_use => 'prct_used', threshold_use => 'prct_used',
perfdatas => [
{ value => 'prct_used', template => '%.2f',
min => 0, max => 100, unit => '%' }
]
}
}
];
$self->{maps_counters}->{cpu_core} = [
{ label => 'core', nlabel => 'core.cpu.utilization.percentage', set => {
key_values => [
{ name => 'PercentProcessorTime', diff => 1 }, { name => 'Timestamp_Sys100NS', diff => 1 }, { name => 'display' }
],
closure_custom_calc => $self->can('custom_cpu_core_calc'),
output_template => 'usage: %.2f %%',
output_use => 'prct_used', threshold_use => 'prct_used',
perfdatas => [
{ value => 'prct_used', template => '%.2f',
min => 0, max => 100, unit => '%', label_extra_instance => 1 }
]
}
}
];
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
});
return $self;
}
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{wsman}->request(
uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*',
wql_filter => "select Name,PercentProcessorTime,Timestamp_Sys100NS from Win32_PerfRawData_PerfOS_Processor where Name != '_Total'",
result_type => 'array'
);
$self->{cpu_avg} = {};
$self->{cpu_core} = {};
foreach (@$results) {
my $cpu_number = $_->{Name};
$self->{cpu_core}->{$cpu_number} = {
display => $cpu_number,
PercentProcessorTime => $_->{PercentProcessorTime},
Timestamp_Sys100NS => $_->{Timestamp_Sys100NS}
};
$self->{cpu_avg}->{'cpu' . $cpu_number . '_PercentProcessorTime'} = $_->{PercentProcessorTime};
$self->{cpu_avg}->{'cpu' . $cpu_number . '_Timestamp_Sys100NS'} = $_->{Timestamp_Sys100NS};
}
$self->{cache_name} = 'windows_wsman_' . $options{wsman}->get_hostname() . '_' . $options{wsman}->get_port . '_' . $self->{mode} . '_' .
(defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all'));
}
1;
__END__
=head1 MODE
Check processor usage.
=over 8
=item B<--warning-average>
Warning threshold average CPU utilization.
=item B<--critical-average>
Critical threshold average CPU utilization.
=item B<--warning-core>
Warning thresholds for each CPU core
=item B<--critical-core>
Critical thresholds for each CPU core
=back
=cut

View File

@ -0,0 +1,202 @@
#
# Copyright 2022 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 os::windows::wsman::mode::filesdate;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
use DateTime;
use centreon::plugins::misc;
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
'warning:s' => { name => 'warning' },
'critical:s' => { name => 'critical' },
'filter-filename:s' => { name => 'filter_filename' },
'folder:s' => { name => 'folder' }
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) {
$self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'.");
$self->{output}->option_exit();
}
if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) {
$self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'.");
$self->{output}->option_exit();
}
if (!defined($self->{option_results}->{folder}) || $self->{option_results}->{folder} eq '') {
$self->{output}->add_option_msg(short_msg => "Need to specify folder option.");
$self->{output}->option_exit();
}
#### Create file path
$self->{option_results}->{folder} =~ s/\//\\\\/g;
}
sub wmi_to_seconds {
my ($self, %options) = @_;
# pass in a WMI Timestamp like 2021-11-04T21:24:11.871719Z
my $sec = '';
my $age_sec = '';
my $current_dt = '';
my $current_sec = '';
my $tz = '';
my $timezone_direction = '+';
my $timezone_offset = 0;
# 1 2 3 4 5 6 7 8 9
if ($options{ts} =~ /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}).(\d*)(\S+)$/) {
my %ts_info= (
year => $1,
month => $2,
day => $3,
hour => $4,
minute => $5,
second => $6,
nanosecond => $7,
time_zone => $8 # set later
);
my $dt = DateTime->new(%ts_info);
$sec = $dt->epoch();
# force the current time into the same timezone as the queried system
$current_dt = DateTime->now(time_zone => $dt->time_zone());
$current_sec = $current_dt->epoch();
$age_sec = $current_sec - $sec;
} else {
$self->{output}->add_option_msg(short_msg => 'Wrong time format');
$self->{output}->option_exit();
}
return ($sec, $age_sec);
}
sub run {
my ($self, %options) = @_;
my $total_size = 0;
my $current_time = time();
$self->{option_results}->{folder} =~ /^(..)(.*)$/;
my ($drive, $path) = ($1, $2);
my $WQL = 'Select name, lastmodified from CIM_DataFile where drive = "' . $drive . '" AND path = "' . $path . '"';
my $results = $options{wsman}->request(
uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*',
wql_filter => $WQL,
result_type => 'array'
);
#
#$VAR1 = 'CLASS: CIM_DataFile
#LastModified;Name
#20211224000036.262291+000;C:\\Users\\Administrator\\NTUSER.DAT';
#
$self->{output}->output_add(
severity => 'OK',
short_msg => 'All files times are ok.'
);
if (!defined($results) || scalar(@$results) <= 0) {
$self->{output}->output_add(
severity => 'UNKNOWN',
short_msg => 'No file found.'
);
}
foreach (@$results) {
my $last_modified = $_->{LastModified};
my $name = centreon::plugins::misc::trim($_->{Name});
my ($time, $diff_time) = $self->wmi_to_seconds(ts => $last_modified);
next if (defined($self->{option_results}->{filter_filename}) && $self->{option_results}->{filter_filename} ne '' &&
$name !~ /$self->{option_results}->{filter_filename}/);
my $exit_code = $self->{perfdata}->threshold_check(
value => $diff_time,
threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]
);
$self->{output}->output_add(long_msg => sprintf("%s: %s seconds (time: %s)", $name, $diff_time, scalar(localtime($time))));
if (!$self->{output}->is_status(litteral => 1, value => $exit_code, compare => 'ok')) {
$self->{output}->output_add(
severity => $exit_code,
short_msg => sprintf('%s: %s seconds (time: %s)', $name, $diff_time, scalar(localtime($time)))
);
}
$self->{output}->perfdata_add(
label => $name,
nlabel => 'file.mtime.last.seconds',
unit => 's',
instances => $name,
value => $diff_time,
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')
);
}
$self->{output}->display();
$self->{output}->exit();
}
1;
__END__
=head1 MODE
Check files modified time.
=over 8
=item B<--folder>
Folder to check. (No WQL wildcard allowed)
Ex: 'C:/Users/Administrator/'.
=item B<--filter-filename>
Filter files by name.
=item B<--warning>
Threshold warning in seconds for each files (diff time).
=item B<--critical>
Threshold critical in seconds for each files (diff time).
=back
=cut

View File

@ -0,0 +1,205 @@
#
# Copyright 2022 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 os::windows::wsman::mode::filessize;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
use centreon::plugins::misc;
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
'warning-one:s' => { name => 'warning_one' },
'critical-one:s' => { name => 'critical_one' },
'warning-total:s' => { name => 'warning_total' },
'critical-total:s' => { name => 'critical_total' },
'all-files' => { name => 'all_files' },
'filter-plugin:s' => { name => 'filter_plugin' },
'folder:s' => { name => 'folder' }
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
if (($self->{perfdata}->threshold_validate(label => 'warning_one', value => $self->{option_results}->{warning_one})) == 0) {
$self->{output}->add_option_msg(short_msg => "Wrong warning-one threshold '" . $self->{warning_one} . "'.");
$self->{output}->option_exit();
}
if (($self->{perfdata}->threshold_validate(label => 'critical_one', value => $self->{option_results}->{critical_one})) == 0) {
$self->{output}->add_option_msg(short_msg => "Wrong critical-one threshold '" . $self->{critical_one} . "'.");
$self->{output}->option_exit();
}
if (($self->{perfdata}->threshold_validate(label => 'warning_total', value => $self->{option_results}->{warning_total})) == 0) {
$self->{output}->add_option_msg(short_msg => "Wrong warning-total threshold '" . $self->{warning_total} . "'.");
$self->{output}->option_exit();
}
if (($self->{perfdata}->threshold_validate(label => 'critical_total', value => $self->{option_results}->{critical_total})) == 0) {
$self->{output}->add_option_msg(short_msg => "Wrong critical-total threshold '" . $self->{critical_total} . "'.");
$self->{output}->option_exit();
}
if (!defined($self->{option_results}->{folder}) || $self->{option_results}->{folder} eq '') {
$self->{output}->add_option_msg(short_msg => "Need to specify folder option.");
$self->{output}->option_exit();
}
#### Create file path
$self->{option_results}->{folder} =~ s/\//\\\\/g;
}
sub run {
my ($self, %options) = @_;
my ($total_size, $exit_code) = (0);
$self->{option_results}->{folder} =~ /^(..)(.*)$/;
my ($drive, $path) = ($1, $2);
my $WQL = 'Select name,filesize from CIM_DataFile where drive = "' . $drive . '" AND path = "' . $path . '"';
my $results = $options{wsman}->request(
uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*',
wql_filter => $WQL,
result_type => 'array'
);
#
#CLASS: CIM_DataFile
#FileSize|Name
#1092|C:\Users\Administrator\.bash_history
#52|C:\Users\Administrator\.gitconfig
#37|C:\Users\Administrator\.lesshst
#1038|C:\Users\Administrator\.viminfo
#20|C:\Users\Administrator\ntuser.ini
#
$self->{output}->output_add(
severity => 'OK',
short_msg => "All file sizes are ok."
);
if (!defined($results) || scalar(@$results) <= 0) {
$self->{output}->output_add(
severity => 'UNKNOWN',
short_msg => 'No file found.'
);
}
foreach (@$results) {
my $size = $_->{FileSize};
my $name = centreon::plugins::misc::trim($_->{Name});
next if (defined($self->{option_results}->{filter_filename}) && $self->{option_results}->{filter_filename} ne '' &&
$name !~ /$self->{option_results}->{filter_filename}/);
$total_size += $size;
my $exit_code = $self->{perfdata}->threshold_check(
value => $size,
threshold => [ { label => 'critical_one', exit_litteral => 'critical' }, { label => 'warning_one', exit_litteral => 'warning' } ]
);
my ($size_value, $size_unit) = $self->{perfdata}->change_bytes(value => $size);
$self->{output}->output_add(long_msg => sprintf("%s: %s", $name, $size_value . ' ' . $size_unit));
if (!$self->{output}->is_status(litteral => 1, value => $exit_code, compare => 'ok')) {
$self->{output}->output_add(
severity => $exit_code,
short_msg => sprintf("'%s' size is %s", $name, $size_value . ' ' . $size_unit)
);
}
$self->{output}->perfdata_add(
nlabel => 'file.size.bytes',
unit => 'B',
instances => $name,
value => $size,
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning_one'),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical_one'),
min => 0
);
}
# Total Size
$exit_code = $self->{perfdata}->threshold_check(
value => $total_size,
threshold => [ { label => 'critical_total', exit_litteral => 'critical' }, { label => 'warning_total', exit_litteral => 'warning' } ]
);
my ($size_value, $size_unit) = $self->{perfdata}->change_bytes(value => $total_size);
$self->{output}->output_add(long_msg => sprintf("Total: %s", $size_value . ' ' . $size_unit));
if (!$self->{output}->is_status(litteral => 1, value => $exit_code, compare => 'ok')) {
$self->{output}->output_add(
severity => $exit_code,
short_msg => sprintf('Total size is %s', $size_value . ' ' . $size_unit)
);
}
$self->{output}->perfdata_add(
nlabel => 'files.size.bytes',
unit => 'B',
value => $total_size,
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning_total'),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical_total'),
min => 0
);
$self->{output}->display();
$self->{output}->exit();
}
1;
__END__
=head1 MODE
Check size of files/directories.
=over 8
=item B<--folder>
Folder to check. (No WQL wildcard allowed)
Ex: 'C:/Users/Administrator/'.
=item B<--filter-filename>
Filter files by name.
=item B<--warning-one>
Threshold warning in bytes for each files/directories.
=item B<--critical-one>
Threshold critical in bytes for each files/directories.
=item B<--warning-total>
Threshold warning in bytes for all files/directories.
=item B<--critical-total>
Threshold critical in bytes for all files/directories.
=back
=cut

View File

@ -0,0 +1,445 @@
#
# Copyright 2022 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 os::windows::wsman::mode::interfaces;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng);
use Digest::MD5 qw(md5_hex);
sub custom_traffic_perfdata {
my ($self, %options) = @_;
my ($warning, $critical);
if ($self->{instance_mode}->{option_results}->{units_traffic} eq 'percent_delta' && defined($self->{result_values}->{speed})) {
$warning = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{speed}, cast_int => 1);
$critical = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{speed}, cast_int => 1);
} elsif ($self->{instance_mode}->{option_results}->{units_traffic} =~ /bps|counter/) {
$warning = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel});
$critical = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel});
}
if ($self->{instance_mode}->{option_results}->{units_traffic} eq 'counter') {
my $nlabel = $self->{nlabel};
$nlabel =~ s/bitspersecond/bits/;
$self->{output}->perfdata_add(
nlabel => $nlabel,
unit => 'b',
instances => $self->{result_values}->{display},
value => $self->{result_values}->{traffic_counter},
warning => $warning,
critical => $critical,
min => 0
);
} else {
$self->{output}->perfdata_add(
nlabel => $self->{nlabel},
instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef,
value => sprintf('%.2f', $self->{result_values}->{traffic_per_seconds}),
warning => $warning,
critical => $critical,
min => 0, max => $self->{result_values}->{speed}
);
}
}
sub custom_traffic_threshold {
my ($self, %options) = @_;
my $exit = 'ok';
if ($self->{instance_mode}->{option_results}->{units_traffic} eq 'percent_delta' && defined($self->{result_values}->{speed})) {
$exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{traffic_prct}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]);
} elsif ($self->{instance_mode}->{option_results}->{units_traffic} eq 'bps') {
$exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{traffic_per_seconds}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]);
} elsif ($self->{instance_mode}->{option_results}->{units_traffic} eq 'counter') {
$exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{traffic_counter}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]);
}
return $exit;
}
sub custom_traffic_output {
my ($self, %options) = @_;
my ($traffic_value, $traffic_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{traffic_per_seconds}, network => 1);
return sprintf(
'traffic %s: %s/s (%s)',
$self->{result_values}->{label}, $traffic_value . $traffic_unit,
defined($self->{result_values}->{traffic_prct}) ? sprintf('%.2f%%', $self->{result_values}->{traffic_prct}) : '-'
);
}
sub custom_traffic_calc {
my ($self, %options) = @_;
$self->{result_values}->{traffic_per_seconds} = ($options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{label_ref}} - $options{old_datas}->{$self->{instance} . '_' . $options{extra_options}->{label_ref}}) /
(($options{new_datas}->{$self->{instance} . '_Timestamp_Sys100NS'} - $options{old_datas}->{$self->{instance} . '_Timestamp_Sys100NS'}) /
$options{new_datas}->{$self->{instance} . '_Frequency_Sys100NS'});
$self->{result_values}->{traffic_counter} = $options{new_datas}->{ $self->{instance} . '_' . $options{extra_options}->{label_ref} };
$self->{result_values}->{traffic_per_seconds} = sprintf('%d', $self->{result_values}->{traffic_per_seconds});
if (defined($options{new_datas}->{$self->{instance} . '_speed_' . $options{extra_options}->{label_ref}}) &&
$options{new_datas}->{$self->{instance} . '_speed_' . $options{extra_options}->{label_ref}} ne '' &&
$options{new_datas}->{$self->{instance} . '_speed_' . $options{extra_options}->{label_ref}} > 0) {
$self->{result_values}->{traffic_prct} = $self->{result_values}->{traffic_per_seconds} * 100 / $options{new_datas}->{$self->{instance} . '_speed_' . $options{extra_options}->{label_ref}};
$self->{result_values}->{speed} = $options{new_datas}->{$self->{instance} . '_speed_' . $options{extra_options}->{label_ref}};
}
$self->{result_values}->{label} = $options{extra_options}->{label_ref};
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'};
return 0;
}
##############
# Errors
sub custom_errors_perfdata {
my ($self, %options) = @_;
if ($self->{instance_mode}->{option_results}->{units_errors} =~ /percent/) {
my $nlabel = $self->{nlabel};
$nlabel =~ s/count$/percentage/;
$self->{output}->perfdata_add(
nlabel => $nlabel,
unit => '%',
instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef,
value => sprintf('%.2f', $self->{result_values}->{prct}),
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}),
min => 0,
max => 100
);
} else {
$self->{output}->perfdata_add(
nlabel => $self->{nlabel},
instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef,
value => $self->{result_values}->{used},
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}),
min => 0,
max => $self->{result_values}->{total}
);
}
}
sub custom_errors_threshold {
my ($self, %options) = @_;
my $exit = 'ok';
if ($self->{instance_mode}->{option_results}->{units_errors} =~ /percent/) {
$exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{prct}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]);
} else {
$exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]);
}
return $exit;
}
sub custom_errors_output {
my ($self, %options) = @_;
return sprintf(
'packets %s: %.2f%% (%s on %s)',
$self->{result_values}->{label},
$self->{result_values}->{prct},
$self->{result_values}->{used},
$self->{result_values}->{total}
);
}
sub custom_errors_calc {
my ($self, %options) = @_;
my $errors = $options{new_datas}->{ $self->{instance} . '_' . $options{extra_options}->{label_ref1} . $options{extra_options}->{label_ref2} };
my $errors_diff = ($options{new_datas}->{ $self->{instance} . '_' . $options{extra_options}->{label_ref1} . $options{extra_options}->{label_ref2} } - $options{old_datas}->{ $self->{instance} . '_' . $options{extra_options}->{label_ref1} . $options{extra_options}->{label_ref2} }) /
(($options{new_datas}->{$self->{instance} . '_Timestamp_Sys100NS'} - $options{old_datas}->{$self->{instance} . '_Timestamp_Sys100NS'}) /
$options{new_datas}->{$self->{instance} . '_Frequency_Sys100NS'});
my $total = $options{new_datas}->{$self->{instance} . '_total_' . $options{extra_options}->{label_ref1} . '_packets'};
my $total_diff = ($options{new_datas}->{$self->{instance} . '_total_' . $options{extra_options}->{label_ref1} . '_packets'} - $options{old_datas}->{$self->{instance} . '_total_' . $options{extra_options}->{label_ref1} . '_packets'}) /
(($options{new_datas}->{$self->{instance} . '_Timestamp_Sys100NS'} - $options{old_datas}->{$self->{instance} . '_Timestamp_Sys100NS'}) /
$options{new_datas}->{$self->{instance} . '_Frequency_Sys100NS'});
$errors_diff = sprintf('%d', $errors_diff);
$total_diff = sprintf('%d', $total_diff);
$self->{result_values}->{prct} = 0;
$self->{result_values}->{used} = $errors_diff;
$self->{result_values}->{total} = $total_diff;
if ($self->{instance_mode}->{option_results}->{units_errors} eq 'percent_delta') {
$self->{result_values}->{prct} = $errors_diff * 100 / $total_diff if ($total_diff > 0);
} elsif ($self->{instance_mode}->{option_results}->{units_errors} eq 'percent') {
$self->{result_values}->{prct} = $errors * 100 / $total if ($total > 0);
$self->{result_values}->{used} = $errors;
} elsif ($self->{instance_mode}->{option_results}->{units_errors} eq 'delta') {
$self->{result_values}->{used} = $errors_diff;
} else {
$self->{result_values}->{used} = $errors;
$self->{result_values}->{total} = $total;
}
if (defined($options{extra_options}->{label})) {
$self->{result_values}->{label} = $options{extra_options}->{label};
} else {
$self->{result_values}->{label} = $options{extra_options}->{label_ref1} . ' ' . $options{extra_options}->{label_ref2};
}
$self->{result_values}->{label1} = $options{extra_options}->{label_ref1};
$self->{result_values}->{label2} = $options{extra_options}->{label_ref2};
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'};
return 0;
}
sub prefix_interface_output {
my ($self, %options) = @_;
return "Interface '" . $options{instance_value}->{display} . "' ";
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'interfaces', type => 1, cb_prefix_output => 'prefix_interface_output', message_multiple => 'All interfaces are ok', skipped_code => { -10 => 1 } },
];
$self->{maps_counters}->{interfaces} = [
{ label => 'in-traffic', filter => 'add_traffic', nlabel => 'interface.traffic.in.bitspersecond', set => {
key_values => [ { name => 'in', diff => 1 }, { name => 'Timestamp_Sys100NS' }, { name => 'Frequency_Sys100NS' }, { name => 'speed_in' }, { name => 'display' } ],
closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'in' },
closure_custom_output => $self->can('custom_traffic_output'), output_error_template => 'traffic in: %s',
closure_custom_perfdata => $self->can('custom_traffic_perfdata'),
closure_custom_threshold_check => $self->can('custom_traffic_threshold')
}
},
{ label => 'out-traffic', filter => 'add_traffic', nlabel => 'interface.traffic.out.bitspersecond', set => {
key_values => [ { name => 'out', diff => 1 }, { name => 'Timestamp_Sys100NS' }, { name => 'Frequency_Sys100NS' }, { name => 'speed_out' }, { name => 'display' } ],
closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'out' },
closure_custom_output => $self->can('custom_traffic_output'), output_error_template => 'traffic out: %s',
closure_custom_perfdata => $self->can('custom_traffic_perfdata'),
closure_custom_threshold_check => $self->can('custom_traffic_threshold')
}
},
{ label => 'in-discard', filter => 'add_errors', nlabel => 'interface.packets.in.discard.count', set => {
key_values => [ { name => 'indiscard', diff => 1 }, { name => 'total_in_packets', diff => 1 }, { name => 'display' }, { name => 'Frequency_Sys100NS' }, { name => 'Timestamp_Sys100NS' } ],
closure_custom_calc => $self->can('custom_errors_calc'), closure_custom_calc_extra_options => { label_ref1 => 'in', label_ref2 => 'discard' },
closure_custom_output => $self->can('custom_errors_output'), output_error_template => 'packets in discard: %s',
closure_custom_perfdata => $self->can('custom_errors_perfdata'),
closure_custom_threshold_check => $self->can('custom_errors_threshold')
}
},
{ label => 'in-error', filter => 'add_errors', nlabel => 'interface.packets.in.error.count', set => {
key_values => [ { name => 'inerror', diff => 1 }, { name => 'total_in_packets', diff => 1 }, { name => 'display' }, { name => 'Frequency_Sys100NS' }, { name => 'Timestamp_Sys100NS' } ],
closure_custom_calc => $self->can('custom_errors_calc'), closure_custom_calc_extra_options => { label_ref1 => 'in', label_ref2 => 'error' },
closure_custom_output => $self->can('custom_errors_output'), output_error_template => 'packets in error: %s',
closure_custom_perfdata => $self->can('custom_errors_perfdata'),
closure_custom_threshold_check => $self->can('custom_errors_threshold')
}
},
{ label => 'out-discard', filter => 'add_errors', nlabel => 'interface.packets.out.discard.count', set => {
key_values => [ { name => 'outdiscard', diff => 1 }, { name => 'total_out_packets', diff => 1 }, { name => 'display' }, { name => 'Frequency_Sys100NS' }, { name => 'Timestamp_Sys100NS' } ],
closure_custom_calc => $self->can('custom_errors_calc'), closure_custom_calc_extra_options => { label_ref1 => 'out', label_ref2 => 'discard' },
closure_custom_output => $self->can('custom_errors_output'), output_error_template => 'packets out discard: %s',
closure_custom_perfdata => $self->can('custom_errors_perfdata'),
closure_custom_threshold_check => $self->can('custom_errors_threshold')
}
},
{ label => 'out-error', filter => 'add_errors', nlabel => 'interface.packets.out.error.count', set => {
key_values => [ { name => 'outerror', diff => 1 }, { name => 'total_out_packets', diff => 1 }, { name => 'display' }, { name => 'Frequency_Sys100NS' }, { name => 'Timestamp_Sys100NS' } ],
closure_custom_calc => $self->can('custom_errors_calc'), closure_custom_calc_extra_options => { label_ref1 => 'out', label_ref2 => 'error' },
closure_custom_output => $self->can('custom_errors_output'), output_error_template => 'packets out error: %s',
closure_custom_perfdata => $self->can('custom_errors_perfdata'),
closure_custom_threshold_check => $self->can('custom_errors_threshold')
}
}
];
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
'add-traffic' => { name => 'add_traffic' },
'add-errors' => { name => 'add_errors' },
'filter-interface:s' => { name => 'filter_interface' },
'exclude-interface:s' => { name => 'exclude_interface' },
'units-traffic:s' => { name => 'units_traffic', default => 'percent_delta' },
'units-errors:s' => { name => 'units_errors', default => 'percent_delta' },
'speed:s' => { name => 'speed' }
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
# If no options, we set add-traffic
if (!defined($self->{option_results}->{add_traffic}) &&
!defined($self->{option_results}->{add_errors})) {
$self->{option_results}->{add_traffic} = 1;
}
if (defined($self->{option_results}->{speed}) && $self->{option_results}->{speed} ne '') {
if ($self->{option_results}->{speed} !~ /^[0-9]+(\.[0-9]+){0,1}$/) {
$self->{output}->add_option_msg(short_msg => "Speed must be a positive number '" . $self->{option_results}->{speed} . "' (can be a float also).");
$self->{output}->option_exit();
} else {
$self->{option_results}->{speed} *= 1000000;
}
}
if (defined($self->{option_results}->{add_traffic})) {
$self->{option_results}->{units_traffic} = 'percent_delta'
if (!defined($self->{option_results}->{units_traffic}) ||
$self->{option_results}->{units_traffic} eq '' ||
$self->{option_results}->{units_traffic} eq '%');
if ($self->{option_results}->{units_traffic} !~ /^(?:percent|percent_delta|bps|counter)$/) {
$self->{output}->add_option_msg(short_msg => 'Wrong option --units-traffic.');
$self->{output}->option_exit();
}
}
if (defined($self->{option_results}->{add_errors})) {
$self->{option_results}->{units_errors} = 'percent_delta'
if (!defined($self->{option_results}->{units_errors}) ||
$self->{option_results}->{units_errors} eq '' ||
$self->{option_results}->{units_errors} eq '%');
if ($self->{option_results}->{units_errors} !~ /^(?:percent|percent_delta|delta|counter)$/) {
$self->{output}->add_option_msg(short_msg => 'Wrong option --units-errors.');
$self->{output}->option_exit();
}
}
}
sub do_selection {
my ($self, %options) = @_;
my $WQL = 'Select CurrentBandwidth,BytesReceivedPerSec,BytesSentPerSec,Name,Frequency_Sys100NS,OutputQueueLength,PacketsReceivedErrors,PacketsReceivedPerSec,PacketsSentPerSec,Timestamp_Sys100NS, PacketsOutboundErrors,PacketsReceivedDiscarded, PacketsOutboundDiscarded from Win32_PerfRawData_Tcpip_NetworkInterface';
my $results = $options{wsman}->request(
uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*',
wql_filter => $WQL,
result_type => 'array'
);
#
#'CLASS: Win32_PerfRawData_Tcpip_NetworkInterface
#BytesReceivedPersec;BytesSentPersec;CurrentBandwidth;Frequency_Sys100NS;Name;OutputQueueLength;PacketsOutboundDiscarded;PacketsOutboundErrors;PacketsReceivedDiscarded;PacketsReceivedErrors;PacketsReceivedPersec;PacketsSentPersec;Timestamp_Sys100NS
#7784631;2497355;1000000000;10000000;AWS PV Network Device _0;0;0;0;5;0;11351;7746;132869914560700000
#
$self->{interfaces} = {};
foreach (@$results) {
next if (defined($self->{option_results}->{filter_interface}) && $self->{option_results}->{filter_interface} ne '' &&
$self->{interface} !~ /$self->{option_results}->{filter_interface}/);
next if (defined($self->{option_results}->{exclude_interface}) && $self->{option_results}->{exclude_interface} ne '' &&
$_->{Name} =~ /$self->{option_results}->{exclude_interface}/);
$self->{interfaces}->{ $_->{Name} } = {
display => $_->{Name},
speed_in => defined($self->{option_results}->{speed}) ? $self->{option_results}->{speed} : $_->{CurrentBandwidth},
speed_out => defined($self->{option_results}->{speed}) ? $self->{option_results}->{speed} : $_->{CurrentBandwidth},
Frequency_Sys100NS => $_->{Frequency_Sys100NS},
Timestamp_Sys100NS => $_->{Timestamp_Sys100NS},
in => $_->{BytesReceivedPersec} * 8,
out => $_->{BytesSentPersec} * 8,
indiscard => $_->{PacketsReceivedDiscarded},
inerror => $_->{PacketsReceivedErrors},
outdiscard => $_->{PacketsOutboundDiscarded},
outerror => $_->{PacketsOutboundErrors},
total_out_packets => $_->{PacketsSentPersec},
total_in_packets => $_->{PacketsReceivedPersec}
};
}
if (scalar(keys %{$self->{interfaces}}) <= 0) {
$self->{output}->add_option_msg(short_msg => "No interface found.");
$self->{output}->option_exit();
}
}
sub manage_selection {
my ($self, %options) = @_;
$self->do_selection(wsman => $options{wsman});
$self->{cache_name} = 'windows_wsman_' . $options{wsman}->get_hostname() . '_' . $options{wsman}->get_port() . '_' . $self->{mode} . '_' .
(defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' .
(defined($self->{option_results}->{filter_interface}) ? md5_hex($self->{option_results}->{filter_interface}) : md5_hex('all'));
}
1;
__END__
=head1 MODE
Check interfaces.
=over 8
=item B<--add-errors>
Check interface errors.
=item B<--warning-in>
Threshold warning in percent for 'in' traffic.
=item B<--critical-in>
Threshold critical in percent for 'in' traffic.
=item B<--warning-out>
Threshold warning in percent for 'out' traffic.
=item B<--critical-out>
Threshold critical in percent for 'out' traffic.
=item B<--warning-*> B<--critical-*>
Thresholds.
Can be: 'in-error', 'in-discard', 'out-error', 'out-discard',
=item B<--units-traffic>
Units of thresholds for the traffic (Default: 'percent_delta') ('percent_delta', 'bps', 'counter').
=item B<--units-errors>
Units of thresholds for errors/discards (Default: 'percent_delta') ('percent_delta', 'percent', 'delta', 'counter').
=item B<--filter-interface>
Filter interface name (regexp can be used).
=item B<--exclude-interface>
Exclude interface name (regexp can be used).
=item B<--speed>
Set interface speed (in Mb).
=back
=cut

View File

@ -0,0 +1,129 @@
#
# Copyright 2022 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 os::windows::wsman::mode::listinterfaces;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$options{options}->add_options(arguments => {});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
}
my @labels = ('name', 'status', 'speed', 'enabled');
my $map_status = {
0 => 'down',
1 => 'connecting',
2 => 'up',
3 => 'disconnecting',
4 => 'hardwareNotPresent',
5 => 'hardwareDisable',
6 => 'hardwarMalfunction',
7 => 'mediaDisconnect',
8 => 'auth',
9 => 'authSucceeded',
10 => 'ÁuthFailed',
11 => 'invalidAddress',
12 => 'credentialsRequired'
};
sub manage_selection {
my ($self, %options) = @_;
my $entries = $options{wsman}->request(
uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*',
wql_filter => 'Select DeviceID, Name, MaxSpeed, NetConnectionStatus, NetEnabled from Win32_NetworkAdapter',
result_type => 'array'
);
my $results = {};
foreach (@$entries) {
my $status = (!defined($_->{NetConnectionStatus}) || $_->{NetConnectionStatus} eq '') ? 0 : $_->{NetConnectionStatus};
$results->{ $_->{DeviceID} } = {
name => $_->{Name},
speed => (!defined($_->{MaxSpeed}) || $_->{MaxSpeed} eq '') ? 0 : $_->{MaxSpeed},
status => $map_status->{$status},
enabled => (!defined($_->{NetEnabled}) || $_->{NetEnabled} eq '') ? 'false' : $_->{NetEnabled}
};
}
return $results;
}
sub run {
my ($self, %options) = @_;
my $results = $self->manage_selection(wsman => $options{wsman});
foreach my $instance (sort keys %$results) {
$self->{output}->output_add(long_msg =>
join('', map("[$_: " . $results->{$instance}->{$_} . ']', @labels))
);
}
$self->{output}->output_add(
severity => 'OK',
short_msg => 'List interfaces:'
);
$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 => [@labels]);
}
sub disco_show {
my ($self, %options) = @_;
my $results = $self->manage_selection(wsman => $options{wsman});
foreach (sort keys %$results) {
$self->{output}->add_disco_entry(
%{$results->{$_}}
);
}
}
1;
__END__
=head1 MODE
List interfaces.
=over 8
=back
=cut

View File

@ -0,0 +1,118 @@
#
# Copyright 2022 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 os::windows::wsman::mode::listprocesses;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$options{options}->add_options(arguments => {});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
}
my @labels = ('name', 'pid', 'status');
my %map_process_status = (
0 => 'running',
1 => 'other',
2 => 'ready',
3 => 'running',
4 => 'blocked'
);
sub manage_selection {
my ($self, %options) = @_;
my $entries = $options{wsman}->request(
uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*',
wql_filter => 'select Name,ExecutionState,CommandLine,ExecutablePath,Handle from Win32_Process',
result_type => 'array'
);
my $results = [];
foreach (@$entries) {
my $status = (!defined($_->{ExecutionState}) || $_->{ExecutionState} eq '') ? 0 : $_->{ExecutionState};
push @$results, {
name => $_->{Name},
status => $map_process_status{$status},
pid => $_->{Handle}
};
}
return $results;
}
sub run {
my ($self, %options) = @_;
my $results = $self->manage_selection(wsman => $options{wsman});
foreach my $entry (@$results) {
$self->{output}->output_add(long_msg =>
join('', map("[$_: " . $entry->{$_} . ']', @labels))
);
}
$self->{output}->output_add(
severity => 'OK',
short_msg => 'List processes:'
);
$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 => [@labels]);
}
sub disco_show {
my ($self, %options) = @_;
my $results = $self->manage_selection(wsman => $options{wsman});
foreach my $entry (@$results) {
$self->{output}->add_disco_entry(%$entry);
}
}
1;
__END__
=head1 MODE
List processes.
=over 8
=back
=cut

View File

@ -1,5 +1,5 @@
#
# Copyright 2022 Centreon (http://www.centreon.com/)
# Copyright 2021 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for

View File

@ -0,0 +1,122 @@
#
# Copyright 2022 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 os::windows::wsman::mode::liststorages;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$options{options}->add_options(arguments => {});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
}
my @labels = ('size', 'name', 'label', 'type');
my $map_types = {
0 => 'unknown',
1 => 'noRootDirectory',
2 => 'removableDisk',
3 => 'localDisk',
4 => 'networkDrive',
5 => 'compactDisc',
6 => 'ramDisk'
};
sub manage_selection {
my ($self, %options) = @_;
my $entries = $options{wsman}->request(
uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*',
wql_filter => 'Select Capacity,DeviceID,DriveLetter,DriveType,FileSystem,FreeSpace,Label,Name from Win32_Volume',
result_type => 'array'
);
my $results = {};
foreach my $entry (@$entries) {
$results->{ $entry->{DeviceID} } = {
size => $entry->{Capacity},
name => $entry->{Name},
label => $entry->{Label},
type => $map_types->{ $entry->{DriveType} }
};
}
return $results;
}
sub run {
my ($self, %options) = @_;
my $results = $self->manage_selection(wsman => $options{wsman});
foreach my $instance (sort keys %$results) {
$self->{output}->output_add(long_msg =>
join('', map("[$_: " . $results->{$instance}->{$_} . ']', @labels))
);
}
$self->{output}->output_add(
severity => 'OK',
short_msg => 'List storages:'
);
$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 => [@labels]);
}
sub disco_show {
my ($self, %options) = @_;
my $results = $self->manage_selection(wsman => $options{wsman});
foreach (sort keys %$results) {
$self->{output}->add_disco_entry(
%{$results->{$_}}
);
}
}
1;
__END__
=head1 MODE
List storages.
=over 8
=back
=cut

View File

@ -0,0 +1,126 @@
#
# Copyright 2022 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 os::windows::wsman::mode::memory;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
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});
return sprintf(
'Memory usage 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}
);
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'memory', type => 0 }
];
$self->{maps_counters}->{memory} = [
{ label => 'usage', nlabel => 'memory.usage.bytes', set => {
key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ],
closure_custom_output => $self->can('custom_usage_output'),
perfdatas => [
{ template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 }
]
}
},
{ label => 'usage-free', nlabel => 'memory.free.bytes', display_ok => 0, set => {
key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ],
closure_custom_output => $self->can('custom_usage_output'),
perfdatas => [
{ template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1 }
]
}
},
{ label => 'usage-prct', nlabel => 'memory.usage.percentage', display_ok => 0, set => {
key_values => [ { name => 'prct_used' }, { name => 'free' }, { name => 'used' }, { name => 'prct_free' }, { name => 'total' } ],
closure_custom_output => $self->can('custom_usage_output'),
perfdatas => [
{ template => '%.2f', min => 0, max => 100, unit => '%' }
]
}
}
];
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {});
return $self;
}
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{wsman}->request(
uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*',
wql_filter => "Select Name,FreePhysicalMemory,TotalVisibleMemorySize from Win32_OperatingSystem",
result_type => 'array'
);
foreach (@$results) {
my $free = $_->{FreePhysicalMemory} * 1024;
my $total = $_->{TotalVisibleMemorySize} * 1024;
$self->{memory} = {
total => $total,
used => $total - $free,
free => $free,
prct_free => $free * 100 / $total,
prct_used => 100 - ($free * 100 / $total)
};
}
}
1;
__END__
=head1 MODE
Check memory.
=over 8
=item B<--warning-*> B<--critical-*>
Thresholds.
Can be: 'usage' (B), 'usage-free' (B), 'usage-prct'.
=back
=cut

View File

@ -0,0 +1,137 @@
#
# Copyright 2022 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 os::windows::wsman::mode::pages;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
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});
return sprintf(
'space usage 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}
);
}
sub prefix_file_output {
my ($self, %options) = @_;
return "Page file '" . $options{instance} . "' ";
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'files', type => 1, cb_prefix_output => 'prefix_file_output', message_multiple => 'All page files are ok' }
];
$self->{maps_counters}->{files} = [
{ label => 'space-usage', nlabel => 'page.space.usage.bytes', set => {
key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ],
closure_custom_output => $self->can('custom_usage_output'),
perfdatas => [
{ template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1 }
]
}
},
{ label => 'space-usage-free', nlabel => 'page.space.free.bytes', display_ok => 0, set => {
key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ],
closure_custom_output => $self->can('custom_usage_output'),
perfdatas => [
{ template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1 }
]
}
},
{ label => 'space-usage-prct', nlabel => 'page.space.usage.percentage', display_ok => 0, set => {
key_values => [ { name => 'prct_used' }, { name => 'free' }, { name => 'used' }, { name => 'prct_free' }, { name => 'total' } ],
closure_custom_output => $self->can('custom_usage_output'),
perfdatas => [
{ template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }
]
}
}
];
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {});
return $self;
}
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{wsman}->request(
uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*',
wql_filter => "Select Name,AllocatedBaseSize,CurrentUsage,PeakUsage from Win32_PageFileUsage",
result_type => 'array'
);
$self->{files} = {};
foreach (@$results) {
my ($total, $used) = ($_->{AllocatedBaseSize} * 1024 * 1024, $_->{CurrentUsage} * 1024 * 1024);
$self->{files}->{ $_->{Name} } = {
total => $total,
used => $used,
free => $total - $used,
prct_free => 100 - ($used * 100 / $total),
prct_used => $used * 100 / $total
};
}
if (scalar(keys %{$self->{files}}) <= 0) {
$self->{output}->add_option_msg(short_msg => 'Cannot find page files');
$self->{output}->option_exit();
}
}
1;
__END__
=head1 MODE
Check page files.
=over 8
=item B<--warning-*> B<--critical-*>
Thresholds.
Can be: 'space-usage' (B), 'space-usage-free' (B), 'space-usage-prct'.
=back
=cut

View File

@ -0,0 +1,164 @@
#
# Copyright 2022 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 os::windows::wsman::mode::processes;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
'process-status:s' => { name => 'process_status', default => 'running' },
'process-name:s' => { name => 'process_name' },
'regexp-name' => { name => 'regexp_name' },
'warning:s' => { name => 'warning' },
'critical:s' => { name => 'critical' }
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) {
$self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'.");
$self->{output}->option_exit();
}
if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) {
$self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'.");
$self->{output}->option_exit();
}
}
my %map_process_status = (
0 => 'running',
1 => 'other',
2 => 'ready',
3 => 'running',
4 => 'blocked'
);
sub run {
my ($self, %options) = @_;
my $WQL = 'select Name,ExecutionState,CommandLine,ExecutablePath,Handle from Win32_Process';
if (defined($self->{option_results}->{process_name}) && $self->{option_results}->{process_name} ne '') {
if (defined($self->{option_results}->{regexp_name})) {
$WQL .= ' where Name like "' . $self->{option_results}->{process_name} . '"';
} else {
$WQL .= ' where Name = "' . $self->{option_results}->{process_name} . '"';
}
}
my $results = $options{wsman}->request(
uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*',
wql_filter => $WQL,
result_type => 'array'
);
#
#CLASS: Win32_Process
#CommandLine;ExecutablePath;ExecutionState;Handle;Name
#C:\\Windows\\system32\\svchost.exe -k DcomLaunch -p;C:\\Windows\\system32\\svchost.exe;0;864;svchost.exe
#"fontdrvhost.exe";C:\\Windows\\system32\\fontdrvhost.exe;0;884;fontdrvhost.exe
#"fontdrvhost.exe";C:\\Windows\\system32\\fontdrvhost.exe;0;892;fontdrvhost.exe
#C:\\Windows\\system32\\svchost.exe -k RPCSS -p;C:\\Windows\\system32\\svchost.exe;0;964;svchost.exe
#
my $detected = 0;
foreach (@$results) {
my $status = (!defined($_->{ExecutionState}) || $_->{ExecutionState} eq '') ? 0 : $_->{ExecutionState};
$self->{output}->output_add(long_msg =>
sprintf(
"Process %s [status: %s] [name: %s]",
$_->{Handle},
$map_process_status{$status},
$_->{Name}
)
);
$detected++;
}
my $exit = $self->{perfdata}->threshold_check(
value => $detected,
threshold => [
{ label => 'critical', exit_litteral => 'critical' },
{ label => 'warning', exit_litteral => 'warning' }
]
);
$self->{output}->output_add(
severity => $exit,
short_msg => "Number of current processes: $detected"
);
$self->{output}->perfdata_add(
nlabel => 'processes.detected.count',
value => $detected,
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'),
min => 0
);
$self->{output}->display();
$self->{output}->exit();
}
1;
__END__
=head1 MODE
Check system number of processes.
=over 8
=item B<--process-status>
Filter process status. Can be a regexp.
(Default: 'running').
=item B<--process-name>
Filter process name.
=item B<--regexp-name>
Allows to use WQL wildcard to filter process
name (with option --process-name).
=item B<--warning>
Threshold warning of matching processes detected.
=item B<--critical>
Threshold critical of matching processes detected.
=back
=cut

View File

@ -1,5 +1,5 @@
#
# Copyright 2022 Centreon (http://www.centreon.com/)
# Copyright 2021 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
@ -18,7 +18,7 @@
# limitations under the License.
#
package os::windows::wsman::mode::service;
package os::windows::wsman::mode::services;
use base qw(centreon::plugins::mode);
@ -35,7 +35,7 @@ sub new {
'critical' => { name => 'critical' },
'services:s' => { name => 'services' },
'auto' => { name => 'auto' },
'exclude:s' => { name => 'exclude' },
'exclude:s' => { name => 'exclude' }
});
$self->{service_rules} = {};
@ -111,8 +111,10 @@ sub check_auto {
$self->{output}->output_add(long_msg => "Service '" . $self->{result}->{$name}->{Name} . "' state: " . $self->{result}->{$name}->{State});
if ($self->{result}->{$name}->{State} !~ /^running$/i) {
$self->{output}->output_add(severity => $self->{threshold},
short_msg => "Service '" . $self->{result}->{$name}->{Name} . "' is " . $self->{result}->{$name}->{State});
$self->{output}->output_add(
severity => $self->{threshold},
short_msg => "Service '" . $self->{result}->{$name}->{Name} . "' is " . $self->{result}->{$name}->{State}
);
}
}
}
@ -128,20 +130,26 @@ sub check {
);
foreach my $name (sort(keys %{$self->{service_rules}})) {
if (!defined($self->{result}->{$name})) {
$self->{output}->output_add(severity => 'UNKNOWN',
short_msg => "Service '" . $name . "' not found");
$self->{output}->output_add(
severity => 'UNKNOWN',
short_msg => "Service '" . $name . "' not found"
);
next;
}
$self->{output}->output_add(long_msg => "Service '" . $name . "' state: " . $self->{result}->{$name}->{State});
if ($self->{service_rules}->{$name}->{operator} eq '=' &&
lc($self->{result}->{$name}->{State}) eq $self->{service_rules}->{$name}->{state}) {
$self->{output}->output_add(severity => $self->{threshold},
short_msg => "Service '" . $self->{result}->{$name}->{Name} . "' is " . $self->{result}->{$name}->{State});
$self->{output}->output_add(
severity => $self->{threshold},
short_msg => "Service '" . $self->{result}->{$name}->{Name} . "' is " . $self->{result}->{$name}->{State}
);
} elsif ($self->{service_rules}->{$name}->{operator} eq '!=' &&
lc($self->{result}->{$name}->{State}) ne $self->{service_rules}->{$name}->{state}) {
$self->{output}->output_add(severity => $self->{threshold},
short_msg => "Service '" . $self->{result}->{$name}->{Name} . "' is " . $self->{result}->{$name}->{State});
$self->{output}->output_add(
severity => $self->{threshold},
short_msg => "Service '" . $self->{result}->{$name}->{Name} . "' is " . $self->{result}->{$name}->{State}
);
}
}
}
@ -150,8 +158,10 @@ sub run {
my ($self, %options) = @_;
$self->{wsman} = $options{wsman};
$self->{output}->output_add(severity => 'OK',
short_msg => 'All service states are ok');
$self->{output}->output_add(
severity => 'OK',
short_msg => 'All service states are ok'
);
if (defined($self->{option_results}->{auto})) {
$self->check_auto();
} else {

View File

@ -0,0 +1,184 @@
#
# Copyright 2022 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 os::windows::wsman::mode::storages;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
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});
return sprintf(
'space usage 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}
);
}
sub prefix_storage_output {
my ($self, %options) = @_;
return sprintf(
"Storage '%s' [type: %s] ",
$options{instance_value}->{name},
$options{instance_value}->{type}
);
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'global', type => 0 },
{ name => 'storages', type => 1, cb_prefix_output => 'prefix_storage_output', message_multiple => 'All storages are ok', skipped_code => { -10 => 1 } }
];
$self->{maps_counters}->{global} = [
{ label => 'detected', nlabel => 'storages.detected.count', display_ok => 0, set => {
key_values => [ { name => 'detected' } ],
output_template => 'Storages detected: %d',
perfdatas => [
{ template => '%d', min => 0 }
]
}
}
];
$self->{maps_counters}->{storages} = [
{ label => 'space-usage', nlabel => 'storage.space.usage.bytes', set => {
key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ],
closure_custom_output => $self->can('custom_usage_output'),
perfdatas => [
{ template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1 }
]
}
},
{ label => 'space-usage-free', nlabel => 'storage.space.free.bytes', display_ok => 0, set => {
key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ],
closure_custom_output => $self->can('custom_usage_output'),
perfdatas => [
{ template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1 }
]
}
},
{ label => 'space-usage-prct', nlabel => 'storage.space.usage.percentage', display_ok => 0, set => {
key_values => [ { name => 'prct_used' }, { name => 'free' }, { name => 'used' }, { name => 'prct_free' }, { name => 'total' } ],
closure_custom_output => $self->can('custom_usage_output'),
perfdatas => [
{ template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }
]
}
}
];
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
'filter-name:s' => { name => 'filter_name' },
'filter-type:s' => { name => 'filter_type', default => 'localDisk' }
});
return $self;
}
my $map_types = {
0 => 'unknown',
1 => 'noRootDirectory',
2 => 'removableDisk',
3 => 'localDisk',
4 => 'networkDrive',
5 => 'compactDisc',
6 => 'ramDisk'
};
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{wsman}->request(
uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*',
wql_filter => 'Select Capacity,DeviceID,DriveLetter,DriveType,FileSystem,FreeSpace,Label,Name from Win32_Volume',
result_type => 'array'
);
# 'CLASS: Win32_Volume',
# 'Capacity;DeviceID;DriveLetter;DriveType;FileSystem;FreeSpace;Label;Name',
# '32210153472;\\\\?\\Volume{1952b268-0000-0000-0000-100000000000}\\;C:;3;NTFS;14982889472;(null);C:\\'
$self->{global} = { detected => 0 };
$self->{storages} = {};
foreach (@$results) {
my $type = $map_types->{ $_->{DriveType} };
next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$_->{Name} !~ /$self->{option_results}->{filter_name}/);
next if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' &&
$type !~ /$self->{option_results}->{filter_type}/);
my ($total, $free) = ($_->{Capacity}, $_->{FreeSpace});
$self->{storages}->{ $_->{Name} } = {
name => $_->{Name},
type => $type,
total => $total,
used => $total - $free,
free => $free,
prct_free => $free * 100 / $total,
prct_used => 100 - ($free * 100 / $total)
};
$self->{global}->{detected}++;
}
}
1;
__END__
=head1 MODE
Check storages.
=over 8
=item B<--filter-name>
Filter storages by name (can be a regexp).
=item B<--filter-type>
Filter storages by type (can be a regexp) (Default: 'localDisk').
=item B<--warning-*> B<--critical-*>
Thresholds.
Can be: 'space-usage' (B), 'space-usage-free' (B), 'space-usage-prct'.
=back
=cut

View File

@ -0,0 +1,245 @@
#
# Copyright 2022 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 os::windows::wsman::mode::time;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use centreon::plugins::misc;
use DateTime;
sub custom_usage_output {
my ($self, %options) = @_;
return sprintf(
'Time offset %d second(s): %s',
$self->{result_values}->{offset},
$self->{result_values}->{date}
);
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'offset', type => 0 }
];
$self->{maps_counters}->{offset} = [
{ label => 'offset', nlabel => 'time.offset.seconds', set => {
key_values => [ { name => 'offset' }, { name => 'date' } ],
closure_custom_output => $self->can('custom_usage_output'),
perfdatas => [
{ template => '%d', unit => 's' }
]
}
}
];
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
'ntp-hostname:s' => { name => 'ntp_hostname' },
'ntp-port:s' => { name => 'ntp_port', default => 123 },
'timezone:s' => { name => 'timezone' }
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
if (defined($self->{option_results}->{ntp_hostname})) {
centreon::plugins::misc::mymodule_load(
output => $self->{output}, module => 'Net::NTP',
error_msg => "Cannot load module 'Net::NTP'."
);
}
}
sub get_from_epoch {
my ($self, %options) = @_;
my $timezone = 'UTC';
if (defined($self->{option_results}->{timezone}) && $self->{option_results}->{timezone} ne '') {
$timezone = $self->{option_results}->{timezone};
}
my $tz = centreon::plugins::misc::set_timezone(name => $timezone);
my $dt = DateTime->from_epoch(
epoch => $options{date},
%$tz
);
my @remote_date = ($dt->year, $dt->month, $dt->day, $dt->hour, $dt->minute, $dt->second);
return ($dt->epoch, \@remote_date, $timezone);
}
sub get_from_datetime {
my ($self, %options) = @_;
my @remote_date = (
$options{year},
$options{mounth},
$options{day},
$options{hour},
$options{minute},
$options{second},
$options{ms}
);
my $timezone = 'UTC';
if (defined($self->{option_results}->{timezone}) && $self->{option_results}->{timezone} ne '') {
$timezone = $self->{option_results}->{timezone};
} elsif (defined($remote_date[9])) {
$timezone = sprintf('%s%02d%02d', $remote_date[7], $remote_date[8], $remote_date[9]); # format +0630
}
my $tz = centreon::plugins::misc::set_timezone(name => $timezone);
my $dt = DateTime->new(
year => $remote_date[0],
month => $remote_date[1],
day => $remote_date[2],
hour => $remote_date[3],
minute => $remote_date[4],
second => $remote_date[5],
%$tz
);
return ($dt->epoch, \@remote_date, $timezone);
}
sub get_target_time {
my ($self, %options) = @_;
my $results = $options{wsman}->request(
uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*',
wql_filter => "Select * from Win32_UTCTime",
result_type => 'array'
);
#
#CLASS: Win32_UTCTime
#Day;DayOfWeek;Hour;Milliseconds;Minute;Month;Quarter;Second;WeekInMonth;Year
#23;4;18;0;56;12;4;45;4;2021
#
my ($day, $hour, $minute, $month, $second, $year);
foreach (@$results) {
$day = $_->{Day};
$hour = $_->{Hour};
$minute = $_->{Minute};
$month = $_->{Month};
$second = $_->{Second};
$year = $_->{Year};
}
return $self->get_from_datetime(
year => $year,
mounth => $month,
day => $day,
hour => $hour,
minute => $minute,
second => $second
);
}
sub manage_selection {
my ($self, %options) = @_;
my ($distant_time, $remote_date, $timezone) = $self->get_target_time(%options);
if ($distant_time == 0) {
$self->{output}->add_option_msg(short_msg => "Couldn't get system date: local time: 0");
$self->{output}->option_exit();
}
my $ref_time;
if (defined($self->{option_results}->{ntp_hostname}) && $self->{option_results}->{ntp_hostname} ne '') {
my %ntp;
eval {
%ntp = Net::NTP::get_ntp_response($self->{option_results}->{ntp_hostname}, $self->{option_results}->{ntp_port});
};
if ($@) {
$self->{output}->add_option_msg(short_msg => "Couldn't connect to ntp server: " . $@);
$self->{output}->option_exit();
}
$ref_time = $ntp{'Transmit Timestamp'};
} else {
$ref_time = time();
}
my $offset = $distant_time - $ref_time;
my $remote_date_formated = sprintf(
'Local Time: %02d-%02d-%02dT%02d:%02d:%02d (%s)',
$remote_date->[0], $remote_date->[1], $remote_date->[2],
$remote_date->[3], $remote_date->[4], $remote_date->[5], $timezone
);
$self->{offset} = {
offset => sprintf('%d', $offset),
date => $remote_date_formated
};
}
1;
__END__
=head1 MODE
Check time offset of server with ntp server. Use local time if ntp-host option is not set.
SNMP gives a date with second precision (no milliseconds). Time precision is not very accurate.
Use threshold with (+-) 2 seconds offset (minimum).
=over 8
=item B<--warning-offset>
Time offset warning threshold (in seconds).
=item B<--critical-offset>
Time offset critical Threshold (in seconds).
=item B<--ntp-hostname>
Set the ntp hostname (if not set, localtime is used).
=item B<--ntp-port>
Set the ntp port (Default: 123).
=item B<--timezone>
Set the timezone of distant server. For Windows, you need to set it.
Can use format: 'Europe/London' or '+0100'.
=back
=cut

View File

@ -0,0 +1,161 @@
#
# Copyright 2022 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 os::windows::wsman::mode::uptime;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use POSIX;
use centreon::plugins::misc;
use Time::HiRes qw(time);
my $unitdiv = { s => 1, w => 604800, d => 86400, h => 3600, m => 60 };
my $unitdiv_long = { s => 'seconds', w => 'weeks', d => 'days', h => 'hours', m => 'minutes' };
sub custom_uptime_output {
my ($self, %options) = @_;
return sprintf(
'System uptime is: %s',
centreon::plugins::misc::change_seconds(value => $self->{result_values}->{uptime}, start => 'd')
);
}
sub custom_uptime_perfdata {
my ($self, %options) = @_;
$self->{output}->perfdata_add(
nlabel => 'system.uptime.' . $unitdiv_long->{ $self->{instance_mode}->{option_results}->{unit} },
unit => $self->{instance_mode}->{option_results}->{unit},
value => floor($self->{result_values}->{uptime} / $unitdiv->{ $self->{instance_mode}->{option_results}->{unit} }),
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}),
min => 0
);
}
sub custom_uptime_threshold {
my ($self, %options) = @_;
return $self->{perfdata}->threshold_check(
value => floor($self->{result_values}->{uptime} / $unitdiv->{ $self->{instance_mode}->{option_results}->{unit} }),
threshold => [
{ label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' },
{ label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' },
{ label => 'unknown-'. $self->{thlabel}, exit_litteral => 'unknown' }
]
);
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'global', type => 0 }
];
$self->{maps_counters}->{global} = [
{ label => 'uptime', set => {
key_values => [ { name => 'uptime' } ],
closure_custom_output => $self->can('custom_uptime_output'),
closure_custom_perfdata => $self->can('custom_uptime_perfdata'),
closure_custom_threshold_check => $self->can('custom_uptime_threshold')
}
}
];
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
'unit:s' => { name => 'unit', default => 's' }
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
if ($self->{option_results}->{unit} eq '' || !defined($unitdiv->{$self->{option_results}->{unit}})) {
$self->{option_results}->{unit} = 's';
}
}
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{wsman}->request(
uri => 'http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*',
wql_filter => "Select Frequency_Sys100NS,SystemUpTime,Timestamp_Object from Win32_PerfRawData_PerfOS_System",
result_type => 'array'
);
#
#CLASS: Win32_PerfRawData_PerfOS_System
#Frequency_Sys100NS;SystemUpTime;Timestamp_Object
#10000000;132847344565000000;132847576466519223
#
my $uptime = 0;
foreach my $result (@$results) {
my $Frequency_Sys100NS = $result->{Frequency_Sys100NS};
my $SystemUpTime = $result->{SystemUpTime};
my $Timestamp_Object = $result->{Timestamp_Object};
if (!defined($result->{SystemUpTime}) || !defined($result->{Timestamp_Object}) || !defined($result->{Frequency_Sys100NS})) {
$self->{output}->add_option_msg(short_msg => 'Some informations missing.');
$self->{output}->option_exit();
}
$self->{global} = { uptime => ($result->{Timestamp_Object} - $result->{SystemUpTime}) / $result->{Frequency_Sys100NS} };
}
}
1;
__END__
=head1 MODE
Check system uptime.
=over 8
=item B<--warning-uptime>
Threshold warning.
=item B<--critical-uptime>
Threshold critical.
=item B<--unit>
Select the unit for performance data and thresholds. May be 's' for seconds, 'm' for minutes,
'h' for hours, 'd' for days, 'w' for weeks. Default is seconds
=back
=cut

View File

@ -1,5 +1,5 @@
#
# Copyright 2022 Centreon (http://www.centreon.com/)
# Copyright 2021 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
@ -29,11 +29,23 @@ sub new {
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '0.1';
%{$self->{modes}} = (
$self->{modes} = {
'cpu' => 'os::windows::wsman::mode::cpu',
'files-date' => 'os::windows::wsman::mode::filesdate',
'files-size' => 'os::windows::wsman::mode::filessize',
'interfaces' => 'os::windows::wsman::mode::interfaces',
'list-interfaces' => 'os::windows::wsman::mode::listinterfaces',
'list-processes' => 'os::windows::wsman::mode::listprocesses',
'list-services' => 'os::windows::wsman::mode::listservices',
'service' => 'os::windows::wsman::mode::service',
);
'list-storages' => 'os::windows::wsman::mode::liststorages',
'memory' => 'os::windows::wsman::mode::memory',
'pages' => 'os::windows::wsman::mode::pages',
'processes' => 'os::windows::wsman::mode::processes',
'services' => 'os::windows::wsman::mode::services',
'storages' => 'os::windows::wsman::mode::storages',
'time' => 'os::windows::wsman::mode::time',
'uptime' => 'os::windows::wsman::mode::uptime'
};
return $self;
}