mirror of
https://github.com/centreon/centreon-plugins.git
synced 2025-04-08 17:06:05 +02:00
(plugin) os::windows::snmp - refactor service mode (#4573)
Co-authored-by: Colin Gagnaire <gagnaire.colin@gmail.com>
This commit is contained in:
parent
7e011ac95b
commit
77a7fd9e84
@ -20,35 +20,99 @@
|
||||
|
||||
package os::windows::snmp::mode::service;
|
||||
|
||||
use base qw(centreon::plugins::mode);
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng);
|
||||
|
||||
my %map_installed_state = (
|
||||
1 => 'uninstalled',
|
||||
2 => 'install-pending',
|
||||
3 => 'uninstall-pending',
|
||||
4 => 'installed'
|
||||
);
|
||||
my %map_operating_state = (
|
||||
1 => 'active',
|
||||
2 => 'continue-pending',
|
||||
3 => 'pause-pending',
|
||||
4 => 'paused'
|
||||
);
|
||||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $msg = "state is '" . $self->{result_values}->{operating_state};
|
||||
$msg .= "' [installed state: '" . $self->{result_values}->{installed_state} . "']";
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub prefix_services_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Service '" . $options{instance_value}->{name} . "' ";
|
||||
}
|
||||
|
||||
sub prefix_global_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return 'Number of services ';
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' },
|
||||
{ name => 'services', type => 1, cb_prefix_output => 'prefix_services_output',
|
||||
message_multiple => 'All services are ok', skipped_code => { -10 => 1, -11 => 1 } }
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{global} = [
|
||||
{ label => 'active', nlabel => 'services.active.count', display_ok => 0, set => {
|
||||
key_values => [ { name => 'active' } ],
|
||||
output_template => 'active: %d',
|
||||
perfdatas => [
|
||||
{ template => '%d', min => 0 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{ label => 'continue-pending', nlabel => 'services.continue.pending.count', display_ok => 0, set => {
|
||||
key_values => [ { name => 'continue-pending' } ],
|
||||
output_template => 'continue pending: %d',
|
||||
perfdatas => [
|
||||
{ template => '%d', min => 0 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{ label => 'pause-pending', nlabel => 'services.pause.pending.count', display_ok => 0, set => {
|
||||
key_values => [ { name => 'pause-pending' } ],
|
||||
output_template => 'pause pending: %d',
|
||||
perfdatas => [
|
||||
{ template => '%d', min => 0 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{ label => 'paused', nlabel => 'services.paused.count', display_ok => 0, set => {
|
||||
key_values => [ { name => 'paused' } ],
|
||||
output_template => 'Service paused: %d',
|
||||
perfdatas => [
|
||||
{ template => '%d', min => 0 }
|
||||
]
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{services} = [
|
||||
{ label => 'status', type => 2, set => {
|
||||
key_values => [ { name => 'operating_state' }, { name => 'installed_state' }, { name => 'name' } ],
|
||||
closure_custom_output => $self->can('custom_status_output'),
|
||||
closure_custom_perfdata => sub { return 0; },
|
||||
closure_custom_threshold_check => \&catalog_status_threshold_ng
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
|
||||
bless $self, $class;
|
||||
|
||||
$options{options}->add_options(arguments => {
|
||||
'warning:s' => { name => 'warning', },
|
||||
'critical:s' => { name => 'critical', },
|
||||
'service:s@' => { name => 'service', },
|
||||
'regexp' => { name => 'use_regexp', },
|
||||
'state:s' => { name => 'state' }
|
||||
'filter-name:s' => { name => 'filter_name' },
|
||||
'warning:s' => { name => 'warning' }, # deprecated
|
||||
'critical:s' => { name => 'critical' }, # deprecated
|
||||
'service:s@' => { name => 'service' }, # deprecated
|
||||
'regexp' => { name => 'use_regexp' }, # deprecated
|
||||
'state:s' => { name => 'state' } # deprecated
|
||||
});
|
||||
|
||||
return $self;
|
||||
@ -56,117 +120,112 @@ sub new {
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::init(%options);
|
||||
|
||||
# Compatibility for deprecated options
|
||||
if (defined($options{option_results}->{warning}) && $options{option_results}->{warning} ne '') {
|
||||
$options{option_results}->{'warning-service-active-count'} = $options{option_results}->{warning};
|
||||
}
|
||||
if (defined($options{option_results}->{critical}) && $options{option_results}->{critical} ne '') {
|
||||
$options{option_results}->{'critical-service-active-count'} = $options{option_results}->{critical};
|
||||
}
|
||||
|
||||
if (!defined($self->{option_results}->{service})) {
|
||||
$self->{output}->add_option_msg(short_msg => "Need to specify at least one '--service' option.");
|
||||
$self->{output}->option_exit();
|
||||
my $delimiter = '';
|
||||
if (defined($options{option_results}->{service})) {
|
||||
my $filter = '';
|
||||
for my $filter_service (@{$options{option_results}->{service}}) {
|
||||
next if ($filter_service eq '');
|
||||
if (defined($options{option_results}->{use_regexp})) {
|
||||
$filter.= $delimiter . $filter_service;
|
||||
} else {
|
||||
$filter .= $delimiter . quotemeta($filter_service);
|
||||
}
|
||||
|
||||
$delimiter = '|';
|
||||
}
|
||||
|
||||
if ($filter ne '' && !defined($options{option_results}->{use_regexp})) {
|
||||
$filter = '^(' . $filter . ')$';
|
||||
}
|
||||
|
||||
if (!defined($options{option_results}->{'filter_name'}) || $options{option_results}->{'filter_name'} eq '') {
|
||||
$options{option_results}->{'filter_name'} = $filter;
|
||||
}
|
||||
}
|
||||
|
||||
if (defined($options{option_results}->{state}) && $options{option_results}->{state} ne '') {
|
||||
$options{option_results}->{'critical-status'} = "%{operating_state} !~ /$options{option_results}->{state}/";
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub run {
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $map_installed_state = {
|
||||
1 => 'uninstalled',
|
||||
2 => 'install-pending',
|
||||
3 => 'uninstall-pending',
|
||||
4 => 'installed'
|
||||
};
|
||||
|
||||
my $oid_svSvcEntry = '.1.3.6.1.4.1.77.1.2.3.1';
|
||||
my $oid_svSvcInstalledState = '.1.3.6.1.4.1.77.1.2.3.1.2';
|
||||
my $oid_svSvcOperatingState = '.1.3.6.1.4.1.77.1.2.3.1.3';
|
||||
my $result = $options{snmp}->get_table(oid => $oid_svSvcEntry, start => $oid_svSvcInstalledState, end => $oid_svSvcOperatingState);
|
||||
|
||||
my $services_match = {};
|
||||
$self->{output}->output_add(
|
||||
severity => 'OK',
|
||||
short_msg => 'All service states are ok'
|
||||
my $map_operating_state = {
|
||||
1 => 'active',
|
||||
2 => 'continue-pending',
|
||||
3 => 'pause-pending',
|
||||
4 => 'paused'
|
||||
};
|
||||
|
||||
my $mapping = {
|
||||
installed_state => { oid => '.1.3.6.1.4.1.77.1.2.3.1.2', map => $map_installed_state }, # svSvcInstalledState
|
||||
operating_state => { oid => '.1.3.6.1.4.1.77.1.2.3.1.3', map => $map_operating_state } # svSvcOperatingState
|
||||
};
|
||||
my $table_svSvcEntry = '.1.3.6.1.4.1.77.1.2.3.1';
|
||||
|
||||
my $snmp_result = $options{snmp}->get_table(
|
||||
oid => $table_svSvcEntry,
|
||||
start => $mapping->{installed_state}->{oid},
|
||||
end => $mapping->{operating_state}->{oid},
|
||||
nothing_quit => 1
|
||||
);
|
||||
use Encode;
|
||||
foreach my $oid ($options{snmp}->oid_lex_sort(keys %$result)) {
|
||||
next if ($oid !~ /^$oid_svSvcOperatingState\.(\d+)\.(.*)$/);
|
||||
|
||||
$self->{global} = {
|
||||
'active' => 0,
|
||||
'continue-pending' => 0,
|
||||
'pause-pending' => 0,
|
||||
'paused' => 0
|
||||
};
|
||||
|
||||
$self->{services} = {};
|
||||
|
||||
foreach my $oid ($options{snmp}->oid_lex_sort(keys %$snmp_result)) {
|
||||
next if ($oid !~ /^$mapping->{operating_state}->{oid}\.(\d+)\.(.*)$/);
|
||||
my $instance = $1 . '.' . $2;
|
||||
|
||||
my $svc_name = $self->{output}->decode(join('', map(chr($_), split(/\./, $2))));
|
||||
my $svc_installed_state = $result->{$oid_svSvcInstalledState . '.' . $instance};
|
||||
my $svc_operating_state = $result->{$oid_svSvcOperatingState . '.' . $instance};
|
||||
for (my $i = 0; $i < scalar(@{$self->{option_results}->{service}}); $i++) {
|
||||
$services_match->{$i} = {} if (!defined($services_match->{$i}));
|
||||
my $filter = $self->{option_results}->{service}->[$i];
|
||||
if (defined($self->{option_results}->{use_regexp}) && $svc_name =~ /$filter/) {
|
||||
$services_match->{$i}->{$svc_name} = {
|
||||
operating_state => $svc_operating_state,
|
||||
installed_state => $svc_installed_state
|
||||
}
|
||||
} elsif ($svc_name eq $filter) {
|
||||
$services_match->{$i}->{$svc_name} = {
|
||||
operating_state => $svc_operating_state,
|
||||
installed_state => $svc_installed_state
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < scalar(@{$self->{option_results}->{service}}); $i++) {
|
||||
my $numbers = 0;
|
||||
my $svc_name_state_wrong = {};
|
||||
foreach my $svc_name (keys %{$services_match->{$i}}) {
|
||||
my $operating_state = $services_match->{$i}->{$svc_name}->{operating_state};
|
||||
my $installed_state = $services_match->{$i}->{$svc_name}->{installed_state};
|
||||
$self->{output}->output_add(long_msg =>
|
||||
sprintf(
|
||||
"Service '%s' match (pattern: '%s') [operating state = %s, installed state = %s]",
|
||||
$svc_name, $self->{option_results}->{service}->[$i],
|
||||
$map_operating_state{$operating_state},
|
||||
$map_installed_state{$installed_state}
|
||||
)
|
||||
);
|
||||
if (defined($self->{option_results}->{state}) && $map_operating_state{$operating_state} !~ /$self->{option_results}->{state}/) {
|
||||
delete $services_match->{$i}->{$svc_name};
|
||||
$svc_name_state_wrong->{$svc_name} = $operating_state;
|
||||
next;
|
||||
}
|
||||
$numbers++;
|
||||
}
|
||||
my $name = $self->{output}->decode(join('', map(chr($_), split(/\./, $2))));
|
||||
|
||||
my $exit = $self->{perfdata}->threshold_check(
|
||||
value => $numbers, threshold => [
|
||||
{ label => 'critical', exit_litteral => 'critical' },
|
||||
{ label => 'warning', exit_litteral => 'warning' }
|
||||
]
|
||||
next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$name !~ /$self->{option_results}->{filter_name}/);
|
||||
|
||||
my $result = $options{snmp}->map_instance(
|
||||
mapping => $mapping,
|
||||
results => $snmp_result,
|
||||
instance => $instance
|
||||
);
|
||||
$self->{output}->output_add(
|
||||
long_msg => sprintf(
|
||||
"Service pattern '%s': service list %s",
|
||||
$self->{option_results}->{service}->[$i],
|
||||
join(', ', keys %{$services_match->{$i}})
|
||||
)
|
||||
);
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
|
||||
if (scalar(keys %$svc_name_state_wrong) > 0) {
|
||||
$self->{output}->output_add(
|
||||
severity => $exit,
|
||||
short_msg => sprintf(
|
||||
"Service pattern '%s' problem: %s [following services match but has the wrong state]",
|
||||
$self->{option_results}->{service}->[$i],
|
||||
join(', ', keys %$svc_name_state_wrong)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$self->{output}->output_add(
|
||||
severity => $exit,
|
||||
short_msg => sprintf("Service problem '%s'", $self->{option_results}->{service}->[$i])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$self->{services}->{$instance} = {
|
||||
name => $name,
|
||||
operating_state => $result->{operating_state},
|
||||
installed_state => $result->{installed_state}
|
||||
};
|
||||
|
||||
$self->{global}->{ $result->{operating_state} }++;
|
||||
}
|
||||
|
||||
$self->{output}->display();
|
||||
$self->{output}->exit();
|
||||
if (scalar(keys %{$self->{services}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No service found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
@ -175,29 +234,44 @@ __END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check Windows Services in SNMP
|
||||
Check Windows services states
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Filter by service name (can be a regexp).
|
||||
|
||||
=item B<--warning-status> B<--critical-status>
|
||||
|
||||
Set WARNING or CRITICAL threshold for status.
|
||||
You can use the following variables: %{operating_state}, %{installed_state}.
|
||||
|
||||
=item B<--warning-*> B<--critical-*>
|
||||
|
||||
Thresholds on services count.
|
||||
Can be: 'active', 'continue-pending',
|
||||
'pause-pending', 'paused'.
|
||||
|
||||
=item B<--warning>
|
||||
|
||||
Warning threshold.
|
||||
DEPRECATED. Use --warning-active instead.
|
||||
|
||||
=item B<--critical>
|
||||
|
||||
Critical threshold.
|
||||
DEPRECATED. Use --critical-active instead.
|
||||
|
||||
=item B<--service>
|
||||
|
||||
Services to check. (can set multiple times)
|
||||
DEPRECATED. Use --filter-name instead.
|
||||
|
||||
=item B<--regexp>
|
||||
|
||||
Allows to use regexp to filter services.
|
||||
DEPRECATED. Use --filter-name instead.
|
||||
|
||||
=item B<--state>
|
||||
|
||||
Service state. (Regexp allowed)
|
||||
DEPRECATED. Use --critical/warning-status instead.
|
||||
|
||||
=back
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user