diff --git a/apps/centreon/local/mode/centreonpluginsversion.pm b/apps/centreon/local/mode/centreonpluginsversion.pm new file mode 100644 index 000000000..ce2829ad9 --- /dev/null +++ b/apps/centreon/local/mode/centreonpluginsversion.pm @@ -0,0 +1,93 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::centreon::local::mode::centreonpluginsversion; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::script; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "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(); + } +} + +sub run { + my ($self, %options) = @_; + + my $global_version = centreon::plugins::script::get_global_version(); + my $exit = $self->{perfdata}->threshold_check(value => $global_version, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); + + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Centreon Plugins Global Version '%s'", + $global_version)); + + $self->{output}->display(); + $self->{output}->exit(); +} + +1; + +__END__ + +=head1 MODE + +Check the centreon-plugins global version. +The version is an integer increasing (format: YYYYMMDD of the release). + +=over 8 + +=item B<--warning> + +Threshold warning. + +=item B<--critical> + +Threshold critical. + +=back + +=cut diff --git a/apps/centreon/local/plugin.pm b/apps/centreon/local/plugin.pm index eed1c8fdc..87fc4823f 100644 --- a/apps/centreon/local/plugin.pm +++ b/apps/centreon/local/plugin.pm @@ -31,9 +31,10 @@ sub new { $self->{version} = '0.1'; %{$self->{modes}} = ( - 'downtime-trap' => 'apps::centreon::local::mode::downtimetrap', - 'metaservice' => 'apps::centreon::local::mode::metaservice', - 'retention-broker' => 'apps::centreon::local::mode::retentionbroker', + 'centreon-plugins-version' => 'apps::centreon::local::mode::centreonpluginsversion', + 'downtime-trap' => 'apps::centreon::local::mode::downtimetrap', + 'metaservice' => 'apps::centreon::local::mode::metaservice', + 'retention-broker' => 'apps::centreon::local::mode::retentionbroker', ); return $self; diff --git a/apps/centreon/sql/mode/multiservices.pm b/apps/centreon/sql/mode/multiservices.pm new file mode 100644 index 000000000..b05aed885 --- /dev/null +++ b/apps/centreon/sql/mode/multiservices.pm @@ -0,0 +1,522 @@ +# Copyright 2016 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::centreon::sql::mode::multiservices; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use JSON; + +my $instance_mode; +my $config_data; + +sub custom_hosts_calc { + my ($self, %options) = @_; + + $self->{result_values}->{total_up} = $options{new_datas}->{$self->{instance} . '_up'}; + $self->{result_values}->{total_down} = $options{new_datas}->{$self->{instance} . '_down'}; + $self->{result_values}->{total_unreachable} = $options{new_datas}->{$self->{instance} . '_unreachable'}; + + return 0 +} + +sub custom_hosts_output { + my ($self, %options) = @_; + my $msg = ''; + $msg .= "[up:".$self->{result_values}->{total_up}."][down:".$self->{result_values}->{total_down}."][unreachable:".$self->{result_values}->{total_unreachable}."]"; + return $msg +} + +sub custom_hosts_perfdata { + my ($self, %options) = @_; + + foreach my $hstate ('up', 'down', 'unreachable') { + $self->{output}->perfdata_add(label => 'total_host_' . $hstate, + value => $self->{result_values}->{'total_'.$hstate}, + min => 0); + } + +} + +sub custom_hosts_threshold { + my ($self, %options) = @_; + + my $message; + my $status = 'ok'; + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_total}) && $instance_mode->{option_results}->{critical_total} ne '' && + eval "$instance_mode->{option_results}->{critical_total}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_total}) && $instance_mode->{option_results}->{warning_total} ne '' && + eval "$instance_mode->{option_results}->{warning_total}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; + +} + +sub custom_services_calc { + my ($self, %options) = @_; + + $self->{result_values}->{total_ok} = $options{new_datas}->{$self->{instance} . '_ok'}; + $self->{result_values}->{total_warning} = $options{new_datas}->{$self->{instance} . '_warning'}; + $self->{result_values}->{total_critical} = $options{new_datas}->{$self->{instance} . '_critical'}; + $self->{result_values}->{total_unknown} = $options{new_datas}->{$self->{instance} . '_unknown'}; + return 0 +} + +sub custom_services_output { + my ($self, %options) = @_; + my $msg = ''; + $msg .= "[ok:$self->{result_values}->{total_ok}][warning:$self->{result_values}->{total_warning}][critical:$self->{result_values}->{total_critical}][unknown:$self->{result_values}->{total_unknown}]\n"; + return $msg +} + +sub custom_services_perfdata { + my ($self, %options) = @_; + + foreach my $sstate ('ok', 'warning', 'critical', 'unknown') { + $self->{output}->perfdata_add(label => 'total_host_' . $sstate, + value => $self->{result_values}->{'total_'.$sstate}, + min => 0); + } + +} + +sub custom_services_threshold { + my ($self, %options) = @_; + + my $message; + my $status = 'ok'; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_total}) && $instance_mode->{option_results}->{critical_total} ne '' && + eval "$instance_mode->{option_results}->{critical_total}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_total}) && $instance_mode->{option_results}->{warning_total} ne '' && + eval "$instance_mode->{option_results}->{warning_total}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; + +} + +sub custom_groups_calc { + my ($self, %options) = @_; + + $self->{result_values}->{instance} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{ok} = $options{new_datas}->{$self->{instance} . '_ok'}; + $self->{result_values}->{warning} = $options{new_datas}->{$self->{instance} . '_warning'}; + $self->{result_values}->{critical} = $options{new_datas}->{$self->{instance} . '_critical'}; + $self->{result_values}->{unknown} = $options{new_datas}->{$self->{instance} . '_unknown'}; + $self->{result_values}->{up} = $options{new_datas}->{$self->{instance} . '_up'}; + $self->{result_values}->{down} = $options{new_datas}->{$self->{instance} . '_down'}; + $self->{result_values}->{unreachable} = $options{new_datas}->{$self->{instance} . '_unreachable'}; + + return 0 +} + +sub custom_groups_output { + my ($self, %options) = @_; + + my $msg_host = ''; + my $msg_svc = ''; + + my $msg_up = ''; + + if ($config_data->{formatting}->{display_details} eq 'true') { + $msg_host .= (defined(@{$instance_mode->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_up}})) + ? "HOSTS: [up: $self->{result_values}->{up} (" . join(' - ', @{$instance_mode->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_up}}) . ")]" + : "HOSTS: [up: $self->{result_values}->{up}]"; + $msg_host .= (defined(@{$instance_mode->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_down}})) + ? "[down: $self->{result_values}->{down} (" . join(' - ', @{$instance_mode->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_down}}) . ")]" + : "[down: $self->{result_values}->{down}]"; + $msg_host .= (defined(@{$instance_mode->{inventory}->{groups}->{unreachable}->{$self->{result_values}->{instance}}->{list_unreachable}})) + ? "[unreachable: $self->{result_values}->{unreachable} (" . join('-', @{$instance_mode->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_unreachable}}) . ")" + : "[unreachable: $self->{result_values}->{unreachable}]"; + + $msg_svc .= (defined(@{$instance_mode->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_ok}})) + ? "SERVICES: [ok: $self->{result_values}->{ok} (" . join(' - ', @{$instance_mode->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_ok}}) .")]" + : "SERVICES: [ok: $self->{result_values}->{ok}]"; + $msg_svc .= (defined(@{$instance_mode->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_warning}})) + ? "[warning: $self->{result_values}->{warning} (" . join(' - ', @{$instance_mode->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_warning}}) .")]" + : "[warning: $self->{result_values}->{warning}]"; + $msg_svc .= (defined(@{$instance_mode->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_critical}})) + ? "[critical: $self->{result_values}->{critical} (" . join(' - ', @{$instance_mode->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_critical}}) .")]" + : "[critical: $self->{result_values}->{critical}]"; + $msg_svc .= (defined(@{$instance_mode->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_unknown}})) + ? "[unknown: $self->{result_values}->{unknown} (" . join(' - ', @{$instance_mode->{inventory}->{groups}->{$self->{result_values}->{instance}}->{list_unknown}}) .")]" + : "[unknown: $self->{result_values}->{unknown}]"; + + + } else { + $msg_host .= "HOSTS [up:$self->{result_values}->{up}][down:$self->{result_values}->{down}][critical:$self->{result_values}->{critical}]"; + $msg_svc .= "SERVICES [ok:$self->{result_values}->{ok}][warning:$self->{result_values}->{warning}][critical:$self->{result_values}->{critical}][unknown:$self->{result_values}->{unknown}]"; + } + return $msg_host . ' - ' . $msg_svc . " \n"; +} + +sub custom_groups_perfdata { + my ($self, %options) = @_; + + foreach my $hstate ('up', 'down', 'unreachable') { + my $warning = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $hstate); + my $critical = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $hstate); + $self->{output}->perfdata_add(label => 'host_' . $hstate . '_' . $self->{result_values}->{instance}, + value => $self->{result_values}->{$hstate}, + warning => $warning, + critical => $critical, + min => 0); + } + foreach my $sstate ('ok', 'warning', 'critical', 'unknown') { + my $warning = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $sstate); + my $critical = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $sstate); + $self->{output}->perfdata_add(label => 'service_' . $sstate . '_' . $self->{result_values}->{instance}, + value => $self->{result_values}->{$sstate}, + warning => $warning, + critical => $critical, + min => 0); + } + +} + +sub custom_groups_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_groups}) && $instance_mode->{option_results}->{critical_groups} ne '' && + eval "$instance_mode->{option_results}->{critical_groups}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_groups}) && $instance_mode->{option_results}->{warning_groups} ne '' && + eval "$instance_mode->{option_results}->{warning_groups}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + ]; + + $self->{maps_counters}->{totalservice} = [ + { label => 'total-service', threshold => 0, set => { + key_values => [ { name => 'ok' }, { name => 'warning' }, { name => 'critical' }, { name => 'unknown' } ], + closure_custom_calc => $self->can('custom_services_calc'), + closure_custom_output => $self->can('custom_services_output'), + closure_custom_threshold_check => $self->can('custom_services_threshold'), + closure_custom_perfdata => $self->can('custom_services_perfdata'), + } + }, + ]; + $self->{maps_counters}->{totalhost} = [ + { label => 'total-host', threshold => 0, set => { + key_values => [ { name => 'up' }, { name => 'down' }, { name => 'unreachable' } ], + closure_custom_calc => $self->can('custom_hosts_calc'), + closure_custom_output => $self->can('custom_hosts_output'), + closure_custom_threshold_check => $self->can('custom_hosts_threshold'), + closure_custom_perfdata => $self->can('custom_hosts_perfdata'), + } + }, + ]; + $self->{maps_counters}->{logicalgroups} = [ + { label => 'group-svc-global', threshold => 0, set => { + key_values => [ { name => 'ok' }, { name => 'unknown' }, { name => 'critical' }, { name => 'warning' }, + { name => 'up' }, { name => 'down' }, { name => 'unreachable' }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_groups_calc'), + closure_custom_output => $self->can('custom_groups_output'), + closure_custom_threshold_check => $self->can('custom_groups_threshold'), + closure_custom_perfdata => $self->can('custom_groups_perfdata'), + } + } + + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "config-file:s" => { name => 'config_file' }, + "json-data:s" => { name => 'json_data' }, + "warning-groups:s" => { name => 'warning_groups' }, + "critical-groups:s" => { name => 'critical_groups' }, + "warning-total:s" => { name => 'warning_total' }, + "critical-total:s" => { name => 'critical_total' } + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + + if (!defined($self->{option_results}->{config_file}) && !defined($self->{option_results}->{json_data})) { + $self->{output}->add_option_msg(short_msg => "Please define --config-file or --json-data option"); + $self->{output}->option_exit(); + } + if (defined($self->{option_results}->{config_file}) && $self->{option_results}->{config_file} ne '') { + $config_data = $self->parse_json_config(config => $self->{option_results}->{config_file}); + } elsif (defined($self->{option_results}->{json_data}) && $self->{option_results}->{json_data} ne '') { + $config_data = $self->parse_json_config(config => $self->{option_results}->{json_data}); + } else { + $self->{output}->add_option_msg(short_msg => "Can't find plugin configuration file / Cannot read from --json-data option"); + $self->{output}->option_exit(); + } + + if (!exists($config_data->{mode})) { + $config_data->{mode} = 'sqlmatching'; + } + if (!exists($config_data->{formatting}->{display_details})) { + $config_data->{formatting}->{display_details} = 'true'; + } + if (!exists(${config_data}->{formatting}->{host_service_separator})) { + ${config_data}->{formatting}->{host_service_separator} = '/'; + } + if (!exists($config_data->{selection}) || scalar(keys(%{$config_data->{selection}})) <= 0) { + $self->{output}->add_option_msg(short_msg => "Check config file: selection is not present or empty"); + $self->{output}->option_exit(); + } + $self->change_macros(); + +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_groups', 'critical_groups', 'warning_total', 'critical_total')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub prefix_totalh_output { + my ($self, %options) = @_; + + return "Hosts state summary "; +} + +sub prefix_totals_output { + my ($self, %options) = @_; + + return "Services state summary "; +} + +sub prefix_groups_output { + my ($self, %options) = @_; + + return "Group '" . $options{instance_value}->{display} . "': "; +} + +sub parse_json_config { + my ($self, %options) = @_; + my $data; + my $message; + + my $json_text = do { + open(my $json_fh, "<:encoding(UTF-8)", $options{config}) + or die("Can't open \$filename\": $!\n"); + local $/; + <$json_fh> + }; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + $data = JSON->new->utf8->decode($json_text); + }; + if ($message) { + $self->{output}->add_option_msg(short_msg => "Cannot decode json config file: $message"); + $self->{output}->option_exit(); + } + return $data +} + +my %map_host_state = ( + 0 => 'up', + 1 => 'down', + 2 => 'unreachable' +); + +my %map_service_state = ( + 0 => 'ok', + 1 => 'warning', + 2 => 'critical', + 3 => 'unknown', +); + +sub manage_selection { + my ($self, %options) = @_; + # $options{sql} = sqlmode object + $self->{sql} = $options{sql}; + $self->{sql}->connect(); + + $self->{groups} = {}; + + if ($config_data->{counters}->{totalhosts} eq 'true') { + push @{$self->{maps_counters_type}}, { + name => 'totalhost', type => 0, cb_prefix_output => 'prefix_totalh_output', + }; + $self->{totalhost} = { up => 0, down => 0, unreachable => 0 }; + } + if ($config_data->{counters}->{totalservices} eq 'true') { + push @{$self->{maps_counters_type}}, { + name => 'totalservice', type => 0, cb_prefix_output => 'prefix_totals_output', + }; + $self->{totalservice} = { ok => 0, warning => 0, critical => 0, unknown => 0 }; + } + if ($config_data->{counters}->{groups} eq 'true') { + push @{$self->{maps_counters_type}}, { + name => 'logicalgroups', type => 1, cb_prefix_output => 'prefix_groups_output', message_multiple => $config_data->{formatting}->{groups_global_msg} + }; + } + + if ($config_data->{mode} eq 'sqlmatching') { + foreach my $group (keys %{$config_data->{selection}}) { + if (!exists($config_data->{selection}->{$group}->{host_name_filter})) { + $self->{output}->add_option_msg(short_msg => "Cannot find host_name_filter nor service_name_filter in config file"); + $self->{output}->option_exit(); + } + $self->{logicalgroups}->{$group} = { display => $group, + up => 0, down => 0, unreachable => 0, + ok => 0, warning => 0, critical => 0, unknown => 0 }; + + my $query = "SELECT hosts.name, services.description, hosts.state as hstate, services.state as sstate, services.output as soutput + FROM centreon_storage.hosts, centreon_storage.services WHERE hosts.host_id=services.host_id + AND hosts.name NOT LIKE 'Module%' AND hosts.enabled=1 AND services.enabled=1 + AND hosts.name LIKE '" . $config_data->{selection}->{$group}->{'host_name_filter'} . "' + AND services.description LIKE '" . $config_data->{selection}->{$group}->{'service_name_filter'} . "'"; + + $self->{sql}->query(query => $query); + while ((my $row = $self->{sql}->fetchrow_hashref())) { + if (!exists($instance_mode->{inventory}->{hosts}->{$group}->{$row->{name}})) { + push @{$instance_mode->{inventory}->{groups}->{$group}->{'list_'.$map_host_state{$row->{hstate}}}} ,$row->{name}; + $self->{totalhost}->{$map_host_state{$row->{hstate}}}++; + $self->{logicalgroups}->{$group}->{$map_host_state{$row->{hstate}}}++; + } + push @{$instance_mode->{inventory}->{groups}->{$group}->{'list_'.$map_service_state{$row->{sstate}}}}, $row->{name} . ${config_data}->{formatting}->{host_service_separator} . $row->{description}; + + $instance_mode->{inventory}->{hosts}->{$group}->{$row->{name}} = $row->{hstate}; + $instance_mode->{inventory}->{services}{ $row->{name} . ${config_data}->{formatting}->{host_service_separator} . $row->{description} } = { state => $row->{sstate}, output => $row->{soutput} } ; + $instance_mode->{inventory}->{groups}->{$group}->{$row->{name} . ${config_data}->{formatting}->{host_service_separator} . $row->{description}} = { state => $row->{sstate}, output => $row->{soutput} }; + + $self->{totalservice}->{$map_service_state{$row->{sstate}}}++; + $self->{logicalgroups}->{$group}->{$map_service_state{$row->{sstate}}}++; + } + } + } elsif ($config_data->{mode} eq 'exactmatch') { + foreach my $group (keys %{$config_data->{selection}}) { + $self->{logicalgroups}->{$group} = { display => $group, + up => 0, down => 0, unreachable => 0, + ok => 0, warning => 0, critical => 0, unknown => 0 }; + foreach my $tuple (keys %{$config_data->{selection}->{$group}}) { + my $query = "SELECT hosts.name, services.description, hosts.state as hstate, services.state as sstate, services.output as soutput + FROM centreon_storage.hosts, centreon_storage.services WHERE hosts.host_id=services.host_id + AND hosts.name NOT LIKE 'Module%' AND hosts.enabled=1 AND services.enabled=1 + AND hosts.name = '" . $tuple . "' + AND services.description = '" . $config_data->{selection}->{$group}->{$tuple} . "'"; + $self->{sql}->query(query => $query); + while ((my $row = $self->{sql}->fetchrow_hashref())) { + if (!exists($instance_mode->{inventory}->{hosts}->{$group}->{$row->{name}})) { + push @{$instance_mode->{inventory}->{groups}->{$group}->{'list_'.$map_host_state{$row->{hstate}}}} ,$row->{name}; + $self->{totalhost}->{$map_host_state{$row->{hstate}}}++; + $self->{logicalgroups}->{$group}->{$map_host_state{$row->{hstate}}}++; + } + push @{$instance_mode->{inventory}->{groups}->{$group}->{'list_'.$map_service_state{$row->{sstate}}}}, $row->{name} . ${config_data}->{formatting}->{host_service_separator} . $row->{description}; + + $instance_mode->{inventory}->{hosts}->{$group}->{$row->{name}} = $row->{hstate}; + $instance_mode->{inventory}->{services}{ $row->{name} . ${config_data}->{formatting}->{host_service_separator} . $row->{description} } = { state => $row->{sstate}, output => $row->{soutput} } ; + $instance_mode->{inventory}->{groups}->{$group}->{$row->{name} . ${config_data}->{formatting}->{host_service_separator} . $row->{description}} = { state => $row->{sstate}, output => $row->{soutput} }; + $self->{totalservice}->{$map_service_state{$row->{sstate}}}++; + $self->{logicalgroups}->{$group}->{$map_service_state{$row->{sstate}}}++; + } + } + } + } +} + +1; + +__END__ + +=head1 MODE + + +=over 8 + +=item B<--config-file> + +Specify the full path to a json config file + +=item B<--json-data> + +JSON input + +=item B<--filter-counters> + +Can be 'totalhost','totalservice','groups'. Better to manage it in config file + +=item B<--warning-*> + +Can be 'total' for host and service, 'groups' for groups +e.g --warning-total '%{total_unreachable} > 4' --warning-groups '%{instance} eq 'ESX' && %{total_down} > 2 && %{total_critical} > 4' + +=item B<--critical-*> + +Can be 'total' for host and service, 'groups' for groups + +=back + +=cut diff --git a/apps/hyperv/2012/local/mode/nodeintegrationservice.pm b/apps/hyperv/2012/local/mode/nodeintegrationservice.pm index 49042c056..3d5554d18 100644 --- a/apps/hyperv/2012/local/mode/nodeintegrationservice.pm +++ b/apps/hyperv/2012/local/mode/nodeintegrationservice.pm @@ -160,6 +160,7 @@ sub new { "no-ps" => { name => 'no_ps' }, "ps-exec-only" => { name => 'ps_exec_only' }, "filter-vm:s" => { name => 'filter_vm' }, + "filter-note:s" => { name => 'filter_note' }, "filter-status:s" => { name => 'filter_status', default => 'running' }, "warning-global-status:s" => { name => 'warning_global_status', default => '%{integration_service_state} =~ /Update required/i' }, "critical-global-status:s" => { name => 'critical_global_status', default => '' }, @@ -205,14 +206,14 @@ sub manage_selection { $self->{output}->exit(); } - #[name= test1 ][state= Running ][IntegrationServicesState= Update required ][IntegrationServicesVersion= 3.1 ] + #[name= test1 ][state= Running ][IntegrationServicesState= Update required ][IntegrationServicesVersion= 3.1 ][note= ] #[service= Time Synchronization ][enabled= True][primaryOperationalStatus= NoContact ][secondaryOperationalStatus= ] #[service= Heartbeat ][enabled= True][primaryOperationalStatus= NoContact ][secondaryOperationalStatus= ] #[service= Key-Value Pair Exchange ][enabled= True][primaryOperationalStatus= NoContact ][secondaryOperationalStatus= ] #[service= Shutdown ][enabled= True][primaryOperationalStatus= NoContact ][secondaryOperationalStatus= ] #[service= VSS ][enabled= True][primaryOperationalStatus= NoContact ][secondaryOperationalStatus= ] #[service= Guest Service Interface ][enabled= False][primaryOperationalStatus= Ok ][secondaryOperationalStatus= ] - #[name= test2 ][state= Running ][IntegrationServicesState= ][IntegrationServicesVersion= ] + #[name= test2 ][state= Running ][IntegrationServicesState= ][IntegrationServicesVersion= ][note= ] #[service= Time Synchronization ][enabled= True][primaryOperationalStatus= NoContact ][secondaryOperationalStatus= ] #[service= Heartbeat ][enabled= True][primaryOperationalStatus= NoContact ][secondaryOperationalStatus= ] #[service= Key-Value Pair Exchange ][enabled= True][primaryOperationalStatus= NoContact ][secondaryOperationalStatus= ] @@ -220,8 +221,8 @@ sub manage_selection { $self->{vm} = {}; my $id = 1; - while ($stdout =~ /^\[name=\s*(.*?)\s*\]\[state=\s*(.*?)\s*\]\[IntegrationServicesState=\s*(.*?)\s*\]\[IntegrationServicesVersion=\s*(.*?)\s*\](.*?)(?=\[name=|\z)/msig) { - my ($name, $status, $integration_service_state, $integration_service_version, $content) = ($1, $2, $3, $4, $5); + while ($stdout =~ /^\[name=\s*(.*?)\s*\]\[state=\s*(.*?)\s*\]\[IntegrationServicesState=\s*(.*?)\s*\]\[IntegrationServicesVersion=\s*(.*?)\s*\]\[note=\s*(.*?)\s*\](.*?)(?=\[name=|\z)/msig) { + my ($name, $status, $integration_service_state, $integration_service_version, $note, $content) = ($1, $2, $3, $4, $5, $6); if (defined($self->{option_results}->{filter_vm}) && $self->{option_results}->{filter_vm} ne '' && $name !~ /$self->{option_results}->{filter_vm}/i) { @@ -233,6 +234,11 @@ sub manage_selection { $self->{output}->output_add(long_msg => "skipping '" . $status . "': no matching filter.", debug => 1); next; } + if (defined($self->{option_results}->{filter_note}) && $self->{option_results}->{filter_note} ne '' && + $note !~ /$self->{option_results}->{filter_note}/i) { + $self->{output}->output_add(long_msg => "skipping '" . $note . "': no matching filter.", debug => 1); + next; + } $self->{vm}->{$id} = { display => $name, vm => $name, service => {} }; $self->{vm}->{$id}->{global} = { @@ -283,14 +289,18 @@ Command options (Default: '-InputFormat none -NoLogo -EncodedCommand'). Print powershell output. -=item B<--filter-status> - -Filter virtual machine status (can be a regexp) (Default: 'running'). - =item B<--filter-vm> Filter virtual machines (can be a regexp). +=item B<--filter-note> + +Filter by VM notes (can be a regexp). + +=item B<--filter-status> + +Filter virtual machine status (can be a regexp) (Default: 'running'). + =item B<--warning-global-status> Set warning threshold for status (Default: '%{integration_service_state} =~ /Update required/i'). diff --git a/apps/hyperv/2012/local/mode/nodesnapshot.pm b/apps/hyperv/2012/local/mode/nodesnapshot.pm index 64d09c053..4aab7d77c 100644 --- a/apps/hyperv/2012/local/mode/nodesnapshot.pm +++ b/apps/hyperv/2012/local/mode/nodesnapshot.pm @@ -71,6 +71,7 @@ sub new { "no-ps" => { name => 'no_ps' }, "ps-exec-only" => { name => 'ps_exec_only' }, "filter-vm:s" => { name => 'filter_vm' }, + "filter-note:s" => { name => 'filter_note' }, "filter-status:s" => { name => 'filter_status', default => 'running' }, }); return $self; @@ -94,14 +95,14 @@ sub manage_selection { $self->{output}->exit(); } - #[name= ISC1-SV04404 ][state= Running ] + #[name= ISC1-SV04404 ][state= Running ][note= ] #[checkpointCreationTime= 1475502921.28734 ] #[checkpointCreationTime= 1475503073.81975 ] $self->{vm} = {}; my $id = 1; - while ($stdout =~ /^\[name=\s*(.*?)\s*\]\[state=\s*(.*?)\s*\](.*?)(?=\[name=|\z)/msig) { - my ($name, $status, $content) = ($1, $2, $3); + while ($stdout =~ /^\[name=\s*(.*?)\s*\]\[state=\s*(.*?)\s*\]\[note=\s*(.*?)\s*\](.*?)(?=\[name=|\z)/msig) { + my ($name, $status, $note, $content) = ($1, $2, $3, $4); my $chkpt = -1; while ($content =~ /\[checkpointCreationTime=s*(.*?)\s*\]/msig) { $chkpt = $1 if ($chkpt == -1 || $chkpt > $1); @@ -112,6 +113,11 @@ sub manage_selection { $name !~ /$self->{option_results}->{filter_vm}/i) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; + } + if (defined($self->{option_results}->{filter_note}) && $self->{option_results}->{filter_note} ne '' && + $note !~ /$self->{option_results}->{filter_note}/i) { + $self->{output}->output_add(long_msg => "skipping '" . $note . "': no matching filter.", debug => 1); + next; } if (defined($self->{option_results}->{filter_status}) && $self->{option_results}->{filter_status} ne '' && $status !~ /$self->{option_results}->{filter_status}/i) { @@ -167,6 +173,10 @@ Filter virtual machine status (can be a regexp) (Default: 'running'). Filter virtual machines (can be a regexp). +=item B<--filter-note> + +Filter by VM notes (can be a regexp). + =item B<--warning-*> Threshold warning. diff --git a/apps/hyperv/2012/local/mode/nodevmstatus.pm b/apps/hyperv/2012/local/mode/nodevmstatus.pm index 4749f4cfe..b21251b8d 100644 --- a/apps/hyperv/2012/local/mode/nodevmstatus.pm +++ b/apps/hyperv/2012/local/mode/nodevmstatus.pm @@ -109,6 +109,7 @@ sub new { "no-ps" => { name => 'no_ps' }, "ps-exec-only" => { name => 'ps_exec_only' }, "filter-vm:s" => { name => 'filter_vm' }, + "filter-note:s" => { name => 'filter_note' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{status} !~ /Operating normally/i' }, }); @@ -151,24 +152,34 @@ sub manage_selection { $self->{output}->exit(); } - #[name= XXXX1 ][state= Running ][status= Operating normally ][IsClustered= True ] - #[name= XXXX2 ][state= Running ][status= Operating normally ][IsClustered= False ] - #[name= XXXX3 ][state= Running ][status= Operating normally ][IsClustered= False ] + #[name= XXXX1 ][state= Running ][status= Operating normally ][IsClustered= True ][note= ] + #[name= XXXX2 ][state= Running ][status= Operating normally ][IsClustered= False ][note= ] + #[name= XXXX3 ][state= Running ][status= Operating normally ][IsClustered= False ][note= ] $self->{vm} = {}; my $id = 1; - while ($stdout =~ /^\[name=\s*(.*?)\s*\]\[state=\s*(.*?)\s*\]\[status=\s*(.*?)\s*\]\[IsClustered=\s*(.*?)\s*\].*?(?=\[name=|\z)/msig) { - my ($name, $state, $status, $is_clustered) = ($1, $2, $3, $4); + while ($stdout =~ /^\[name=\s*(.*?)\s*\]\[state=\s*(.*?)\s*\]\[status=\s*(.*?)\s*\]\[IsClustered=\s*(.*?)\s*\]\[note=\s*(.*?)\s*\].*?(?=\[name=|\z)/msig) { + my ($name, $state, $status, $is_clustered, $note) = ($1, $2, $3, $4, $5); if (defined($self->{option_results}->{filter_vm}) && $self->{option_results}->{filter_vm} ne '' && $name !~ /$self->{option_results}->{filter_vm}/i) { $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); next; } + if (defined($self->{option_results}->{filter_note}) && $self->{option_results}->{filter_note} ne '' && + $note !~ /$self->{option_results}->{filter_note}/i) { + $self->{output}->output_add(long_msg => "skipping '" . $note . "': no matching filter.", debug => 1); + next; + } $self->{vm}->{$id} = { display => $name, vm => $name, status => $status, state => $state, is_clustered => $is_clustered }; $id++; } + + if (scalar(keys %{$self->{vm}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No virtual machine found."); + $self->{output}->option_exit(); + } } 1; @@ -210,6 +221,10 @@ Print powershell output. Filter virtual machines (can be a regexp). +=item B<--filter-note> + +Filter by VM notes (can be a regexp). + =item B<--warning-status> Set warning threshold for status (Default: ''). diff --git a/apps/hyperv/2012/local/mode/scvmmintegrationservice.pm b/apps/hyperv/2012/local/mode/scvmmintegrationservice.pm index fbaf574c5..dfc96d8e0 100644 --- a/apps/hyperv/2012/local/mode/scvmmintegrationservice.pm +++ b/apps/hyperv/2012/local/mode/scvmmintegrationservice.pm @@ -183,7 +183,7 @@ sub manage_selection { $values{hostgroup} =~ s/\\/\//g; my $filtered = 0; - foreach (('name', 'description', 'status', 'hostgroup')) { + foreach (('vm', 'description', 'status', 'hostgroup')) { if (defined($self->{option_results}->{'filter_' . $_}) && $self->{option_results}->{'filter_' . $_} ne '' && $values{$_} !~ /$self->{option_results}->{'filter_' . $_}/i) { $self->{output}->output_add(long_msg => "skipping '" . $values{$_} . "': no matching filter.", debug => 1); diff --git a/apps/hyperv/2012/local/mode/scvmmsnapshot.pm b/apps/hyperv/2012/local/mode/scvmmsnapshot.pm index 16db4947b..44d2e0573 100644 --- a/apps/hyperv/2012/local/mode/scvmmsnapshot.pm +++ b/apps/hyperv/2012/local/mode/scvmmsnapshot.pm @@ -75,6 +75,7 @@ sub new { "no-ps" => { name => 'no_ps' }, "ps-exec-only" => { name => 'ps_exec_only' }, "filter-vm:s" => { name => 'filter_vm' }, + "filter-description:s"=> { name => 'filter_description' }, "filter-hostgroup:s" => { name => 'filter_hostgroup' }, "filter-status:s" => { name => 'filter_status', default => 'running' }, }); @@ -117,38 +118,34 @@ sub manage_selection { $self->{output}->exit(); } - #[name= test-server ][status= Running ][cloud= ][hostgrouppath= All Hosts\CORP\Test\test-server ] + #[name= test-server ][description= ][status= Running ][cloud= ][hostgrouppath= All Hosts\CORP\Test\test-server ] #[checkpointAddedTime= 1475502741.957 ] #[checkpointAddedTime= 1475502963.21 ] $self->{vm} = {}; my $id = 1; - while ($stdout =~ /^\[name=\s*(.*?)\s*\]\[status=\s*(.*?)\s*\]\[cloud=\s*(.*?)\s*\]\[hostgrouppath=\s*(.*?)\s*\](.*?)(?=\[name=|\z)/msig) { - my ($name, $status, $cloud, $hg, $content) = ($1, $2, $3, $4, $5); + while ($stdout =~ /^\[name=\s*(.*?)\s*\]\[description=\s*(.*?)\s*\]\[status=\s*(.*?)\s*\]\[cloud=\s*(.*?)\s*\]\[hostgrouppath=\s*(.*?)\s*\](.*?)(?=\[name=|\z)/msig) { + my %values = (vm => $1, description => $2, status => $3, cloud => $4, hostgroup => $5); + my $content = $6; + my $chkpt = -1; while ($content =~ /\[checkpointAddedTime=s*(.*?)\s*\]/msig) { $chkpt = $1 if ($chkpt == -1 || $chkpt > $1); } next if ($chkpt == -1); - $hg =~ s/\\/\//g; - if (defined($self->{option_results}->{filter_vm}) && $self->{option_results}->{filter_vm} ne '' && - $name !~ /$self->{option_results}->{filter_vm}/i) { - $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); - next; - } - if (defined($self->{option_results}->{filter_hostgroup}) && $self->{option_results}->{filter_hostgroup} ne '' && - $hg !~ /$self->{option_results}->{filter_hostgroup}/i) { - $self->{output}->output_add(long_msg => "skipping '" . $hg . "': no matching filter.", debug => 1); - next; - } - if (defined($self->{option_results}->{filter_status}) && $self->{option_results}->{filter_status} ne '' && - $status !~ /$self->{option_results}->{filter_status}/i) { - $self->{output}->output_add(long_msg => "skipping '" . $status . "': no matching filter.", debug => 1); - next; + my $filtered = 0; + $values{hostgroup} =~ s/\\/\//g; + foreach (('vm', 'description', 'status', 'hostgroup')) { + if (defined($self->{option_results}->{'filter_' . $_}) && $self->{option_results}->{'filter_' . $_} ne '' && + $values{$_} !~ /$self->{option_results}->{'filter_' . $_}/i) { + $self->{output}->output_add(long_msg => "skipping '" . $values{$_} . "': no matching filter.", debug => 1); + $filtered = 1; + last; + } } - $self->{vm}->{$id} = { display => $name, snapshot => time() - $chkpt }; + $self->{vm}->{$id} = { display => $values{vm}, snapshot => time() - $chkpt } if ($filtered == 0); $id++; } } @@ -212,6 +209,10 @@ Filter virtual machine status (can be a regexp) (Default: 'running'). Filter virtual machines (can be a regexp). +=item B<--filter-description> + +Filter by description (can be a regexp). + =item B<--filter-hostgroup> Filter hostgroup (can be a regexp). diff --git a/apps/hyperv/2012/local/mode/scvmmvmstatus.pm b/apps/hyperv/2012/local/mode/scvmmvmstatus.pm index bcfa068ec..6563b126a 100644 --- a/apps/hyperv/2012/local/mode/scvmmvmstatus.pm +++ b/apps/hyperv/2012/local/mode/scvmmvmstatus.pm @@ -112,6 +112,7 @@ sub new { "no-ps" => { name => 'no_ps' }, "ps-exec-only" => { name => 'ps_exec_only' }, "filter-vm:s" => { name => 'filter_vm' }, + "filter-description:s"=> { name => 'filter_description' }, "filter-hostgroup:s" => { name => 'filter_hostgroup' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{status} !~ /Running|Stopped/i' }, @@ -168,29 +169,33 @@ sub manage_selection { $self->{output}->exit(); } - #[name= test-server ][status= Running ][cloud= ][hostgrouppath= All Hosts\CORP\Test\test-server ] - #[name= test-server2 ][status= Running ][cloud= ][hostgrouppath= All Hosts\CORP\Test\test-server2 ] + #[name= test-server ][description= ][status= Running ][cloud= ][hostgrouppath= All Hosts\CORP\Test\test-server ] + #[name= test-server2 ][description= ][status= Running ][cloud= ][hostgrouppath= All Hosts\CORP\Test\test-server2 ] $self->{vm} = {}; my $id = 1; - while ($stdout =~ /^\[name=\s*(.*?)\s*\]\[status=\s*(.*?)\s*\]\[cloud=\s*(.*?)\s*\]\[hostgrouppath=\s*(.*?)\s*\].*?(?=\[name=|\z)/msig) { - my ($name, $status, $cloud, $hg) = ($1, $2, $3, $4); - - $hg =~ s/\\/\//g; - if (defined($self->{option_results}->{filter_vm}) && $self->{option_results}->{filter_vm} ne '' && - $name !~ /$self->{option_results}->{filter_vm}/i) { - $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); - next; - } - if (defined($self->{option_results}->{filter_hostgroup}) && $self->{option_results}->{filter_hostgroup} ne '' && - $hg !~ /$self->{option_results}->{filter_hostgroup}/i) { - $self->{output}->output_add(long_msg => "skipping '" . $hg . "': no matching filter.", debug => 1); - next; + while ($stdout =~ /^\[name=\s*(.*?)\s*\]\[description=\s*(.*?)\s*\]\[status=\s*(.*?)\s*\]\[cloud=\s*(.*?)\s*\]\[hostgrouppath=\s*(.*?)\s*\].*?(?=\[name=|\z)/msig) { + my %values = (vm => $1, description => $2, status => $3, cloud => $4, hostgroup => $5); + + my $filtered = 0; + $values{hostgroup} =~ s/\\/\//g; + foreach (('vm', 'description', 'hostgroup')) { + if (defined($self->{option_results}->{'filter_' . $_}) && $self->{option_results}->{'filter_' . $_} ne '' && + $values{$_} !~ /$self->{option_results}->{'filter_' . $_}/i) { + $self->{output}->output_add(long_msg => "skipping '" . $values{$_} . "': no matching filter.", debug => 1); + $filtered = 1; + last; + } } - $self->{vm}->{$id} = { display => $name, vm => $name, status => $status, hostgroup => $hg }; + $self->{vm}->{$id} = { display => $values{vm}, vm => $values{vm}, status => $values{status}, hostgroup => $values{hostgroup} }; $id++; } + + if (scalar(keys %{$self->{vm}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No virtual machine found."); + $self->{output}->option_exit(); + } } 1; @@ -252,6 +257,10 @@ Filter virtual machines (can be a regexp). Filter hostgroup (can be a regexp). +=item B<--filter-description> + +Filter by description (can be a regexp). + =item B<--warning-status> Set warning threshold for status (Default: ''). diff --git a/apps/jmeter/mode/scenario.pm b/apps/jmeter/mode/scenario.pm new file mode 100644 index 000000000..9ead71843 --- /dev/null +++ b/apps/jmeter/mode/scenario.pm @@ -0,0 +1,270 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::jmeter::mode::scenario; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use XML::XPath; +use XML::XPath::XMLParser; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "remote" => { name => 'remote' }, + "hostname:s" => { name => 'hostname' }, + "ssh-option:s@" => { name => 'ssh_option' }, + "ssh-path:s" => { name => 'ssh_path' }, + "ssh-command:s" => { name => 'ssh_command', default => 'ssh' }, + "sudo" => { name => 'sudo' }, + "command:s" => { name => 'command', default => 'jmeter' }, + "command-path:s" => { name => 'command_path' }, + "command-extra-options:s" => { name => 'command_extra_options' }, + "timeout:s" => { name => 'timeout', default => 50 }, + "directory:s" => { name => 'directory' }, + "scenario:s" => { name => 'scenario' }, + "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(); + } + if (!defined($self->{option_results}->{scenario})) { + $self->{output}->add_option_msg(short_msg => "Please specify a scenario name."); + $self->{output}->option_exit(); + } +} + +sub run { + my ($self, %options) = @_; + + my $filename = $self->{option_results}->{directory} . '/' . $self->{option_results}->{scenario} . '.jmx'; + my $command_options .= '-t ' . $filename; + + # Temporary write result on stderr + $command_options .= ' -l /dev/stderr'; + + # Write logs to trash + $command_options .= ' -j /dev/null'; + + $command_options .= ' -n'; + $command_options .= ' -J jmeter.save.saveservice.output_format=xml'; + + if (defined($self->{option_results}->{command_extra_options})) { + $command_options .= ' ' . $self->{option_results}->{command_extra_options}; + } + + # Redirect result on stdout and default stdout to trash + $command_options .= ' 2>&1 >/dev/null'; + + my $stdout = centreon::plugins::misc::execute(output => $self->{output}, + options => $self->{option_results}, + sudo => $self->{option_results}->{sudo}, + command => $self->{option_results}->{command}, + command_path => $self->{option_results}->{command_path}, + command_options => $command_options); + + my $p = XML::Parser->new(NoLWP => 1); + my $xp = XML::XPath->new(parser => $p, xml => $stdout); + + my $listHttpSampleNode = $xp->findnodes('/testResults/httpSample'); + + my $timing0 = 0; + my $timing1 = 0; + my $step = $listHttpSampleNode->get_nodelist; + my $stepOk = 0; + my $first_failed_label; + my $exit1 = 'OK'; + + foreach my $httpSampleNode ($listHttpSampleNode->get_nodelist) { + my $temp_exit = 'OK'; + + my $elapsed_time = $httpSampleNode->getAttribute('t'); + my $timestamp = $httpSampleNode->getAttribute('ts'); + my $success = $httpSampleNode->getAttribute('s'); + my $label = $httpSampleNode->getAttribute('lb'); + my $response_code = $httpSampleNode->getAttribute('rc'); + my $response_message = $httpSampleNode->getAttribute('rm'); + + $self->{output}->output_add(long_msg => "* Sample: " . $label); + $self->{output}->output_add(long_msg => " - Success: " . $success); + $self->{output}->output_add(long_msg => " - Elapsed Time: " . $elapsed_time / 1000 . "s"); + $self->{output}->output_add(long_msg => " - Response Code: " . $response_code); + $self->{output}->output_add(long_msg => " - Response Message: " . $response_message); + + if ($success ne 'true') { + $temp_exit = 'CRITICAL'; + } + + my $listAssertionResultNode = $xp->findnodes('./assertionResult', $httpSampleNode); + + foreach my $assertionResultNode ($listAssertionResultNode->get_nodelist) { + my $name = $xp->findvalue('./name', $assertionResultNode); + my $failure = $xp->findvalue('./failure', $assertionResultNode); + my $error = $xp->findvalue('./error', $assertionResultNode); + + $self->{output}->output_add(long_msg => " - Assertion: " . $name); + + if (($failure eq 'true') || ($error eq 'true')) { + my $failure_message = $xp->findvalue('./failureMessage', $assertionResultNode); + $self->{output}->output_add(long_msg => " + Failure Message: " . $failure_message); + + $temp_exit = 'CRITICAL'; + } + } + + if ($temp_exit eq 'OK') { + $stepOk++; + } else { + if (!defined($first_failed_label)) { + $first_failed_label = $label . " (" . $response_code . " " . $response_message . ")"; + } + + $exit1 = $self->{output}->get_most_critical(status => [ $exit1, $temp_exit ]); + } + + if ($timestamp > 0) { + if ($timing0 == 0) { + $timing0 = $timestamp; + } + + $timing1 = $timestamp + $elapsed_time; + } + } + + my $timeelapsed = ($timing1 - $timing0) / 1000; + my $availability = sprintf("%d", $stepOk * 100 / $step); + + my $exit2 = $self->{perfdata}->threshold_check(value => $timeelapsed, + threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); + my $exit = $self->{output}->get_most_critical(status => [ $exit1, $exit2 ]); + if (!defined($first_failed_label)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("%d/%d steps (%.3fs)", $stepOk, $step, $timeelapsed)); + } else { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("%d/%d steps (%.3fs) - %s", $stepOk, $step, $timeelapsed, $first_failed_label)); + } + $self->{output}->perfdata_add(label => "time", unit => 's', + value => sprintf('%.3f', $timeelapsed), + min => 0, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')); + $self->{output}->perfdata_add(label => "steps", + value => sprintf('%d', $stepOk), + min => 0, + max => $step); + $self->{output}->perfdata_add(label => "availability", unit => '%', + value => sprintf('%d', $availability), + min => 0, + max => 100); + + $self->{output}->display(); + $self->{output}->exit(); +} + +1; + +__END__ + +=head1 MODE + +Check scenario execution + +=over 8 + +=item B<--remote> + +Execute command remotely in 'ssh'. + +=item B<--hostname> + +Hostname to query (need --remote). + +=item B<--ssh-option> + +Specify multiple options like the user (example: --ssh-option='-l=centreon-engine' --ssh-option='-p=52'). + +=item B<--ssh-path> + +Specify ssh command path (default: none). + +=item B<--ssh-command> + +Specify ssh command (default: 'ssh'). Useful to use 'plink'. + +=item B<--sudo> + +Use 'sudo' to execute the command. + +=item B<--command> + +Command to get information (default: 'jmeter'). + +=item B<--command-path> + +Command path (default: none). + +=item B<--command-extra-options> + +Command extra options (default: none). + +=item B<--timeout> + +Timeout in seconds for the command (default: 50). + +=item B<--directory> + +Directory where scenarii are stored. + +=item B<--scenario> + +Scenario used by JMeter (without extension). + +=item B<--warning> + +Threshold warning in seconds (scenario execution time). + +=item B<--critical> + +Threshold critical in seconds (scenario execution time). + +=back + +=cut diff --git a/apps/jmeter/plugin.pm b/apps/jmeter/plugin.pm new file mode 100644 index 000000000..e92cf065b --- /dev/null +++ b/apps/jmeter/plugin.pm @@ -0,0 +1,48 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::jmeter::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_simple); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + %{$self->{modes}} = ( + 'scenario' => 'apps::jmeter::mode::scenario', + ); + + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check JMeter. + +=cut diff --git a/apps/protocols/modbus/mode/numericvalue.pm b/apps/protocols/modbus/mode/numericvalue.pm new file mode 100644 index 000000000..c8c50a5a7 --- /dev/null +++ b/apps/protocols/modbus/mode/numericvalue.pm @@ -0,0 +1,369 @@ +# +# Copyright 2016 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::protocols::modbus::mode::numericvalue; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use List::Util qw (min max sum); +use JSON; +my $config_data; + +sub custom_metric_output { + my ($self, %options) = @_; + my $msg; + my $message; + + if ($self->{result_values}->{type} eq 'unique') { + if (defined($config_data->{selection}->{$self->{result_values}->{instance}}->{formatting}->{printf_var}) && defined($config_data->{selection}->{$self->{result_values}->{instance}}->{formatting}->{printf_msg})) { + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + $msg = sprintf("$config_data->{selection}->{$self->{result_values}->{instance}}->{formatting}->{printf_msg}", + eval "$config_data->{selection}->{$self->{result_values}->{instance}}->{formatting}->{printf_var}"); + }; + } elsif (defined($config_data->{formatting}->{printf_var}) && defined($config_data->{formatting}->{printf_msg})) { + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + $msg = sprintf("$config_data->{formatting}->{printf_msg}", eval "$config_data->{formatting}->{printf_var}"); + }; + } else { + $msg = sprintf("Metric '%s' value is '%s'", $self->{result_values}->{instance}, $self->{result_values}->{value}); + } + } + + if ($self->{result_values}->{type} eq 'global') { + if (defined($config_data->{virtualcurve}->{$self->{result_values}->{instance}}->{formatting})) { + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + $msg = sprintf("$config_data->{virtualcurve}->{$self->{result_values}->{instance}}->{formatting}->{printf_msg}", + eval "$config_data->{virtualcurve}->{$self->{result_values}->{instance}}->{formatting}->{printf_var}"); + }; + } elsif (defined($config_data->{formatting}->{printf_var}) && defined($config_data->{formatting}->{printf_msg})) { + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + $msg = sprintf("$config_data->{formatting}->{printf_msg}", eval "$config_data->{formatting}->{printf_var}"); + }; + } else { + $msg = sprintf("Metric '%s' value is '%s'", $self->{result_values}->{instance}, $self->{result_values}->{value}); + } + } + + if (defined($message)) { + $self->{output}->output_add(long_msg => 'printf expression problem: ' . $message); + $self->{output}->option_exit(); + } + + return $msg; + +} + +sub custom_metric_calc { + my ($self, %options) = @_; + + $self->{result_values}->{value} = $options{new_datas}->{$self->{instance} . '_value'}; + $self->{result_values}->{unit} = $options{new_datas}->{$self->{instance} . '_unit'}; + $self->{result_values}->{instance} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_type'}; + $self->{result_values}->{perfdata_value} = $options{new_datas}->{$self->{instance} . '_value'}; + $self->{result_values}->{perfdata_unit} = $options{new_datas}->{$self->{instance} . '_unit'}; + $self->{result_values}->{min} = $options{new_datas}->{$self->{instance} . '_min'}; + $self->{result_values}->{max} = $options{new_datas}->{$self->{instance} . '_max'}; + + my $elem = $self->{result_values}->{type} eq 'unique' ? 'selection' : 'virtualcurve'; + my ($change_bytes_metric_selection); + if (defined($config_data->{$elem}->{$self->{result_values}->{instance}}->{formatting}) && + defined($config_data->{$elem}->{$self->{result_values}->{instance}}->{formatting}->{change_bytes})) { + $change_bytes_metric_selection = $config_data->{$elem}->{$self->{result_values}->{instance}}->{formatting}->{change_bytes}; + } + + if ((defined($change_bytes_metric_selection) && $change_bytes_metric_selection) || + ($config_data->{formatting}->{change_bytes} && !defined($change_bytes_metric_selection))) { + ($self->{result_values}->{value}, $self->{result_values}->{unit}) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value}); + } + return 0; +} + +sub custom_metric_perfdata { + my ($self, %options) = @_; + + $self->{output}->perfdata_add(label => $self->{result_values}->{instance}, + value => $self->{result_values}->{perfdata_value}, + warning => $self->{perfdata}->get_perfdata_for_output(label => ($self->{result_values}->{type} eq 'unique') ? 'warning-metric' : 'warning-global-'.$self->{result_values}->{instance}), + critical => $self->{perfdata}->get_perfdata_for_output(label => ($self->{result_values}->{type} eq 'unique') ? 'critical-metric' : 'critical-global-'.$self->{result_values}->{instance}), + unit => $self->{result_values}->{perfdata_unit}, + min => $self->{result_values}->{min}, + max => $self->{result_values}->{max}, + ); + +} + +sub custom_metric_threshold { + my ($self, %options) = @_; + + my $label_warn = ($self->{result_values}->{type} eq 'unique') ? 'warning-metric' : 'warning-global-'.$self->{result_values}->{instance}; + my $label_crit = ($self->{result_values}->{type} eq 'unique') ? 'critical-metric' : 'critical-global-'.$self->{result_values}->{instance}; + + my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{perfdata_value}, + threshold => [ { label => $label_crit, exit_litteral => 'critical' }, + { label => $label_warn, exit_litteral => 'warning' } ]); + return $exit; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = []; + + $self->{maps_counters}->{global} = [ + { label => 'global', set => { + key_values => [ { name => 'value' }, { name => 'display' }, { name => 'type' }, { name => 'unit' }, { name => 'min' }, { name => 'max' } ], + closure_custom_calc => $self->can('custom_metric_calc'), + closure_custom_output => $self->can('custom_metric_output'), + closure_custom_perfdata => $self->can('custom_metric_perfdata'), + closure_custom_threshold_check => $self->can('custom_metric_threshold'), + } + } + ]; + + $self->{maps_counters}->{metric} = [ + { label => 'metric', set => { + key_values => [ { name => 'value' }, { name => 'display' }, { name => 'type' }, { name => 'unit' }, { name => 'min' }, { name => 'max' } ], + closure_custom_calc => $self->can('custom_metric_calc'), + closure_custom_output => $self->can('custom_metric_output'), + closure_custom_perfdata => $self->can('custom_metric_perfdata'), + closure_custom_threshold_check => $self->can('custom_metric_threshold'), + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "config:s" => { name => 'config' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + if (!defined($self->{option_results}->{config}) || $self->{option_results}->{config} eq '') { + $self->{output}->add_option_msg(short_msg => "Please define --config option"); + $self->{output}->option_exit(); + } + + $config_data = $self->parse_json_config(config => $self->{option_results}->{config}); + + if (!defined($config_data->{selection})) { + $self->{output}->add_option_msg(short_msg => "Config_error: there is no selection section in your JSON configuration !"); + $self->{output}->option_exit(); + } + + $config_data->{formatting}->{printf_msg} = "Metric '%s' value is %d" if (!exists($config_data->{formatting}->{printf_msg})); + $config_data->{formatting}->{printf_metric_value} = "%d" if (!exists($config_data->{formatting}->{printf_metric_value})); + $config_data->{formatting}->{custom_message_global} = "Global metrics are OK" if (!exists($config_data->{formatting}->{custom_message_global})); + $config_data->{formatting}->{custom_message_metric} = "All metrics are OK" if (!exists($config_data->{formatting}->{custom_message_metric})); + $config_data->{formatting}->{cannonical_separator} = "#" if (!exists($config_data->{formatting}->{cannonical_separator})); + $config_data->{formatting}->{change_bytes} = 0 if (!exists($config_data->{formatting}->{change_bytes})); +} + +sub parse_json_config { + my ($self, %options) = @_; + my ($data, $json_text); + + if (-f $options{config} and -r $options{config}) { + $json_text = do { + local $/; + my $fh; + if (!open($fh, "<:encoding(UTF-8)", $options{config})) { + $self->{output}->add_option_msg(short_msg => "Can't open file $options{config}: $!"); + $self->{output}->option_exit(); + } + <$fh>; + }; + } else { + $json_text = $options{config}; + } + + eval { + $data = decode_json($json_text); + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => "Cannot decode json config file: $@"); + $self->{output}->option_exit(); + } + return $data +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{metrics} = {}; + $self->{vmetrics} = {}; + $self->{metric} = {}; + $self->{global} = {}; + + if (defined($config_data->{virtualcurve})) { + push @{$self->{maps_counters_type}}, { + name => 'global', type => 1, message_separator => $config_data->{formatting}->{message_separator}, message_multiple => $config_data->{formatting}->{custom_message_global}, + }; + } + + if (defined($config_data->{selection})) { + my $pushed = 0; + foreach my $id (keys %{$config_data->{selection}}) { + next if (!defined($config_data->{selection}->{$id}->{address})); + my $results = $options{custom}->read_objects(address => $config_data->{selection}->{$id}->{address}, + unit => $config_data->{selection}->{$id}->{unit}, quantity => $config_data->{selection}->{$id}->{quantity}, + type => $config_data->{selection}->{$id}->{type}); + my $i = 0; + my $extra_num = 0; + if (scalar(@$results) > 1) { + $extra_num = 1; + } + foreach (@{$results}) { + my $metric_key = $id; + $metric_key .= '.' . $i if ($extra_num == 1); + $self->{metrics}->{$metric_key} = { name => $metric_key }; + $self->{metrics}->{$metric_key}->{display_name} = $metric_key; + $self->{metrics}->{$metric_key}->{current} = $_; + $self->{metrics}->{$metric_key}->{unit} = defined($config_data->{selection}->{$id}->{unit_name}) ? $config_data->{selection}->{$id}->{unit_name} : ''; + $self->{metrics}->{$metric_key}->{min} = defined($config_data->{selection}->{$id}->{min}) ? $config_data->{selection}->{$id}->{min} : ''; + $self->{metrics}->{$metric_key}->{max} = defined($config_data->{selection}->{$id}->{max}) ? $config_data->{selection}->{$id}->{max} : ''; + $self->{metrics}->{$metric_key}->{display} = (defined($config_data->{selection}->{$id}->{display}) && $config_data->{selection}->{$id}->{display}) ? 1 : 0; + $i++; + + + if ($self->{metrics}->{$metric_key}->{display} == 1) { + $self->{metric}->{$metric_key} = { + display => $self->{metrics}->{$metric_key}->{display_name}, + type => 'unique', + unit => $self->{metrics}->{$metric_key}->{unit}, + value => $self->{metrics}->{$metric_key}->{current}, + min => $self->{metrics}->{$metric_key}->{min}, + max => $self->{metrics}->{$metric_key}->{max} }; + push @{$self->{maps_counters_type}}, { + name => 'metric', type => 1, message_separator => $config_data->{formatting}->{message_separator}, message_multiple => $config_data->{formatting}->{custom_message_metric}, + } if ($pushed == 0); + $pushed = 1; + } + } + } + } + + foreach my $vcurve (keys %{$config_data->{virtualcurve}}) { + foreach my $metric (keys %{$self->{metrics}}) { + $self->{vmetrics}->{$vcurve}->{values} = [] if (!defined($self->{vmetrics}->{$vcurve})); + if (defined($config_data->{virtualcurve}->{$vcurve}->{pattern}) && $config_data->{virtualcurve}->{$vcurve}->{pattern} ne '') { + push (@{$self->{vmetrics}->{$vcurve}->{values}}, $self->{metrics}->{$metric}->{current}) if ($self->{metrics}->{$metric}->{name} =~ /$config_data->{virtualcurve}{$vcurve}->{pattern}/); + } else { + push (@{$self->{vmetrics}->{$vcurve}->{values}}, $self->{metrics}->{$metric}->{current}); + } + } + + next if (!defined($self->{vmetrics}->{$vcurve}->{values}) || scalar(@{$self->{vmetrics}->{$vcurve}->{values}}) == 0); + + $self->{vmetrics}->{$vcurve}->{aggregated_value} = sprintf($config_data->{formatting}->{printf_metric_value}, + sum(@{$self->{vmetrics}->{$vcurve}->{values}}) / scalar(@{$self->{vmetrics}->{$vcurve}->{values}})) if ($config_data->{virtualcurve}->{$vcurve}->{aggregation} eq 'avg'); + $self->{vmetrics}->{$vcurve}->{aggregated_value} = sprintf($config_data->{formatting}->{printf_metric_value}, + sum(@{$self->{vmetrics}->{$vcurve}->{values}})) if ($config_data->{virtualcurve}->{$vcurve}->{aggregation} eq 'sum'); + $self->{vmetrics}->{$vcurve}->{aggregated_value} = sprintf($config_data->{formatting}->{printf_metric_value}, + min(@{$self->{vmetrics}->{$vcurve}->{values}})) if ($config_data->{virtualcurve}->{$vcurve}->{aggregation} eq 'min'); + $self->{vmetrics}->{$vcurve}->{aggregated_value} = sprintf($config_data->{formatting}->{printf_metric_value}, + max(@{$self->{vmetrics}->{$vcurve}->{values}})) if ($config_data->{virtualcurve}->{$vcurve}->{aggregation} eq 'max'); + $self->{vmetrics}->{$vcurve}->{aggregated_value} = eval "$self->{vmetrics}->{$vcurve}->{aggregated_value} $config_data->{virtualcurve}->{$vcurve}->{custom}" if (defined($config_data->{virtualcurve}->{$vcurve}->{custom})); + + $self->{vmetrics}->{$vcurve}->{unit} = (defined($config_data->{virtualcurve}->{$vcurve}->{unit})) ? $config_data->{virtualcurve}->{$vcurve}->{unit} : ''; + $self->{vmetrics}->{$vcurve}->{min} = (defined($config_data->{virtualcurve}->{$vcurve}->{min})) ? $config_data->{virtualcurve}->{$vcurve}->{min} : ''; + $self->{vmetrics}->{$vcurve}->{max} = (defined($config_data->{virtualcurve}->{$vcurve}->{max})) ? $config_data->{virtualcurve}->{$vcurve}->{max} : ''; + + if (defined($self->{option_results}->{'warning-global'}) || defined($config_data->{virtualcurve}->{$vcurve}->{warning})) { + $self->{perfdata}->threshold_validate(label => 'warning-global-' . $vcurve, + value => (defined($self->{option_results}->{'warning-global'})) ? $self->{option_results}->{'warning-global'} : $config_data->{virtualcurve}->{$vcurve}->{warning}); + } + if (defined($self->{option_results}->{'critical-global'}) || defined($config_data->{virtualcurve}->{$vcurve}->{critical})) { + $self->{perfdata}->threshold_validate(label => 'critical-global-' . $vcurve, + value => (defined($self->{option_results}->{'critical-global'})) ? $self->{option_results}->{'critical-global'} : $config_data->{virtualcurve}->{$vcurve}->{critical}); + } + + $self->{global}->{$vcurve} = { + display => $vcurve, + type => 'global', + unit => $self->{vmetrics}->{$vcurve}->{unit}, + value => $self->{vmetrics}->{$vcurve}->{aggregated_value}, + min => $self->{vmetrics}->{$vcurve}->{min}, + max => $self->{vmetrics}->{$vcurve}->{max} + }; + } + + if (scalar(keys %{$self->{metric}}) <= 0 && scalar(keys %{$self->{global}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No metrics returned - are your selection correct ?"); + $self->{output}->option_exit(); + } +} + +1 + +__END__ + +=head1 MODE + +Mode to play with modbus metrics +e.g: display two curves of different service on the same graph +e.g: aggregate multiple metrics (min,max,avg,sum) or custom operation + +=over 8 + +=item B<--config> + +Specify the config (can be a file or a json string directly). + +=item B<--filter-counters> + +Filter some counter (can be 'unique' or 'global') +Useless, if you use selection/filter but not +global/virtual curves + +=item B<--warning-*> + +Warning threshold (can be 'unique' or 'global') +(Override config if set) + +=item B<--critical-*> + +Critical threshold (can be 'unique' or 'global') +(Override config if set) + +=back + +=cut diff --git a/apps/protocols/modbus/plugin.pm b/apps/protocols/modbus/plugin.pm new file mode 100644 index 000000000..cfd0c49ee --- /dev/null +++ b/apps/protocols/modbus/plugin.pm @@ -0,0 +1,49 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::protocols::modbus::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_custom); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '0.1'; + %{$self->{modes}} = ( + 'numeric-value' => 'apps::protocols::modbus::mode::numericvalue', + ); + + $self->{custom_modes}{api} = 'centreon::common::protocols::modbus::custom::api'; + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Generic Modbus plugin. + +=cut diff --git a/centreon/common/powershell/hyperv/2012/nodeintegrationservice.pm b/centreon/common/powershell/hyperv/2012/nodeintegrationservice.pm index e6fcaf461..e165bef1c 100644 --- a/centreon/common/powershell/hyperv/2012/nodeintegrationservice.pm +++ b/centreon/common/powershell/hyperv/2012/nodeintegrationservice.pm @@ -40,7 +40,9 @@ Try { $vms = Get-VM Foreach ($vm in $vms) { - Write-Host "[name=" $vm.VMName "][state=" $vm.State "][IntegrationServicesState=" $vm.IntegrationServicesState "][IntegrationServicesVersion=" $vm.IntegrationServicesVersion "]" + $note = $vm.Notes -replace "\r","" + $note = $note -replace "\n"," - " + Write-Host "[name=" $vm.VMName "][state=" $vm.State "][IntegrationServicesState=" $vm.IntegrationServicesState "][IntegrationServicesVersion=" $vm.IntegrationServicesVersion "][note=" $note "]" Foreach ($service in $VM.VMIntegrationService) { Write-Host "[service=" $service.Name "][enabled=" $service.Enabled "][primaryOperationalStatus=" $service.PrimaryOperationalStatus "][secondaryOperationalStatus=" $service.SecondaryOperationalStatus "]" } diff --git a/centreon/common/powershell/hyperv/2012/nodesnapshot.pm b/centreon/common/powershell/hyperv/2012/nodesnapshot.pm index 805d4a77a..0134855fe 100644 --- a/centreon/common/powershell/hyperv/2012/nodesnapshot.pm +++ b/centreon/common/powershell/hyperv/2012/nodesnapshot.pm @@ -44,15 +44,31 @@ Try { Foreach ($vm in $vms) { $i=0 + $note = $vm.Notes -replace "\r","" + $note = $note -replace "\n"," - " Foreach ($snap in $snapshots) { if ($snap.VMName -eq $vm.VMName) { if ($i -eq 0) { - Write-Host "[name=" $vm.VMName "][state=" $vm.State "]" + Write-Host "[name=" $vm.VMName "][state=" $vm.State "][note=" $note "]" } - Write-Host "[checkpointCreationTime=" (get-date -date $snap.CreationTime -UFormat ' . "'%s'" . ') "]" + Write-Host "[checkpointCreationTime=" (get-date -date $snap.CreationTime.ToUniversalTime() -UFormat ' . "'%s'" . ') "]" $i=1 } } + if ($vm.status -imatch "Backing") { + $VMDisks = Get-VMHardDiskDrive -VMName $vm.VMName + Foreach ($VMDisk in $VMDisks) { + $VHD = Get-VHD $VMDisk.Path + if ($VHD.Path -imatch ".avhdx" -or $VHD.VhdType -imatch "Differencing") { + $parent = Get-Item $VHD.ParentPath + if ($i -eq 0) { + Write-Host "[name=" $vm.VMName "][state=" $vm.State "][note=" $note "]" + } + Write-Host "[checkpointCreationTime=" (get-date -date $parent.LastWriteTime.ToUniversalTime() -UFormat ' . "'%s'" . ') "]" + $i=1 + } + } + } } } Catch { Write-Host $Error[0].Exception diff --git a/centreon/common/powershell/hyperv/2012/nodevmstatus.pm b/centreon/common/powershell/hyperv/2012/nodevmstatus.pm index 7c0c39abc..23ac2ced5 100644 --- a/centreon/common/powershell/hyperv/2012/nodevmstatus.pm +++ b/centreon/common/powershell/hyperv/2012/nodevmstatus.pm @@ -40,7 +40,9 @@ Try { $vms = Get-VM Foreach ($vm in $vms) { - Write-Host "[name=" $vm.VMName "][state=" $vm.State "][status=" $vm.Status "][IsClustered=" $vm.IsClustered "]" + $note = $vm.Notes -replace "\r","" + $note = $note -replace "\n"," - " + Write-Host "[name=" $vm.VMName "][state=" $vm.State "][status=" $vm.Status "][IsClustered=" $vm.IsClustered "][note=" $note "]" } } Catch { Write-Host $Error[0].Exception diff --git a/centreon/common/powershell/hyperv/2012/scvmmsnapshot.pm b/centreon/common/powershell/hyperv/2012/scvmmsnapshot.pm index be9017857..07fe8305b 100644 --- a/centreon/common/powershell/hyperv/2012/scvmmsnapshot.pm +++ b/centreon/common/powershell/hyperv/2012/scvmmsnapshot.pm @@ -49,11 +49,13 @@ Try { Foreach ($vm in $vms) { $i = 0 $checkpoints = Get-SCVMCheckpoint -VMMServer $connection -Vm $vm + $desc = $vm.description -replace "\r","" + $desc = $desc -replace "\n"," - " foreach ($checkpoint in $checkpoints) { if ($i -eq 0) { - Write-Host "[name=" $vm.Name "][status=" $vm.Status "][cloud=" $vm.Cloud "][hostgrouppath=" $vm.HostGroupPath "]" + Write-Host "[name=" $vm.Name "][description=" $desc "][status=" $vm.Status "][cloud=" $vm.Cloud "][hostgrouppath=" $vm.HostGroupPath "]" } - Write-Host "[checkpointAddedTime=" (get-date -date $checkpoint.AddedTime -UFormat ' . "'%s'" . ') "]" + Write-Host "[checkpointAddedTime=" (get-date -date $checkpoint.AddedTime.ToUniversalTime() -UFormat ' . "'%s'" . ') "]" $i = 1 } } diff --git a/centreon/common/powershell/hyperv/2012/scvmmvmstatus.pm b/centreon/common/powershell/hyperv/2012/scvmmvmstatus.pm index be9ec4c6a..fb1cb74ff 100644 --- a/centreon/common/powershell/hyperv/2012/scvmmvmstatus.pm +++ b/centreon/common/powershell/hyperv/2012/scvmmvmstatus.pm @@ -47,7 +47,9 @@ Try { $vms = Get-SCVirtualMachine -VMMServer $connection Foreach ($vm in $vms) { - Write-Host "[name=" $vm.Name "][status=" $vm.Status "][cloud=" $vm.Cloud "][hostgrouppath=" $vm.HostGroupPath "]" + $desc = $vm.description -replace "\r","" + $desc = $desc -replace "\n"," - " + Write-Host "[name=" $vm.Name "][description=" $desc "][status=" $vm.Status "][cloud=" $vm.Cloud "][hostgrouppath=" $vm.HostGroupPath "]" } } Catch { Write-Host $Error[0].Exception diff --git a/centreon/common/protocols/modbus/custom/api.pm b/centreon/common/protocols/modbus/custom/api.pm new file mode 100644 index 000000000..2f73624b5 --- /dev/null +++ b/centreon/common/protocols/modbus/custom/api.pm @@ -0,0 +1,234 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package centreon::common::protocols::modbus::custom::api; + +use strict; +use warnings; +use centreon::plugins::misc; + +sub new { + my ($class, %options) = @_; + my $self = {}; + bless $self, $class; + + if (!defined($options{output})) { + print "Class Custom: Need to specify 'output' argument.\n"; + exit 3; + } + if (!defined($options{options})) { + $options{output}->add_option_msg(short_msg => "Class Custom: Need to specify 'options' argument."); + $options{output}->option_exit(); + } + + if (!defined($options{noptions})) { + $options{options}->add_options(arguments => + { + "rtu-port:s@" => { name => 'rtu_port' }, + "rtu-baudrate:s@" => { name => 'rtu_baudrate' }, + "rtu-databits:s@" => { name => 'rtu_databits' }, + "rtu-parity:s@" => { name => 'rtu_parity' }, + "rtu-stopbits:s@" => { name => 'rtu_stopbits' }, + "tcp-host:s@" => { name => 'tcp_host' }, + "tcp-port:s@" => { name => 'tcp_port' }, + "timeout:s@" => { name => 'timeout' }, + }); + } + $options{options}->add_help(package => __PACKAGE__, sections => 'MODBUS OPTIONS', once => 1); + + $self->{output} = $options{output}; + $self->{mode} = $options{mode}; + + return $self; +} + +sub set_options { + my ($self, %options) = @_; + + $self->{option_results} = $options{option_results}; + # We remove empty rtu_port and tcp_host + foreach my $label ('rtu_port', 'tcp_host') { + if (defined($self->{option_results}->{$label})) { + my @del_indexes = reverse(grep { $self->{option_results}->{$label}->[$_] eq '' } 0..$#{$self->{option_results}->{$label}}); + foreach my $item (@del_indexes) { + splice (@{$self->{option_results}->{$label}}, $item, 1); + } + } + } +} + +sub set_defaults { + my ($self, %options) = @_; + + foreach (keys %{$options{default}}) { + if ($_ eq $self->{mode}) { + for (my $i = 0; $i < scalar(@{$options{default}->{$_}}); $i++) { + foreach my $opt (keys %{$options{default}->{$_}[$i]}) { + if (!defined($self->{option_results}->{$opt}[$i])) { + $self->{option_results}->{$opt}[$i] = $options{default}->{$_}[$i]->{$opt}; + } + } + } + } + } +} + +sub check_options { + my ($self, %options) = @_; + + $self->{modbus_type} = 1; + $self->{modbus_params} = { rtu => {} , tcp => {} }; + my $timeout = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; + + if (defined($self->{option_results}->{rtu_port}->[0])) { + $self->{modbus_type} = 2; + $self->{modbus_params}->{rtu}->{port} = shift(@{$self->{option_results}->{rtu_port}}); + $self->{modbus_params}->{rtu}->{baudrate} = (defined($self->{option_results}->{rtu_baudrate})) ? shift(@{$self->{option_results}->{rtu_baudrate}}) : 9600; + $self->{modbus_params}->{rtu}->{databits} = (defined($self->{option_results}->{rtu_databits})) ? shift(@{$self->{option_results}->{rtu_databits}}) : 8; + $self->{modbus_params}->{rtu}->{parity} = (defined($self->{option_results}->{rtu_parity})) ? shift(@{$self->{option_results}->{rtu_parity}}) : 'none'; + $self->{modbus_params}->{rtu}->{stopbits} = (defined($self->{option_results}->{rtu_stopbits})) ? shift(@{$self->{option_results}->{rtu_stopbits}}) : 1; + $self->{modbus_params}->{rtu}->{timeout} = $timeout; + } elsif (defined($self->{option_results}->{tcp_host}->[0])) { + $self->{modbus_params}->{tcp}->{host} = shift(@{$self->{option_results}->{tcp_host}}); + $self->{modbus_params}->{tcp}->{port} = (defined($self->{option_results}->{tcp_port})) ? shift(@{$self->{option_results}->{tcp_port}}) : 502; + $self->{modbus_params}->{tcp}->{timeout} = $timeout; + } else { + $self->{output}->add_option_msg(short_msg => "Need to specify --rtu-port or --tcp-host option."); + $self->{output}->option_exit(); + } + + if ((!defined($self->{modbus_params}->{rtu}->{port}) || scalar(@{$self->{option_results}->{rtu_port}}) == 0) && + (!defined($self->{modbus_params}->{tcp}->{host}) || scalar(@{$self->{option_results}->{tcp_host}}) == 0)) { + return 0; + } + return 1; +} + +sub connect { + my ($self, %options) = @_; + + if ($self->{modbus_type} == 1) { + centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'Device::Modbus::TCP::Client', + error_msg => "Cannot load module 'Device::Modbus::TCP::Client'."); + $self->{modbus_client} = Device::Modbus::TCP::Client->new(%{$self->{modbus_params}->{tcp}}); + } else { + centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'Device::Modbus::RTU::Client', + error_msg => "Cannot load module 'Device::Modbus::RTU::Client'."); + $self->{modbus_client} = Device::Modbus::RTU::Client->new(%{$self->{modbus_params}->{rtu}}); + } +} + +my %mapping_methods = ( + holding => 'read_holding_registers', + coils => 'read_coils', + discrete => 'read_discrete_inputs', + input => 'read_input_registers', +); + +sub read_objects { + my ($self, %options) = @_; + my $unit = defined($options{unit}) ? $options{unit} : 1; + my $type = defined($options{type}) ? $options{type} : 'holding'; + my $quantity = defined($options{quantity}) ? $options{quantity} : 1; + my $results = []; + + if (!defined($self->{modbus_client})) { + $self->connect(); + } + + my $method = $self->{modbus_client}->can($mapping_methods{$type}); + if ($method) { + my $req = $self->{modbus_client}->$method(unit => $unit, address => $options{address}, quantity => $quantity); + if (!$self->{modbus_client}->send_request($req)) { + $self->{output}->add_option_msg(short_msg => "Modbus Request: send error $!"); + $self->{output}->option_exit(); + } + my $response = $self->{modbus_client}->receive_response; + if ($response->success()) { + $results = $response->values(); + } else { + $self->{output}->add_option_msg(short_msg => "Modbus Request: error " . $response->message()->stringify()); + $self->{output}->option_exit(); + } + } + + if (scalar(@{$results}) == 0) { + $self->{output}->add_option_msg(short_msg => "Modbus Request: Cant get a single value."); + $self->{output}->option_exit(); + } + return $results; +} + +1; + +__END__ + +=head1 NAME + +Modbus connector library + +=head1 SYNOPSIS + +my modbus connector + +=head1 MODBUS OPTIONS + +=over 8 + +=item B<--rtu-port> + +The serial port to open. +Example: --rtu-port=/dev/ttyUSB0 + +=item B<--rtu-baudrate> + +A valid baud rate (Default: 9600) + +=item B<--rtu-databits> + +An integer from 5 to 8 (Default: 8) + +=item B<--rtu-parity> + +Either 'even', 'odd' or 'none' (Default: none) + +=item B<--rtu-stopbits> + +1 or 2 (Default: 1) + +=item B<--tcp-host> + +Host address + +=item B<--tcp-port> + +Host port (Default: 502) + +=item B<--timeout> + +Timeout in seconds (Default: 10) + +=back + +=head1 DESCRIPTION + +B. + +=cut \ No newline at end of file diff --git a/centreon/plugins/script.pm b/centreon/plugins/script.pm index 3ddd9f9e8..e5f3ead05 100644 --- a/centreon/plugins/script.pm +++ b/centreon/plugins/script.pm @@ -78,6 +78,10 @@ sub handle_DIE { $self->{output}->die_exit(); } +sub get_global_version { + return $global_version; +} + sub get_plugin { my ($self) = @_; @@ -129,7 +133,7 @@ sub convert_args { if ($self->{convert_args} =~ /^(.+?),(.*)/) { my ($search, $replace) = ($1, $2); for (my $i = 0; $i < $#ARGV; $i++) { - $ARGV[$i] =~ s/$search/$replace/g; + eval "\$ARGV[\$i] =~ s/$search/$replace/g"; } } } @@ -402,7 +406,7 @@ Set environment variables for the script (prefer to set it before running it for =item B<--convert-args> Change strings of arguments. Useful to use '!' in nrpe protocol. -Example: --convert-args='##,!' +Example: --convert-args='##,\x21' =back diff --git a/cloud/nutanix/snmp/mode/clusterusage.pm b/cloud/nutanix/snmp/mode/clusterusage.pm new file mode 100644 index 000000000..ca3156227 --- /dev/null +++ b/cloud/nutanix/snmp/mode/clusterusage.pm @@ -0,0 +1,290 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::clusterusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $instance_mode; +my $cluster_name = ''; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = 'status : ' . $self->{result_values}->{status}; + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_clusterStatus'}; + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + return 0; +} + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $label = 'used'; + my $value_perf = $self->{result_values}->{used}; + if (defined($instance_mode->{option_results}->{free})) { + $label = 'free'; + $value_perf = $self->{result_values}->{free}; + } + my %total_options = (); + if ($instance_mode->{option_results}->{units} eq '%') { + $total_options{total} = $self->{result_values}->{total}; + $total_options{cast_int} = 1; + } + + $self->{output}->perfdata_add(label => $label, unit => 'B', + value => $value_perf, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_usage_threshold { + my ($self, %options) = @_; + + my ($exit, $threshold_value); + $threshold_value = $self->{result_values}->{used}; + $threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free})); + if ($instance_mode->{option_results}->{units} eq '%') { + $threshold_value = $self->{result_values}->{prct_used}; + $threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free})); + } + $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + my $msg = sprintf("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}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_clusterTotalStorageCapacity'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_clusterUsedStorageCapacity'}; + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'cluster', type => 0, cb_prefix_output => 'prefix_cluster_output', skipped_code => { -10 => 1 } }, + ]; + + $self->{maps_counters}->{cluster} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'clusterStatus' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + { label => 'usage', set => { + key_values => [ { name => 'clusterTotalStorageCapacity' }, { name => 'clusterUsedStorageCapacity' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + { label => 'avg-latency', set => { + key_values => [ { name => 'clusterLatency' } ], + output_template => 'Average Latency : %s µs', + perfdatas => [ + { label => 'avg_latency', value => 'clusterLatency_absolute', template => '%s', unit => 'µs', + min => 0 }, + ], + } + }, + { label => 'iops', set => { + key_values => [ { name => 'clusterIops' } ], + output_template => 'IOPs : %s', + perfdatas => [ + { label => 'iops', value => 'clusterIops_absolute', template => '%s', unit => 'iops', + min => 0 }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "warning-status:s" => { name => 'warning_status', default => '' }, + "critical-status:s" => { name => 'critical_status', default => '' }, + "units:s" => { name => 'units', default => '%' }, + "free" => { name => 'free' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub prefix_cluster_output { + my ($self, %options) = @_; + + return "Cluster '" . $cluster_name . "' "; +} + +my $mapping = { + clusterName => { oid => '.1.3.6.1.4.1.41263.501' }, + clusterStatus => { oid => '.1.3.6.1.4.1.41263.503' }, + clusterTotalStorageCapacity => { oid => '.1.3.6.1.4.1.41263.504' }, + clusterUsedStorageCapacity => { oid => '.1.3.6.1.4.1.41263.505' }, + clusterIops => { oid => '.1.3.6.1.4.1.41263.506' }, + clusterLatency => { oid => '.1.3.6.1.4.1.41263.507' }, +}; +my $oid_nutanix = '.1.3.6.1.4.1.41263'; + +sub manage_selection { + my ($self, %options) = @_; + + if ($options{snmp}->is_snmpv1()) { + $self->{output}->add_option_msg(short_msg => "Need to use SNMP v2c or v3."); + $self->{output}->option_exit(); + } + + my $snmp_result = $options{snmp}->get_table(oid => $oid_nutanix, + start => $mapping->{clusterName}->{oid}, end => $mapping->{clusterLatency}->{oid}, + nothing_quit => 1); + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => '0'); + $self->{cluster} = { %$result }; + $cluster_name = centreon::plugins::misc::trim($result->{clusterName}); +} + +1; + +__END__ + +=head1 MODE + +Check cluster usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^usage$' + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{status}, %{display} + +=item B<--critical-status> + +Set critical threshold for status. +Can used special variables like: %{status}, %{display} + +=item B<--warning-*> + +Threshold warning. +Can be: 'usage', 'avg-latency', 'iops'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'usage', 'avg-latency', 'iops'. + +=item B<--units> + +Units of thresholds (Default: '%') ('%', 'B'). + +=item B<--free> + +Thresholds are on free space left. + +=back + +=cut diff --git a/cloud/nutanix/snmp/mode/containerusage.pm b/cloud/nutanix/snmp/mode/containerusage.pm new file mode 100644 index 000000000..0d1a30917 --- /dev/null +++ b/cloud/nutanix/snmp/mode/containerusage.pm @@ -0,0 +1,245 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::containerusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $instance_mode; + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $label = 'used'; + my $value_perf = $self->{result_values}->{used}; + if (defined($instance_mode->{option_results}->{free})) { + $label = 'free'; + $value_perf = $self->{result_values}->{free}; + } + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + my %total_options = (); + if ($instance_mode->{option_results}->{units} eq '%') { + $total_options{total} = $self->{result_values}->{total}; + $total_options{cast_int} = 1; + } + + $self->{output}->perfdata_add(label => $label . $extra_label, unit => 'B', + value => $value_perf, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_usage_threshold { + my ($self, %options) = @_; + + my ($exit, $threshold_value); + $threshold_value = $self->{result_values}->{used}; + $threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free})); + if ($instance_mode->{option_results}->{units} eq '%') { + $threshold_value = $self->{result_values}->{prct_used}; + $threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free})); + } + $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + my $msg = sprintf("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}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_citTotalCapacity'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_citUsedCapacity'}; + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'container', type => 1, cb_prefix_output => 'prefix_container_output', message_multiple => 'All containers are ok', skipped_code => { -10 => 1 } }, + ]; + + $self->{maps_counters}->{container} = [ + { label => 'usage', set => { + key_values => [ { name => 'display' }, { name => 'citUsedCapacity' }, { name => 'citTotalCapacity' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + { label => 'avg-latency', set => { + key_values => [ { name => 'citAvgLatencyUsecs' }, { name => 'display' } ], + output_template => 'Average Latency : %s µs', + perfdatas => [ + { label => 'avg_latency', value => 'citAvgLatencyUsecs_absolute', template => '%s', unit => 'µs', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'iops', set => { + key_values => [ { name => 'citIOPerSecond' }, { name => 'display' } ], + output_template => 'IOPs : %s', + perfdatas => [ + { label => 'iops', value => 'citIOPerSecond_absolute', template => '%s', unit => 'iops', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "units:s" => { name => 'units', default => '%' }, + "free" => { name => 'free' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +sub prefix_container_output { + my ($self, %options) = @_; + + return "Container '" . $options{instance_value}->{display} . "' "; +} + +my $mapping = { + citContainerName => { oid => '.1.3.6.1.4.1.41263.8.1.3' }, + citTotalCapacity => { oid => '.1.3.6.1.4.1.41263.8.1.4' }, + citUsedCapacity => { oid => '.1.3.6.1.4.1.41263.8.1.5' }, + citIOPerSecond => { oid => '.1.3.6.1.4.1.41263.8.1.6' }, + citAvgLatencyUsecs => { oid => '.1.3.6.1.4.1.41263.8.1.7' }, +}; + +my $oid_citEntry = '.1.3.6.1.4.1.41263.8.1'; + +sub manage_selection { + my ($self, %options) = @_; + + if ($options{snmp}->is_snmpv1()) { + $self->{output}->add_option_msg(short_msg => "Need to use SNMP v2c or v3."); + $self->{output}->option_exit(); + } + + $self->{container} = {}; + my $snmp_result = $options{snmp}->get_table(oid => $oid_citEntry, + nothing_quit => 1); + + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{citContainerName}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + $result->{citContainerName} = centreon::plugins::misc::trim($result->{citContainerName}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{citContainerName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{citContainerName} . "': no matching filter.", debug => 1); + next; + } + + $self->{container}->{$instance} = { display => $result->{citContainerName}, + %$result, + }; + } + + if (scalar(keys %{$self->{container}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No container found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check container usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^usage$' + +=item B<--filter-name> + +Filter container name (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'usage', 'avg-latency', 'iops'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'usage', 'avg-latency', 'iops'. + +=item B<--units> + +Units of thresholds (Default: '%') ('%', 'B'). + +=item B<--free> + +Thresholds are on free space left. + +=back + +=cut diff --git a/cloud/nutanix/snmp/mode/diskusage.pm b/cloud/nutanix/snmp/mode/diskusage.pm new file mode 100644 index 000000000..bbbea260e --- /dev/null +++ b/cloud/nutanix/snmp/mode/diskusage.pm @@ -0,0 +1,331 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::diskusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = 'state : ' . $self->{result_values}->{state}; + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_dstState'}; + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + return 0; +} + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $label = 'used'; + my $value_perf = $self->{result_values}->{used}; + if (defined($instance_mode->{option_results}->{free})) { + $label = 'free'; + $value_perf = $self->{result_values}->{free}; + } + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + my %total_options = (); + if ($instance_mode->{option_results}->{units} eq '%') { + $total_options{total} = $self->{result_values}->{total}; + $total_options{cast_int} = 1; + } + + $self->{output}->perfdata_add(label => $label . $extra_label, unit => 'B', + value => $value_perf, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_usage_threshold { + my ($self, %options) = @_; + + my ($exit, $threshold_value); + $threshold_value = $self->{result_values}->{used}; + $threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free})); + if ($instance_mode->{option_results}->{units} eq '%') { + $threshold_value = $self->{result_values}->{prct_used}; + $threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free})); + } + $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + my $msg = sprintf("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}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_dstNumTotalBytes'}; + $self->{result_values}->{free} = $options{new_datas}->{$self->{instance} . '_dstNumFreeBytes'}; + $self->{result_values}->{used} = $self->{result_values}->{total} - $self->{result_values}->{free}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'disk', type => 1, cb_prefix_output => 'prefix_disk_output', message_multiple => 'All disks are ok', skipped_code => { -10 => 1 } }, + ]; + + $self->{maps_counters}->{disk} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'dstState' }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + { label => 'usage', set => { + key_values => [ { name => 'display' }, { name => 'dstNumFreeBytes' }, { name => 'dstNumTotalBytes' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + { label => 'inodes', set => { + key_values => [ { name => 'inodes_used' }, { name => 'display' } ], + output_template => 'Inodes Used : %s %%', + perfdatas => [ + { label => 'inodes', value => 'inodes_used_absolute', template => '%s', unit => '%', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'avg-latency', set => { + key_values => [ { name => 'dstAverageLatency' }, { name => 'display' } ], + output_template => 'Average Latency : %s µs', + perfdatas => [ + { label => 'avg_latency', value => 'dstAverageLatency_absolute', template => '%s', unit => 'µs', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'iops', set => { + key_values => [ { name => 'dstNumberIops' }, { name => 'display' } ], + output_template => 'IOPs : %s', + perfdatas => [ + { label => 'iops', value => 'dstNumberIops_absolute', template => '%s', unit => 'iops', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "warning-status:s" => { name => 'warning_status', default => '' }, + "critical-status:s" => { name => 'critical_status', default => '' }, + "units:s" => { name => 'units', default => '%' }, + "free" => { name => 'free' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub prefix_disk_output { + my ($self, %options) = @_; + + return "Disk '" . $options{instance_value}->{display} . "' "; +} + +my %map_state = (1 => 'online', 2 => 'offline'); + +my $mapping = { + dstDiskId => { oid => '.1.3.6.1.4.1.41263.3.1.2' }, + dstNumTotalBytes => { oid => '.1.3.6.1.4.1.41263.3.1.6' }, + dstNumFreeBytes => { oid => '.1.3.6.1.4.1.41263.3.1.7' }, + dstNumTotalInodes => { oid => '.1.3.6.1.4.1.41263.3.1.8' }, + dstNumFreeInodes => { oid => '.1.3.6.1.4.1.41263.3.1.9' }, + dstAverageLatency => { oid => '.1.3.6.1.4.1.41263.3.1.10' }, + dstNumberIops => { oid => '.1.3.6.1.4.1.41263.3.1.12' }, + dstState => { oid => '.1.3.6.1.4.1.41263.3.1.13', map => \%map_state }, +}; + +my $oid_dstEntry = '.1.3.6.1.4.1.41263.3.1'; + +sub manage_selection { + my ($self, %options) = @_; + + if ($options{snmp}->is_snmpv1()) { + $self->{output}->add_option_msg(short_msg => "Need to use SNMP v2c or v3."); + $self->{output}->option_exit(); + } + + $self->{disk} = {}; + my $snmp_result = $options{snmp}->get_table(oid => $oid_dstEntry, + nothing_quit => 1); + + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{dstDiskId}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + $result->{dstDiskId} = centreon::plugins::misc::trim($result->{dstDiskId}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{dstDiskId} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{dstDiskId} . "': no matching filter.", debug => 1); + next; + } + + my $inodes_used; + $inodes_used = 100 - ($result->{dstNumFreeInodes} * 100 / $result->{dstNumTotalInodes}) if ($result->{dstNumTotalInodes} > 0); + $self->{disk}->{$instance} = { display => $result->{dstDiskId}, + %$result, inodes_used => $inodes_used, + }; + } + + if (scalar(keys %{$self->{disk}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No disk found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check disk usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^usage$' + +=item B<--filter-name> + +Filter disk name (can be a regexp). + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{state}, %{display} + +=item B<--critical-status> + +Set critical threshold for status. +Can used special variables like: %{state}, %{display} + +=item B<--warning-*> + +Threshold warning. +Can be: 'usage', 'inodes' (%), 'avg-latency', 'iops'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'usage', 'inodes' (%), 'avg-latency', 'iops'. + +=item B<--units> + +Units of thresholds (Default: '%') ('%', 'B'). + +=item B<--free> + +Thresholds are on free space left. + +=back + +=cut diff --git a/cloud/nutanix/snmp/mode/hypervisorusage.pm b/cloud/nutanix/snmp/mode/hypervisorusage.pm new file mode 100644 index 000000000..ef295314f --- /dev/null +++ b/cloud/nutanix/snmp/mode/hypervisorusage.pm @@ -0,0 +1,245 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::hypervisorusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $instance_mode; + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $label = 'memory_used'; + my $value_perf = $self->{result_values}->{used}; + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + my %total_options = (total => $self->{result_values}->{total}, cast_int => 1); + + $self->{output}->perfdata_add(label => $label . $extra_label, unit => 'B', + value => $value_perf, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + my $msg = sprintf("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}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_hypervisorMemory'}; + $self->{result_values}->{prct_used} = $options{new_datas}->{$self->{instance} . '_hypervisorMemoryUsagePercent'}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + $self->{result_values}->{used} = $self->{result_values}->{prct_used} * $self->{result_values}->{total} / 100; + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'hypervisor', type => 1, cb_prefix_output => 'prefix_hypervisor_output', message_multiple => 'All hypervisors are ok', skipped_code => { -10 => 1 } }, + ]; + + $self->{maps_counters}->{hypervisor} = [ + { label => 'cpu', set => { + key_values => [ { name => 'hypervisorCpuUsagePercent' }, { name => 'display' } ], + output_template => 'CPU Usage : %s %%', + perfdatas => [ + { label => 'cpu_usage', value => 'hypervisorCpuUsagePercent_absolute', template => '%s', unit => '%', + min => 0, max => 100, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'memory', set => { + key_values => [ { name => 'display' }, { name => 'hypervisorMemory' }, { name => 'hypervisorMemoryUsagePercent' } ], + threshold_use => 'prct_used', + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + } + }, + { label => 'avg-latency', set => { + key_values => [ { name => 'hypervisorAverageLatency' }, { name => 'display' } ], + output_template => 'Average Latency : %s µs', + perfdatas => [ + { label => 'avg_latency', value => 'hypervisorAverageLatency_absolute', template => '%s', unit => 'µs', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'read-iops', set => { + key_values => [ { name => 'hypervisorReadIOPerSecond' }, { name => 'display' } ], + output_template => 'Read IOPs : %s', + perfdatas => [ + { label => 'read_iops', value => 'hypervisorReadIOPerSecond_absolute', template => '%s', unit => 'iops', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'write-iops', set => { + key_values => [ { name => 'hypervisorWriteIOPerSecond' }, { name => 'display' } ], + output_template => 'Write IOPs : %s', + perfdatas => [ + { label => 'write_iops', value => 'hypervisorWriteIOPerSecond_absolute', template => '%s', unit => 'iops', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'vm-count', set => { + key_values => [ { name => 'hypervisorVmCount' }, { name => 'display' } ], + output_template => 'VM Count : %s', + perfdatas => [ + { label => 'vm_count', value => 'hypervisorVmCount_absolute', template => '%s', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +sub prefix_hypervisor_output { + my ($self, %options) = @_; + + return "Hypervisor '" . $options{instance_value}->{display} . "' "; +} + +my $mapping = { + hypervisorName => { oid => '.1.3.6.1.4.1.41263.9.1.3' }, + hypervisorVmCount => { oid => '.1.3.6.1.4.1.41263.9.1.4' }, + hypervisorCpuUsagePercent => { oid => '.1.3.6.1.4.1.41263.9.1.6' }, + hypervisorMemory => { oid => '.1.3.6.1.4.1.41263.9.1.7' }, + hypervisorMemoryUsagePercent => { oid => '.1.3.6.1.4.1.41263.9.1.8' }, + hypervisorReadIOPerSecond => { oid => '.1.3.6.1.4.1.41263.9.1.9' }, + hypervisorWriteIOPerSecond => { oid => '.1.3.6.1.4.1.41263.9.1.10' }, + hypervisorAverageLatency => { oid => '.1.3.6.1.4.1.41263.9.1.11' }, +}; + +my $oid_hypervisorEntry = '.1.3.6.1.4.1.41263.9.1'; + +sub manage_selection { + my ($self, %options) = @_; + + if ($options{snmp}->is_snmpv1()) { + $self->{output}->add_option_msg(short_msg => "Need to use SNMP v2c or v3."); + $self->{output}->option_exit(); + } + + $self->{hypervisor} = {}; + my $snmp_result = $options{snmp}->get_table(oid => $oid_hypervisorEntry, + nothing_quit => 1); + + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{hypervisorName}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + $result->{hypervisorName} = centreon::plugins::misc::trim($result->{hypervisorName}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{hypervisorName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{hypervisorName} . "': no matching filter.", debug => 1); + next; + } + + $self->{hypervisor}->{$instance} = { display => $result->{hypervisorName}, + %$result, + }; + } + + if (scalar(keys %{$self->{hypervisor}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No hypervisor found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check hypervisor usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^memory$' + +=item B<--filter-name> + +Filter hypervisor name (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'memory' (%), 'avg-latency', 'read-iops', 'write-iops', +'cpu' (%), 'vm-count'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'memory' (%), 'avg-latency', 'read-iops', 'write-iops', +'cpu' (%), 'vm-count'. + +=back + +=cut diff --git a/cloud/nutanix/snmp/mode/listcontainers.pm b/cloud/nutanix/snmp/mode/listcontainers.pm new file mode 100644 index 000000000..82e350f77 --- /dev/null +++ b/cloud/nutanix/snmp/mode/listcontainers.pm @@ -0,0 +1,114 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::listcontainers; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $oid_citContainerName = '.1.3.6.1.4.1.41263.8.1.3'; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $self->{snmp}->get_table(oid => $oid_citContainerName, nothing_quit => 1); + $self->{container} = {}; + foreach my $oid (keys %{$snmp_result}) { + $snmp_result->{$oid} = centreon::plugins::misc::trim($snmp_result->{$oid}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $snmp_result->{$oid} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping container '" . $snmp_result->{$oid} . "'.", debug => 1); + next; + } + + $self->{container}->{$snmp_result->{$oid}} = { name => $snmp_result->{$oid} }; + } +} + +sub run { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{container}}) { + $self->{output}->output_add(long_msg => "'" . $name . "'"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List Containers:'); + $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 => ['name']); +} + +sub disco_show { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{container}}) { + $self->{output}->add_disco_entry(name => $name); + } +} + +1; + +__END__ + +=head1 MODE + +List container. + +=over 8 + +=item B<--filter-name> + +Filter by container name. + +=back + +=cut + diff --git a/cloud/nutanix/snmp/mode/listdisks.pm b/cloud/nutanix/snmp/mode/listdisks.pm new file mode 100644 index 000000000..bde130826 --- /dev/null +++ b/cloud/nutanix/snmp/mode/listdisks.pm @@ -0,0 +1,129 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::listdisks; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::misc; + +my %map_state = ( + 1 => 'online', + 2 => 'offline', +); + +my $mapping = { + dstDiskId => { oid => '.1.3.6.1.4.1.41263.3.1.2' }, + dstState => { oid => '.1.3.6.1.4.1.41263.3.1.13', map => \%map_state }, +}; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $self->{snmp}->get_multiple_table(oids => [ + { oid => $mapping->{dstDiskId}->{oid} }, + { oid => $mapping->{dstState}->{oid} }, + ], return_type => 1, nothing_quit => 1); + $self->{disk} = {}; + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{dstState}->{oid}\.(.*)$/); + + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $1); + $result->{dstDiskId} = centreon::plugins::misc::trim($result->{dstDiskId}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{dstDiskId} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping disk '" . $result->{dstDiskId} . "'.", debug => 1); + next; + } + + $self->{disk}->{$result->{dstDiskId}} = { %{$result} }; + } +} + +sub run { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{disk}}) { + $self->{output}->output_add(long_msg => "[disk_id = " . $self->{disk}->{$name}->{dstDiskId} . "] [state = " . $self->{disk}->{$name}->{dstState} . "]"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List Disks:'); + $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 => ['disk_id', 'state']); +} + +sub disco_show { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{disk}}) { + $self->{output}->add_disco_entry(disk_id => $self->{disk}->{$name}->{dstDiskId}, + state => $self->{disk}->{$name}->{dstState}); + } +} + +1; + +__END__ + +=head1 MODE + +List disks. + +=over 8 + +=item B<--filter-name> + +Filter by disk id. + +=back + +=cut + diff --git a/cloud/nutanix/snmp/mode/listhypervisors.pm b/cloud/nutanix/snmp/mode/listhypervisors.pm new file mode 100644 index 000000000..d99d0a944 --- /dev/null +++ b/cloud/nutanix/snmp/mode/listhypervisors.pm @@ -0,0 +1,114 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::listhypervisors; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $oid_hypervisorName = '.1.3.6.1.4.1.41263.9.1.3'; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $self->{snmp}->get_table(oid => $oid_hypervisorName, nothing_quit => 1); + $self->{hypervisor} = {}; + foreach my $oid (keys %{$snmp_result}) { + $snmp_result->{$oid} = centreon::plugins::misc::trim($snmp_result->{$oid}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $snmp_result->{$oid} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping hypervisor '" . $snmp_result->{$oid} . "'.", debug => 1); + next; + } + + $self->{hypervisor}->{$snmp_result->{$oid}} = { name => $snmp_result->{$oid} }; + } +} + +sub run { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{hypervisor}}) { + $self->{output}->output_add(long_msg => "'" . $name . "'"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List Hypervisors:'); + $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 => ['name']); +} + +sub disco_show { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{hypervisor}}) { + $self->{output}->add_disco_entry(name => $name); + } +} + +1; + +__END__ + +=head1 MODE + +List hypervisors. + +=over 8 + +=item B<--filter-name> + +Filter by hypervisor name. + +=back + +=cut + diff --git a/cloud/nutanix/snmp/mode/liststoragepools.pm b/cloud/nutanix/snmp/mode/liststoragepools.pm new file mode 100644 index 000000000..07499f79d --- /dev/null +++ b/cloud/nutanix/snmp/mode/liststoragepools.pm @@ -0,0 +1,114 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::liststoragepools; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $oid_spitStoragePoolName = '.1.3.6.1.4.1.41263.7.1.3'; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $self->{snmp}->get_table(oid => $oid_spitStoragePoolName, nothing_quit => 1); + $self->{sp} = {}; + foreach my $oid (keys %{$snmp_result}) { + $snmp_result->{$oid} = centreon::plugins::misc::trim($snmp_result->{$oid}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $snmp_result->{$oid} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping storage pool '" . $snmp_result->{$oid} . "'.", debug => 1); + next; + } + + $self->{sp}->{$snmp_result->{$oid}} = { name => $snmp_result->{$oid} }; + } +} + +sub run { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{sp}}) { + $self->{output}->output_add(long_msg => "'" . $name . "'"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List Storage Pools:'); + $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 => ['name']); +} + +sub disco_show { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{sp}}) { + $self->{output}->add_disco_entry(name => $name); + } +} + +1; + +__END__ + +=head1 MODE + +List storage pools. + +=over 8 + +=item B<--filter-name> + +Filter by storage pool name. + +=back + +=cut + diff --git a/cloud/nutanix/snmp/mode/listvms.pm b/cloud/nutanix/snmp/mode/listvms.pm new file mode 100644 index 000000000..fe790f336 --- /dev/null +++ b/cloud/nutanix/snmp/mode/listvms.pm @@ -0,0 +1,124 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::listvms; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $mapping = { + vmName => { oid => '.1.3.6.1.4.1.41263.10.1.3' }, + vmPowerState => { oid => '.1.3.6.1.4.1.41263.10.1.5' }, +}; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $self->{snmp}->get_multiple_table(oids => [ + { oid => $mapping->{vmName}->{oid} }, + { oid => $mapping->{vmPowerState}->{oid} }, + ], return_type => 1, nothing_quit => 1); + $self->{vm} = {}; + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{vmPowerState}->{oid}\.(.*)$/); + + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $1); + $result->{vmName} = centreon::plugins::misc::trim($result->{vmName}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{vmName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping virtual machine '" . $result->{vmName} . "'.", debug => 1); + next; + } + + $self->{vm}->{$result->{vmName}} = { %{$result} }; + } +} + +sub run { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{vm}}) { + $self->{output}->output_add(long_msg => "[name = " . $self->{vm}->{$name}->{vmName} . "] [state = " . $self->{vm}->{$name}->{vmPowerState} . "]"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List Virtual Machines:'); + $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 => ['name', 'state']); +} + +sub disco_show { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{vm}}) { + $self->{output}->add_disco_entry(name => $self->{vm}->{$name}->{vmName}, + state => $self->{vm}->{$name}->{vmPowerState}); + } +} + +1; + +__END__ + +=head1 MODE + +List virtual machines. + +=over 8 + +=item B<--filter-name> + +Filter by virtual machine name. + +=back + +=cut + diff --git a/cloud/nutanix/snmp/mode/storagepoolusage.pm b/cloud/nutanix/snmp/mode/storagepoolusage.pm new file mode 100644 index 000000000..4cae44919 --- /dev/null +++ b/cloud/nutanix/snmp/mode/storagepoolusage.pm @@ -0,0 +1,245 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::storagepoolusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $instance_mode; + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $label = 'used'; + my $value_perf = $self->{result_values}->{used}; + if (defined($instance_mode->{option_results}->{free})) { + $label = 'free'; + $value_perf = $self->{result_values}->{free}; + } + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + my %total_options = (); + if ($instance_mode->{option_results}->{units} eq '%') { + $total_options{total} = $self->{result_values}->{total}; + $total_options{cast_int} = 1; + } + + $self->{output}->perfdata_add(label => $label . $extra_label, unit => 'B', + value => $value_perf, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_usage_threshold { + my ($self, %options) = @_; + + my ($exit, $threshold_value); + $threshold_value = $self->{result_values}->{used}; + $threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free})); + if ($instance_mode->{option_results}->{units} eq '%') { + $threshold_value = $self->{result_values}->{prct_used}; + $threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free})); + } + $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + my $msg = sprintf("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}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_spitTotalCapacity'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_spitUsedCapacity'}; + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'sp', type => 1, cb_prefix_output => 'prefix_sp_output', message_multiple => 'All storage pools are ok', skipped_code => { -10 => 1 } }, + ]; + + $self->{maps_counters}->{sp} = [ + { label => 'usage', set => { + key_values => [ { name => 'display' }, { name => 'spitUsedCapacity' }, { name => 'spitTotalCapacity' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + { label => 'avg-latency', set => { + key_values => [ { name => 'spitAvgLatencyUsecs' }, { name => 'display' } ], + output_template => 'Average Latency : %s µs', + perfdatas => [ + { label => 'avg_latency', value => 'spitAvgLatencyUsecs_absolute', template => '%s', unit => 'µs', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'iops', set => { + key_values => [ { name => 'spitIOPerSecond' }, { name => 'display' } ], + output_template => 'IOPs : %s', + perfdatas => [ + { label => 'iops', value => 'spitIOPerSecond_absolute', template => '%s', unit => 'iops', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "units:s" => { name => 'units', default => '%' }, + "free" => { name => 'free' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +sub prefix_sp_output { + my ($self, %options) = @_; + + return "Storage Pool '" . $options{instance_value}->{display} . "' "; +} + +my $mapping = { + spitStoragePoolName => { oid => '.1.3.6.1.4.1.41263.7.1.3' }, + spitTotalCapacity => { oid => '.1.3.6.1.4.1.41263.7.1.4' }, + spitUsedCapacity => { oid => '.1.3.6.1.4.1.41263.7.1.5' }, + spitIOPerSecond => { oid => '.1.3.6.1.4.1.41263.7.1.6' }, + spitAvgLatencyUsecs => { oid => '.1.3.6.1.4.1.41263.7.1.7' }, +}; + +my $oid_spitEntry = '.1.3.6.1.4.1.41263.7.1'; + +sub manage_selection { + my ($self, %options) = @_; + + if ($options{snmp}->is_snmpv1()) { + $self->{output}->add_option_msg(short_msg => "Need to use SNMP v2c or v3."); + $self->{output}->option_exit(); + } + + $self->{sp} = {}; + my $snmp_result = $options{snmp}->get_table(oid => $oid_spitEntry, + nothing_quit => 1); + + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{spitStoragePoolName}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + $result->{spitStoragePoolName} = centreon::plugins::misc::trim($result->{spitStoragePoolName}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{spitStoragePoolName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{spitStoragePoolName} . "': no matching filter.", debug => 1); + next; + } + + $self->{sp}->{$instance} = { display => $result->{spitStoragePoolName}, + %$result, + }; + } + + if (scalar(keys %{$self->{sp}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No storage pool found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check storage pool usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^usage$' + +=item B<--filter-name> + +Filter storage pool name (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'usage', 'avg-latency', 'iops'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'usage', 'avg-latency', 'iops'. + +=item B<--units> + +Units of thresholds (Default: '%') ('%', 'B'). + +=item B<--free> + +Thresholds are on free space left. + +=back + +=cut diff --git a/cloud/nutanix/snmp/mode/vmusage.pm b/cloud/nutanix/snmp/mode/vmusage.pm new file mode 100644 index 000000000..760421f31 --- /dev/null +++ b/cloud/nutanix/snmp/mode/vmusage.pm @@ -0,0 +1,214 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::vmusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; +use Digest::MD5 qw(md5_hex); + +my $instance_mode; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'vm', type => 1, cb_prefix_output => 'prefix_vm_output', message_multiple => 'All virtual machines are ok', skipped_code => { -10 => 1 } }, + ]; + + $self->{maps_counters}->{vm} = [ + { label => 'cpu', set => { + key_values => [ { name => 'vmCpuUsagePercent' }, { name => 'display' } ], + output_template => 'CPU Usage : %s %%', + perfdatas => [ + { label => 'cpu_usage', value => 'vmCpuUsagePercent_absolute', template => '%s', unit => '%', + min => 0, max => 100, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'avg-latency', set => { + key_values => [ { name => 'vmAverageLatency' }, { name => 'display' } ], + output_template => 'Average Latency : %s µs', + perfdatas => [ + { label => 'avg_latency', value => 'vmAverageLatency_absolute', template => '%s', unit => 'µs', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'read-iops', set => { + key_values => [ { name => 'vmReadIOPerSecond' }, { name => 'display' } ], + output_template => 'Read IOPs : %s', + perfdatas => [ + { label => 'read_iops', value => 'vmReadIOPerSecond_absolute', template => '%s', unit => 'iops', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'write-iops', set => { + key_values => [ { name => 'vmWriteIOPerSecond' }, { name => 'display' } ], + output_template => 'Write IOPs : %s', + perfdatas => [ + { label => 'write_iops', value => 'vmWriteIOPerSecond_absolute', template => '%s', unit => 'iops', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'traffic-in', set => { + key_values => [ { name => 'vmRxBytes', diff => 1 }, { name => 'display' } ], + output_template => 'Traffic In : %s %s/s', + per_second => 1, output_change_bytes => 2, + perfdatas => [ + { label => 'traffic_in', value => 'vmRxBytes_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'traffic-out', set => { + key_values => [ { name => 'vmTxBytes', diff => 1 }, { name => 'display' } ], + output_template => 'Traffic Out : %s %s/s', + per_second => 1, output_change_bytes => 2, + perfdatas => [ + { label => 'traffic_out', value => 'vmTxBytes_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +sub prefix_vm_output { + my ($self, %options) = @_; + + return "Virtual machine '" . $options{instance_value}->{display} . "' "; +} + +my $mapping = { + vmName => { oid => '.1.3.6.1.4.1.41263.10.1.3' }, + vmCpuUsagePercent => { oid => '.1.3.6.1.4.1.41263.10.1.7' }, + vmMemory => { oid => '.1.3.6.1.4.1.41263.10.1.8' }, + vmMemoryUsagePercent => { oid => '.1.3.6.1.4.1.41263.10.1.9' }, + vmReadIOPerSecond => { oid => '.1.3.6.1.4.1.41263.10.1.10' }, + vmWriteIOPerSecond => { oid => '.1.3.6.1.4.1.41263.10.1.11' }, + vmAverageLatency => { oid => '.1.3.6.1.4.1.41263.10.1.12' }, + vmRxBytes => { oid => '.1.3.6.1.4.1.41263.10.1.14' }, + vmTxBytes => { oid => '.1.3.6.1.4.1.41263.10.1.15' }, +}; + +my $oid_vmEntry = '.1.3.6.1.4.1.41263.10.1'; + +sub manage_selection { + my ($self, %options) = @_; + + if ($options{snmp}->is_snmpv1()) { + $self->{output}->add_option_msg(short_msg => "Need to use SNMP v2c or v3."); + $self->{output}->option_exit(); + } + + $self->{vm} = {}; + my $snmp_result = $options{snmp}->get_table(oid => $oid_vmEntry, + nothing_quit => 1); + + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{vmName}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + $result->{vmName} = centreon::plugins::misc::trim($result->{vmName}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{vmName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{vmName} . "': no matching filter.", debug => 1); + next; + } + + $result->{vmRxBytes} *= 8; + $result->{vmTxBytes} *= 8; + $self->{vm}->{$instance} = { display => $result->{vmName}, + %$result, + }; + } + + if (scalar(keys %{$self->{vm}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No virtual machine found."); + $self->{output}->option_exit(); + } + + $self->{cache_name} = "nutanix_" . $self->{mode} . '_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . + (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); +} + +1; + +__END__ + +=head1 MODE + +Check virtual machine usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^memory$' + +=item B<--filter-name> + +Filter virtual machine name (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'avg-latency', 'read-iops', 'write-iops', +'cpu' (%), 'traffic-in', 'traffic-out'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'avg-latency', 'read-iops', 'write-iops', +'cpu' (%), 'traffic-in', 'traffic-out'. + +=back + +=cut diff --git a/cloud/nutanix/snmp/plugin.pm b/cloud/nutanix/snmp/plugin.pm new file mode 100644 index 000000000..019f2e53e --- /dev/null +++ b/cloud/nutanix/snmp/plugin.pm @@ -0,0 +1,58 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_snmp); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + %{$self->{modes}} = ( + 'cluster-usage' => 'cloud::nutanix::snmp::mode::clusterusage', + 'container-usage' => 'cloud::nutanix::snmp::mode::containerusage', + 'disk-usage' => 'cloud::nutanix::snmp::mode::diskusage', + 'hypervisor-usage' => 'cloud::nutanix::snmp::mode::hypervisorusage', + 'list-containers' => 'cloud::nutanix::snmp::mode::listcontainers', + 'list-disks' => 'cloud::nutanix::snmp::mode::listdisks', + 'list-hypervisors' => 'cloud::nutanix::snmp::mode::listhypervisors', + 'list-storage-pools' => 'cloud::nutanix::snmp::mode::liststoragepools', + 'list-vms' => 'cloud::nutanix::snmp::mode::listvms', + 'storage-pool-usage' => 'cloud::nutanix::snmp::mode::storagepoolusage', + 'vm-usage' => 'cloud::nutanix::snmp::mode::vmusage', + ); + + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Nutanix in SNMP. + +=cut diff --git a/docs/en/user/guide.rst b/docs/en/user/guide.rst index 41038eed7..8745fb42b 100644 --- a/docs/en/user/guide.rst +++ b/docs/en/user/guide.rst @@ -884,3 +884,176 @@ An example for authentification form of ``demo.centreon.com``: $ perl centreon_plugins.pl --plugin=apps::protocols::http::plugin --mode=expected-content --hostname=demo.centreon.com --method='POST' --post-param='useralias=admin' --post-param='password=centreon' --cookies-file='/tmp/lwp_cookies.dat' --urlpath='/centreon/index.php' --expected-string='color_UNREACHABLE' OK: 'color_UNREACHABLE' is present in content. | 'time'=0.575s;;;0; 'size'=20708B;;;0; + +--------------- +Modbus Protocol +--------------- + +Check 3 holding registers +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The content of the ``modbus.json`` file can be set directly in ``--config`` option (eg. : ``--config='{ "selection": { "metric1":{...'``). +The ``type`` attribute can have following values: + +* holding (default) +* coils +* discrete +* input + +:: + + { + "selection":{ + "metric1":{ + "address": 1, + "quantity": 1, + "type": "holding", + "display": true + }, + "metric2":{ + "address": 2, + "quantity": 1, + "type": "holding", + "display": true + }, + "metric3":{ + "address": 3, + "quantity": 1, + "type": "holding", + "display": true + } + } + } + +The command result: +:: + + $ perl centreon_plugins.pl --plugin=apps/protocols/modbus/plugin.pm --mode=numeric-value --tcp-host=10.0.0.1 --config=modbus.json --verbose + OK: All metrics are OK | 'metric1'=0;;;; 'metric2'=41291;;;; 'metric3'=42655;;;; + Metric 'metric1' value is '0' + Metric 'metric2' value is '41291' + Metric 'metric3' value is '42655' + +How to change the formatting output ? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There is a command section to change formatting output globally and also to override for each metrics: +:: + + { + "selection":{ + "metric1":{ + "address": 1, + "quantity": 1, + "type": "holding", + "display": true + }, + "metric2":{ + "address": 2, + "quantity": 1, + "type": "holding", + "display": true + }, + "metric3":{ + "address": 3, + "quantity": 1, + "type": "holding", + "display": true, + "formatting": { + "printf_msg": "Override '%s' value is %.2f", + "printf_var": "$self->{result_values}->{instance}, $self->{result_values}->{value}" + } + } + }, + "formatting": { + "printf_msg": "My metric '%s' value is %.2f", + "printf_var": "$self->{result_values}->{instance}, $self->{result_values}->{value}" + } + } + +The command result: +:: + + $ perl centreon_plugins.pl --plugin=apps/protocols/modbus/plugin.pm --mode=numeric-value --tcp-host=10.0.0.1 --config=modbus.json --verbose + OK: All metrics are OK | 'metric1'=0;;;; 'metric2'=41291;;;; 'metric3'=42655;;;; + My Metric 'metric1' value is 0.00 + My Metric 'metric2' value is 41291.00 + Override 'metric3' value is 42655.00 + +How to average 4 registers ? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +We create following average values: ``[x1 + x2 / 2 = y]`` ``[x3 + x4 / 2 = z]``. +With the pattern, you can select the metrics. In our case, we get 4 values in one selection. +Selected metric names are: ``metrics.0``, ``metrics.1``, ``metrics.2``, ``metrics.3`` (order is preserved). + +The ``aggregation`` attribute can have following values: + +* avg: returns the average of all the elements. +* sum: returns the numerical sum of all the elements. +* min: returns the entry in elements with the lowest numerical value. +* max: returns the entry in elements with the highest numerical value. + +:: + + { + "selection":{ + "metrics":{ + "address": 1, + "quantity": 4, + "type": "holding", + "display": false + } + }, + "virtualcurve":{ + "avg1":{ + "pattern": "metrics\\.[01]$", + "aggregation": "avg", + "unit": "con" + }, + "avg2":{ + "pattern": "metrics\\.[23]$", + "aggregation": "avg", + "unit": "con" + } + } + } + +The command result: +:: + + $ perl centreon_plugins.pl --plugin=apps/protocols/modbus/plugin.pm --mode=numeric-value --tcp-host=10.0.0.1 --config=modbus.json --verbose + OK: Global metrics are OK | 'avg1'=42192con;;;; 'avg2'=40574con;;;; + Metric 'avg1' value is '42192' + Metric 'avg2' value is '40574' + +Apply a custom calculation +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There is a ``custom`` attribute to applied some change on the value: +:: + + { + "selection":{ + "metrics":{ + "address": 1, + "quantity": 4, + "type": "holding", + "display": false + } + }, + "virtualcurve":{ + "avg":{ + "aggregation": "avg", + "custom": " / 10", + "unit": "con" + } + } + } + +The command result: +:: + + $ perl centreon_plugins.pl --plugin=apps/protocols/modbus/plugin.pm --mode=numeric-value --tcp-host=10.0.0.1 --config=modbus.json --verbose + OK: Metric 'avg' value is '3072.3' | 'avg'=3072.3con;;;; + Metric 'avg' value is '3072.3' diff --git a/docs/fr/user/guide.rst b/docs/fr/user/guide.rst index 7e83f4a79..50f7b75f0 100644 --- a/docs/fr/user/guide.rst +++ b/docs/fr/user/guide.rst @@ -885,3 +885,176 @@ Voici un exemple pour le formulaire d'authentification de ``demo.centreon.com`` $ perl centreon_plugins.pl --plugin=apps::protocols::http::plugin --mode=expected-content --hostname=demo.centreon.com --method='POST' --post-param='useralias=admin' --post-param='password=centreon' --cookies-file='/tmp/lwp_cookies.dat' --urlpath='/centreon/index.php' --expected-string='color_UNREACHABLE' OK: 'color_UNREACHABLE' is present in content. | 'time'=0.575s;;;0; 'size'=20708B;;;0; + +---------------- +Protocole Modbus +---------------- + +Contrôler 3 registres holding +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Le contenu du fichier ``modbus.json`` peut être spécifié directement dans l'option ``--config`` (exemple: ``--config='{ "selection": { "metric1":{...'``). +L'attribut ``type`` peut avoir les valeurs suivantes : + +* holding (défaut) +* coils +* discrete +* input + +:: + + { + "selection":{ + "metric1":{ + "address": 1, + "quantity": 1, + "type": "holding", + "display": true + }, + "metric2":{ + "address": 2, + "quantity": 1, + "type": "holding", + "display": true + }, + "metric3":{ + "address": 3, + "quantity": 1, + "type": "holding", + "display": true + } + } + } + +Le résultat de la commande : +:: + + $ perl centreon_plugins.pl --plugin=apps/protocols/modbus/plugin.pm --mode=numeric-value --tcp-host=10.0.0.1 --config=modbus.json --verbose + OK: All metrics are OK | 'metric1'=0;;;; 'metric2'=41291;;;; 'metric3'=42655;;;; + Metric 'metric1' value is '0' + Metric 'metric2' value is '41291' + Metric 'metric3' value is '42655' + +Comment modifier la sortie ? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Il existe une section pour modifier la sortie globallement. Il est aussi possible de surcharger une métrique spécifiquement : +:: + + { + "selection":{ + "metric1":{ + "address": 1, + "quantity": 1, + "type": "holding", + "display": true + }, + "metric2":{ + "address": 2, + "quantity": 1, + "type": "holding", + "display": true + }, + "metric3":{ + "address": 3, + "quantity": 1, + "type": "holding", + "display": true, + "formatting": { + "printf_msg": "Override '%s' value is %.2f", + "printf_var": "$self->{result_values}->{instance}, $self->{result_values}->{value}" + } + } + }, + "formatting": { + "printf_msg": "My metric '%s' value is %.2f", + "printf_var": "$self->{result_values}->{instance}, $self->{result_values}->{value}" + } + } + +Le résultat de la commande : +:: + + $ perl centreon_plugins.pl --plugin=apps/protocols/modbus/plugin.pm --mode=numeric-value --tcp-host=10.0.0.1 --config=modbus.json --verbose + OK: All metrics are OK | 'metric1'=0;;;; 'metric2'=41291;;;; 'metric3'=42655;;;; + My Metric 'metric1' value is 0.00 + My Metric 'metric2' value is 41291.00 + Override 'metric3' value is 42655.00 + +Comment moyenner 4 registres ? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Nous créons les valeurs moyennées suivantes : ``[x1 + x2 / 2 = y]`` ``[x3 + x4 / 2 = z]``. +Avec l'attribut ``pattern``, il est possible de sélectionner les valeurs. Dans notre cas, nous récupérons 4 valeurs en 1 seule sélection. +Les valeurs sélectionnées se nomment : ``metrics.0``, ``metrics.1``, ``metrics.2``, ``metrics.3`` (order is preserved). + +L'attribut ``aggregation`` peut avoir les valeurs suivantes : + +* avg: retourne la moyenne des valeurs. +* sum: retourne la somme des valeurs. +* min: retourne la plus petite valeur numérique des valeurs. +* max: retourne la plus grande valeur numérique des valeurs. + +:: + + { + "selection":{ + "metrics":{ + "address": 1, + "quantity": 4, + "type": "holding", + "display": false + } + }, + "virtualcurve":{ + "avg1":{ + "pattern": "metrics\\.[01]$", + "aggregation": "avg", + "unit": "con" + }, + "avg2":{ + "pattern": "metrics\\.[23]$", + "aggregation": "avg", + "unit": "con" + } + } + } + +Le résultat de la commande : +:: + + $ perl centreon_plugins.pl --plugin=apps/protocols/modbus/plugin.pm --mode=numeric-value --tcp-host=10.0.0.1 --config=modbus.json --verbose + OK: Global metrics are OK | 'avg1'=42192con;;;; 'avg2'=40574con;;;; + Metric 'avg1' value is '42192' + Metric 'avg2' value is '40574' + +Appliquer un calcul spécifique +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +L'attribut ``custom`` permet d'appliquer des modifications à la valeur : +:: + + { + "selection":{ + "metrics":{ + "address": 1, + "quantity": 4, + "type": "holding", + "display": false + } + }, + "virtualcurve":{ + "avg":{ + "aggregation": "avg", + "custom": " / 10", + "unit": "con" + } + } + } + +Le résultat de la commande : +:: + + $ perl centreon_plugins.pl --plugin=apps/protocols/modbus/plugin.pm --mode=numeric-value --tcp-host=10.0.0.1 --config=modbus.json --verbose + OK: Metric 'avg' value is '3072.3' | 'avg'=3072.3con;;;; + Metric 'avg' value is '3072.3' \ No newline at end of file diff --git a/hardware/pdu/apc/snmp/mode/outlet.pm b/hardware/pdu/apc/snmp/mode/outlet.pm index 51d0daf49..015356ace 100644 --- a/hardware/pdu/apc/snmp/mode/outlet.pm +++ b/hardware/pdu/apc/snmp/mode/outlet.pm @@ -164,6 +164,7 @@ sub run { } if (defined($result->{rPDUOutletStatusLoad}) && $result->{rPDUOutletStatusLoad} =~ /[0-9]/ && $result->{rPDUOutletStatusLoad} != 0) { + $result->{rPDUOutletStatusLoad} /= 10; my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'load', instance => $instance, value => $result->{rPDUOutletStatusLoad}); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit2, @@ -280,4 +281,4 @@ Set critical threshold for temperatures (syntax: type,instance,threshold) Example: --critical='load,.*,40' =back -=cut \ No newline at end of file +=cut diff --git a/hardware/printers/standard/rfc3805/mode/markersupply.pm b/hardware/printers/standard/rfc3805/mode/markersupply.pm index dfafda3b7..0aa8214a3 100644 --- a/hardware/printers/standard/rfc3805/mode/markersupply.pm +++ b/hardware/printers/standard/rfc3805/mode/markersupply.pm @@ -30,6 +30,8 @@ use centreon::plugins::misc; my %unit_managed = ( 3 => 1, # tenThousandthsOfInches(3), -- .0001 4 => 1, # micrometers(4), + 7 => 1, # impressions(7), + 8 => 1, # sheets(8), 12 => 1, # thousandthsOfOunces(12), 13 => 1, # tenthsOfGrams(13), 14 => 1, # hundrethsOfFluidOunces(14), @@ -128,7 +130,7 @@ sub run { $prct_value = $current_value * 100 / $max_value; } - my $exit = $self->{perfdata}->threshold_check(value => $prct_value, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); + my $exit = $self->{perfdata}->threshold_check(value => $prct_value, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(long_msg => sprintf("Marker supply '%s': %.2f %% [instance: '%s']", $descr, $prct_value, $hrDeviceIndex . '.' . $prtMarkerSuppliesIndex)); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, @@ -136,8 +138,9 @@ sub run { } my $label = $descr; - if ($result->{$oid_prtMarkerSuppliesColorantIndex . '.' . $instance} != 0) { - $label = $result2->{$oid_prtMarkerColorantValue . '.' . $hrDeviceIndex . '.' . $result->{$oid_prtMarkerSuppliesColorantIndex . '.' . $instance}}; + if ($result->{$oid_prtMarkerSuppliesColorantIndex . '.' . $instance} != 0 && + defined($result2->{$oid_prtMarkerColorantValue . '.' . $hrDeviceIndex . '.' . $result->{$oid_prtMarkerSuppliesColorantIndex . '.' . $instance}})) { + $label .= '#' . $result2->{$oid_prtMarkerColorantValue . '.' . $hrDeviceIndex . '.' . $result->{$oid_prtMarkerSuppliesColorantIndex . '.' . $instance}}; if (defined($perf_label->{$label})) { $label .= '#' . $hrDeviceIndex . '#' . $prtMarkerSuppliesIndex; } diff --git a/hardware/server/hp/ilo/xmlapi/mode/components/bios.pm b/hardware/server/hp/ilo/xmlapi/mode/components/bios.pm new file mode 100644 index 000000000..8ecf8af4f --- /dev/null +++ b/hardware/server/hp/ilo/xmlapi/mode/components/bios.pm @@ -0,0 +1,54 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package hardware::server::hp::ilo::xmlapi::mode::components::bios; + +use strict; +use warnings; + +sub load { } + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking bios"); + $self->{components}->{bios} = {name => 'bios', total => 0, skip => 0}; + return if ($self->check_filter(section => 'bios')); + return if (!defined($self->{xml_result}->{GET_EMBEDDED_HEALTH_DATA}->{HEALTH_AT_A_GLANCE}->{BIOS_HARDWARE})); + + # + # + my $status = $self->{xml_result}->{GET_EMBEDDED_HEALTH_DATA}->{HEALTH_AT_A_GLANCE}->{BIOS_HARDWARE}->{STATUS}; + next if ($status =~ /not installed|n\/a|not present|not applicable/i && + $self->absent_problem(section => 'bios')); + + $self->{components}->{bios}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("BIOS status is '%s'", + $status)); + + my $exit = $self->get_severity(label => 'default', section => 'bios', value => $status); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("BIOS status is '%s'", $status)); + } +} + +1; \ No newline at end of file diff --git a/hardware/server/hp/ilo/xmlapi/mode/hardware.pm b/hardware/server/hp/ilo/xmlapi/mode/hardware.pm index 679da787a..0fe7b3cbc 100644 --- a/hardware/server/hp/ilo/xmlapi/mode/hardware.pm +++ b/hardware/server/hp/ilo/xmlapi/mode/hardware.pm @@ -29,7 +29,7 @@ sub set_system { my ($self, %options) = @_; $self->{regexp_threshold_overload_check_section_option} = - '^(temperature|fan|vrm|psu|cpu|memory|nic|battery|ctrl|driveencl|pdrive|ldrive)$'; + '^(temperature|fan|vrm|psu|cpu|memory|nic|battery|ctrl|driveencl|pdrive|ldrive|bios)$'; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|fan)$'; $self->{cb_hook2} = 'api_execute'; @@ -54,7 +54,7 @@ sub set_system { $self->{components_path} = 'hardware::server::hp::ilo::xmlapi::mode::components'; $self->{components_module} = ['fan', 'temperature', 'vrm', 'psu', 'cpu', 'memory', 'nic', 'battery', 'ctrl', - 'driveencl', 'pdrive', 'ldrive']; + 'driveencl', 'pdrive', 'ldrive', 'bios']; } sub api_execute { @@ -90,7 +90,7 @@ Check hardware. Which component to check (Default: '.*'). Can be: 'fan', 'temperature', 'vrm', 'psu', 'cpu', 'memory', 'nic', 'battery', 'ctrl', -'driveencl', 'pdrive', 'ldrive'. +'driveencl', 'pdrive', 'ldrive', 'bios'. =item B<--filter> diff --git a/network/alcatel/common/mode/components/backplane.pm b/network/alcatel/common/mode/components/backplane.pm deleted file mode 100644 index e0368b0cc..000000000 --- a/network/alcatel/common/mode/components/backplane.pm +++ /dev/null @@ -1,106 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package network::alcatel::common::mode::components::backplane; - -use strict; -use warnings; -use network::alcatel::common::mode::components::resources qw(%physical_class %phys_oper_status %phys_admin_status %oids); - -my @admin_conditions = ( - ['^(reset|takeover|resetWithFabric|takeoverWithFabrc)$', 'WARNING'], - ['^(powerOff)$', 'CRITICAL'], - ['^(?!(powerOn|standby)$)', 'UNKNOWN'], -); - -my @oper_conditions = ( - ['^(testing)$', 'WARNING'], - ['^(unpowered|down|notpresent)$', 'CRITICAL'], - ['^(?!(up|secondary|master|idle)$)', 'UNKNOWN'], -); - -sub check { - my ($self) = @_; - - $self->{output}->output_add(long_msg => "Checking backplane"); - $self->{components}->{backplane} = {name => 'backplanes', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'backplane')); - - my @instances = (); - foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { - if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 4) { - next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); - push @instances, $1; - } - } - - foreach my $instance (@instances) { - next if (!defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); - - my $descr = defined($self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance} : 'unknown'; - my $name = defined($self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance} : 'unknown'; - my $admin_status = defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance} : 1; - my $oper_status = defined($self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance} : 4; - my $power = defined($self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance} : -1; - - next if ($self->check_exclude(section => 'backplane', instance => $instance)); - $self->{components}->{backplane}->{total}++; - - $self->{output}->output_add(long_msg => sprintf("backplane '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", - $name, $descr, $instance, - $phys_admin_status{$admin_status}, $phys_oper_status{$oper_status}) - ); - - my $go_forward = 1; - foreach (@admin_conditions) { - if ($phys_admin_status{$admin_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("backplane '%s/%s/%s' admin status is %s", - $name, $descr, $instance, $phys_admin_status{$admin_status})); - $go_forward = 0; - last; - } - } - - if ($power > 0) { - $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', - value => $power, - min => 0); - } - - next if ($go_forward == 0); - - foreach (@oper_conditions) { - if ($phys_oper_status{$oper_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("backplane '%s/%s/%s' oeprationnal status is %s", - $name, $descr, $instance, $phys_oper_status{$oper_status})); - last; - } - } - } -} - -1; \ No newline at end of file diff --git a/network/alcatel/common/mode/components/chassis.pm b/network/alcatel/common/mode/components/chassis.pm deleted file mode 100644 index 258f68c67..000000000 --- a/network/alcatel/common/mode/components/chassis.pm +++ /dev/null @@ -1,140 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package network::alcatel::common::mode::components::chassis; - -use strict; -use warnings; -use network::alcatel::common::mode::components::resources qw(%physical_class %phys_oper_status %phys_admin_status %oids); - -my @admin_conditions = ( - ['^(reset|takeover|resetWithFabric|takeoverWithFabrc)$', 'WARNING'], - ['^(powerOff)$', 'CRITICAL'], - ['^(?!(powerOn|standby)$)', 'UNKNOWN'], -); - -my @oper_conditions = ( - ['^(testing)$', 'WARNING'], - ['^(unpowered|down|notpresent)$', 'CRITICAL'], - ['^(?!(up|secondary|master|idle)$)', 'UNKNOWN'], -); - -sub check { - my ($self) = @_; - - $self->{output}->output_add(long_msg => "Checking chassis"); - $self->{components}->{chassis} = {name => 'chassis', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'chassis')); - - my @instances = (); - foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { - if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 3) { - next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); - push @instances, $1; - } - } - - return if (scalar(@instances) == 0); - - foreach my $instance (@instances) { - next if (!defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); - - my $descr = defined($self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance} : 'unknown'; - my $name = defined($self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance} : 'unknown'; - my $admin_status = defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance} : 1; - my $oper_status = defined($self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance} : 4; - my $power = defined($self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance} : -1; - - next if ($self->check_exclude(section => 'chassis', instance => $instance)); - $self->{components}->{chassis}->{total}++; - - $self->{output}->output_add(long_msg => sprintf("chassis '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", - $name, $descr, $instance, - $phys_admin_status{$admin_status}, $phys_oper_status{$oper_status}) - ); - - my $go_forward = 1; - foreach (@admin_conditions) { - if ($phys_admin_status{$admin_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("chassis '%s/%s/%s' admin status is %s", - $name, $descr, $instance, $phys_admin_status{$admin_status})); - $go_forward = 0; - last; - } - } - - if ($power > 0) { - $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', - value => $power, - min => 0); - } - - next if ($go_forward == 0); - - foreach (@oper_conditions) { - if ($phys_oper_status{$oper_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("chassis '%s/%s/%s' oeprationnal status is %s", - $name, $descr, $instance, $phys_oper_status{$oper_status})); - last; - } - } - } - - # Check board temp - $self->{snmp}->load(oids => [$oids{chasHardwareBoardTemp}, $oids{chasTempThreshold}, $oids{chasDangerTempThreshold}], - instances => [@instances]); - my $result = $self->{snmp}->get_leef(); - foreach my $instance (@instances) { - my $value = defined($result->{$oids{chasHardwareBoardTemp} . '.' . $instance}) ? - $result->{$oids{chasHardwareBoardTemp} . '.' . $instance} : undef; - my $warn = defined($result->{$oids{chasTempThreshold} . '.' . $instance}) ? - $result->{$oids{chasTempThreshold} . '.' . $instance} : undef; - my $crit = defined($result->{$oids{chasDangerTempThreshold} . '.' . $instance}) ? - $result->{$oids{chasDangerTempThreshold} . '.' . $instance} : undef; - - next if (!defined($value)); - - $self->{perfdata}->threshold_validate(label => 'warning_' . $instance, value => $warn); - $self->{perfdata}->threshold_validate(label => 'critical_' . $instance, value => $crit); - - my $exit = $self->{perfdata}->threshold_check(value => $value, threshold => [ { label => 'critical_' . $instance, 'exit_litteral' => 'critical' }, { label => 'warning_' . $instance, exit_litteral => 'warning' } ]); - $self->{output}->output_add(long_msg => sprintf("Temperature board '%s' value is %s C.", - $instance, $value)); - if (!$self->{output}->is_status(litteral => 1, value => $exit, compare => 'ok')) { - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Temperature board '%s' value is %s C", $instance, $value)); - } - - $self->{output}->perfdata_add(label => 'temp_board_' . $instance, unit => 'C', - value => $value, - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning_' . $instance), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical_' . $instance), - ); - } -} - -1; \ No newline at end of file diff --git a/network/alcatel/common/mode/components/container.pm b/network/alcatel/common/mode/components/container.pm deleted file mode 100644 index 4dc5c6cd6..000000000 --- a/network/alcatel/common/mode/components/container.pm +++ /dev/null @@ -1,106 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package network::alcatel::common::mode::components::container; - -use strict; -use warnings; -use network::alcatel::common::mode::components::resources qw(%physical_class %phys_oper_status %phys_admin_status %oids); - -my @admin_conditions = ( - ['^(reset|takeover|resetWithFabric|takeoverWithFabrc)$', 'WARNING'], - ['^(powerOff)$', 'CRITICAL'], - ['^(?!(powerOn|standby)$)', 'UNKNOWN'], -); - -my @oper_conditions = ( - ['^(testing)$', 'WARNING'], - ['^(unpowered|down|notpresent)$', 'CRITICAL'], - ['^(?!(up|secondary|master|idle)$)', 'UNKNOWN'], -); - -sub check { - my ($self) = @_; - - $self->{output}->output_add(long_msg => "Checking container"); - $self->{components}->{container} = {name => 'containers', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'container')); - - my @instances = (); - foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { - if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 5) { - next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); - push @instances, $1; - } - } - - foreach my $instance (@instances) { - next if (!defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); - - my $descr = defined($self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance} : 'unknown'; - my $name = defined($self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance} : 'unknown'; - my $admin_status = defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance} : 1; - my $oper_status = defined($self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance} : 4; - my $power = defined($self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance} : -1; - - next if ($self->check_exclude(section => 'container', instance => $instance)); - $self->{components}->{container}->{total}++; - - $self->{output}->output_add(long_msg => sprintf("container '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", - $name, $descr, $instance, - $phys_admin_status{$admin_status}, $phys_oper_status{$oper_status}) - ); - - my $go_forward = 1; - foreach (@admin_conditions) { - if ($phys_admin_status{$admin_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("container '%s/%s/%s' admin status is %s", - $name, $descr, $instance, $phys_admin_status{$admin_status})); - $go_forward = 0; - last; - } - } - - if ($power > 0) { - $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', - value => $power, - min => 0); - } - - next if ($go_forward == 0); - - foreach (@oper_conditions) { - if ($phys_oper_status{$oper_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("container '%s/%s/%s' oeprationnal status is %s", - $name, $descr, $instance, $phys_oper_status{$oper_status})); - last; - } - } - } -} - -1; \ No newline at end of file diff --git a/network/alcatel/common/mode/components/fan.pm b/network/alcatel/common/mode/components/fan.pm deleted file mode 100644 index 8ac72436d..000000000 --- a/network/alcatel/common/mode/components/fan.pm +++ /dev/null @@ -1,146 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package network::alcatel::common::mode::components::fan; - -use strict; -use warnings; -use network::alcatel::common::mode::components::resources qw(%physical_class %phys_oper_status %phys_admin_status %oids); - -my @admin_conditions = ( - ['^(reset|takeover|resetWithFabric|takeoverWithFabrc)$', 'WARNING'], - ['^(powerOff)$', 'CRITICAL'], - ['^(?!(powerOn|standby)$)', 'UNKNOWN'], -); - -my @oper_conditions = ( - ['^(testing)$', 'WARNING'], - ['^(unpowered|down|notpresent)$', 'CRITICAL'], - ['^(?!(up|secondary|master|idle)$)', 'UNKNOWN'], -); - -my @fan_conditions = ( - ['^noStatus$', 'UNKNOWN'], - ['^notRunning$', 'CRITICAL'], - ['^(?!(running)$)', 'UNKNOWN'], -); - -my %fan_status = ( - 0 => 'noStatus', - 1 => 'notRunning', - 2 => 'running', -); - -sub check { - my ($self) = @_; - - $self->{output}->output_add(long_msg => "Checking fan"); - $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'fan')); - - my @instances = (); - foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { - if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 7) { - next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); - push @instances, $1; - } - } - - foreach my $instance (@instances) { - next if (!defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); - - my $descr = defined($self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance} : 'unknown'; - my $name = defined($self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance} : 'unknown'; - my $admin_status = defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance} : 1; - my $oper_status = defined($self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance} : 4; - my $power = defined($self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance} : -1; - - next if ($self->check_exclude(section => 'fan', instance => $instance)); - $self->{components}->{fan}->{total}++; - - $self->{output}->output_add(long_msg => sprintf("fan '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", - $name, $descr, $instance, - $phys_admin_status{$admin_status}, $phys_oper_status{$oper_status}) - ); - - my $go_forward = 1; - foreach (@admin_conditions) { - if ($phys_admin_status{$admin_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("fan '%s/%s/%s' admin status is %s", - $name, $descr, $instance, $phys_admin_status{$admin_status})); - $go_forward = 0; - last; - } - } - - if ($power > 0) { - $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', - value => $power, - min => 0); - } - - next if ($go_forward == 0); - - foreach (@oper_conditions) { - if ($phys_oper_status{$oper_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("fan '%s/%s/%s' oeprationnal status is %s", - $name, $descr, $instance, $phys_oper_status{$oper_status})); - last; - } - } - } - - foreach my $key (keys %{$self->{results}->{$oids{alaChasEntPhysFanStatus}}}) { - next if ($key !~ /^$oids{alaChasEntPhysFanStatus}\.(.*?)\.(.*?)$/); - my ($phys_index, $loc_index) = ($1, $2); - my $status = $self->{results}->{$oids{alaChasEntPhysFanStatus}}->{$key}; - my $descr = defined($self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $phys_index}) ? - $self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $phys_index} : 'unknown'; - my $name = defined($self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $phys_index}) ? - $self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $phys_index} : 'unknown'; - - next if ($self->check_exclude(section => 'fan', instance => $phys_index . '.' . $loc_index)); - $self->{components}->{fan}->{total}++; - - $self->{output}->output_add(long_msg => sprintf("fan '%s/%s' [instance: %s] status is %s.", - $name, $descr, $loc_index, - $fan_status{$status}) - ); - foreach (@fan_conditions) { - if ($fan_status{$status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("fan '%s/%s/%s' status is %s.", - $name, $descr, $loc_index, - $fan_status{$status}) - ); - last; - } - } - } -} - -1; \ No newline at end of file diff --git a/network/alcatel/common/mode/components/module.pm b/network/alcatel/common/mode/components/module.pm deleted file mode 100644 index 98f982805..000000000 --- a/network/alcatel/common/mode/components/module.pm +++ /dev/null @@ -1,106 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package network::alcatel::common::mode::components::module; - -use strict; -use warnings; -use network::alcatel::common::mode::components::resources qw(%physical_class %phys_oper_status %phys_admin_status %oids); - -my @admin_conditions = ( - ['^(reset|takeover|resetWithFabric|takeoverWithFabrc)$', 'WARNING'], - ['^(powerOff)$', 'CRITICAL'], - ['^(?!(powerOn|standby)$)', 'UNKNOWN'], -); - -my @oper_conditions = ( - ['^(testing)$', 'WARNING'], - ['^(unpowered|down|notpresent)$', 'CRITICAL'], - ['^(?!(up|secondary|master|idle)$)', 'UNKNOWN'], -); - -sub check { - my ($self) = @_; - - $self->{output}->output_add(long_msg => "Checking module"); - $self->{components}->{module} = {name => 'modules', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'module')); - - my @instances = (); - foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { - if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 9) { - next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); - push @instances, $1; - } - } - - foreach my $instance (@instances) { - next if (!defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); - - my $descr = defined($self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance} : 'unknown'; - my $name = defined($self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance} : 'unknown'; - my $admin_status = defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance} : 1; - my $oper_status = defined($self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance} : 4; - my $power = defined($self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance} : -1; - - next if ($self->check_exclude(section => 'module', instance => $instance)); - $self->{components}->{module}->{total}++; - - $self->{output}->output_add(long_msg => sprintf("module '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", - $name, $descr, $instance, - $phys_admin_status{$admin_status}, $phys_oper_status{$oper_status}) - ); - - my $go_forward = 1; - foreach (@admin_conditions) { - if ($phys_admin_status{$admin_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("module '%s/%s/%s' admin status is %s", - $name, $descr, $instance, $phys_admin_status{$admin_status})); - $go_forward = 0; - last; - } - } - - if ($power > 0) { - $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', - value => $power, - min => 0); - } - - next if ($go_forward == 0); - - foreach (@oper_conditions) { - if ($phys_oper_status{$oper_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("module '%s/%s/%s' oeprationnal status is %s", - $name, $descr, $instance, $phys_oper_status{$oper_status})); - last; - } - } - } -} - -1; \ No newline at end of file diff --git a/network/alcatel/common/mode/components/other.pm b/network/alcatel/common/mode/components/other.pm deleted file mode 100644 index fe3cc10ce..000000000 --- a/network/alcatel/common/mode/components/other.pm +++ /dev/null @@ -1,106 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package network::alcatel::common::mode::components::other; - -use strict; -use warnings; -use network::alcatel::common::mode::components::resources qw(%physical_class %phys_oper_status %phys_admin_status %oids); - -my @admin_conditions = ( - ['^(reset|takeover|resetWithFabric|takeoverWithFabrc)$', 'WARNING'], - ['^(powerOff)$', 'CRITICAL'], - ['^(?!(powerOn|standby)$)', 'UNKNOWN'], -); - -my @oper_conditions = ( - ['^(testing)$', 'WARNING'], - ['^(unpowered|down|notpresent)$', 'CRITICAL'], - ['^(?!(up|secondary|master|idle)$)', 'UNKNOWN'], -); - -sub check { - my ($self) = @_; - - $self->{output}->output_add(long_msg => "Checking other"); - $self->{components}->{other} = {name => 'others', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'other')); - - my @instances = (); - foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { - if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 1) { - next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); - push @instances, $1; - } - } - - foreach my $instance (@instances) { - next if (!defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); - - my $descr = defined($self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance} : 'unknown'; - my $name = defined($self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance} : 'unknown'; - my $admin_status = defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance} : 1; - my $oper_status = defined($self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance} : 4; - my $power = defined($self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance} : -1; - - next if ($self->check_exclude(section => 'other', instance => $instance)); - $self->{components}->{other}->{total}++; - - $self->{output}->output_add(long_msg => sprintf("other '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", - $name, $descr, $instance, - $phys_admin_status{$admin_status}, $phys_oper_status{$oper_status}) - ); - - my $go_forward = 1; - foreach (@admin_conditions) { - if ($phys_admin_status{$admin_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("other '%s/%s/%s' admin status is %s", - $name, $descr, $instance, $phys_admin_status{$admin_status})); - $go_forward = 0; - last; - } - } - - if ($power > 0) { - $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', - value => $power, - min => 0); - } - - next if ($go_forward == 0); - - foreach (@oper_conditions) { - if ($phys_oper_status{$oper_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("other '%s/%s/%s' oeprationnal status is %s", - $name, $descr, $instance, $phys_oper_status{$oper_status})); - last; - } - } - } -} - -1; \ No newline at end of file diff --git a/network/alcatel/common/mode/components/port.pm b/network/alcatel/common/mode/components/port.pm deleted file mode 100644 index a3a720b5f..000000000 --- a/network/alcatel/common/mode/components/port.pm +++ /dev/null @@ -1,106 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package network::alcatel::common::mode::components::port; - -use strict; -use warnings; -use network::alcatel::common::mode::components::resources qw(%physical_class %phys_oper_status %phys_admin_status %oids); - -my @admin_conditions = ( - ['^(reset|takeover|resetWithFabric|takeoverWithFabrc)$', 'WARNING'], - ['^(powerOff)$', 'CRITICAL'], - ['^(?!(powerOn|standby)$)', 'UNKNOWN'], -); - -my @oper_conditions = ( - ['^(testing)$', 'WARNING'], - ['^(unpowered|down|notpresent)$', 'CRITICAL'], - ['^(?!(up|secondary|master|idle)$)', 'UNKNOWN'], -); - -sub check { - my ($self) = @_; - - $self->{output}->output_add(long_msg => "Checking port"); - $self->{components}->{port} = {name => 'ports', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'port')); - - my @instances = (); - foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { - if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 10) { - next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); - push @instances, $1; - } - } - - foreach my $instance (@instances) { - next if (!defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); - - my $descr = defined($self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance} : 'unknown'; - my $name = defined($self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance} : 'unknown'; - my $admin_status = defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance} : 1; - my $oper_status = defined($self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance} : 4; - my $power = defined($self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance} : -1; - - next if ($self->check_exclude(section => 'port', instance => $instance)); - $self->{components}->{port}->{total}++; - - $self->{output}->output_add(long_msg => sprintf("port '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", - $name, $descr, $instance, - $phys_admin_status{$admin_status}, $phys_oper_status{$oper_status}) - ); - - my $go_forward = 1; - foreach (@admin_conditions) { - if ($phys_admin_status{$admin_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("port '%s/%s/%s' admin status is %s", - $name, $descr, $instance, $phys_admin_status{$admin_status})); - $go_forward = 0; - last; - } - } - - if ($power > 0) { - $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', - value => $power, - min => 0); - } - - next if ($go_forward == 0); - - foreach (@oper_conditions) { - if ($phys_oper_status{$oper_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("port '%s/%s/%s' oeprationnal status is %s", - $name, $descr, $instance, $phys_oper_status{$oper_status})); - last; - } - } - } -} - -1; \ No newline at end of file diff --git a/network/alcatel/common/mode/components/powersupply.pm b/network/alcatel/common/mode/components/powersupply.pm deleted file mode 100644 index 0a96b523e..000000000 --- a/network/alcatel/common/mode/components/powersupply.pm +++ /dev/null @@ -1,106 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package network::alcatel::common::mode::components::powersupply; - -use strict; -use warnings; -use network::alcatel::common::mode::components::resources qw(%physical_class %phys_oper_status %phys_admin_status %oids); - -my @admin_conditions = ( - ['^(reset|takeover|resetWithFabric|takeoverWithFabrc)$', 'WARNING'], - ['^(powerOff)$', 'CRITICAL'], - ['^(?!(powerOn|standby)$)', 'UNKNOWN'], -); - -my @oper_conditions = ( - ['^(testing)$', 'WARNING'], - ['^(unpowered|down|notpresent)$', 'CRITICAL'], - ['^(?!(up|secondary|master|idle)$)', 'UNKNOWN'], -); - -sub check { - my ($self) = @_; - - $self->{output}->output_add(long_msg => "Checking psu"); - $self->{components}->{psu} = {name => 'power supplies', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'psu')); - - my @instances = (); - foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { - if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 6) { - next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); - push @instances, $1; - } - } - - foreach my $instance (@instances) { - next if (!defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); - - my $descr = defined($self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance} : 'unknown'; - my $name = defined($self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance} : 'unknown'; - my $admin_status = defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance} : 1; - my $oper_status = defined($self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance} : 4; - my $power = defined($self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance} : -1; - - next if ($self->check_exclude(section => 'psu', instance => $instance)); - $self->{components}->{psu}->{total}++; - - $self->{output}->output_add(long_msg => sprintf("power supply '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", - $name, $descr, $instance, - $phys_admin_status{$admin_status}, $phys_oper_status{$oper_status}) - ); - - my $go_forward = 1; - foreach (@admin_conditions) { - if ($phys_admin_status{$admin_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("power supply '%s/%s/%s' admin status is %s", - $name, $descr, $instance, $phys_admin_status{$admin_status})); - $go_forward = 0; - last; - } - } - - if ($power > 0) { - $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', - value => $power, - min => 0); - } - - next if ($go_forward == 0); - - foreach (@oper_conditions) { - if ($phys_oper_status{$oper_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("power supply '%s/%s/%s' operationnal status is %s", - $name, $descr, $instance, $phys_oper_status{$oper_status})); - last; - } - } - } -} - -1; diff --git a/network/alcatel/common/mode/components/sensor.pm b/network/alcatel/common/mode/components/sensor.pm deleted file mode 100644 index 3d7f9c742..000000000 --- a/network/alcatel/common/mode/components/sensor.pm +++ /dev/null @@ -1,106 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package network::alcatel::common::mode::components::sensor; - -use strict; -use warnings; -use network::alcatel::common::mode::components::resources qw(%physical_class %phys_oper_status %phys_admin_status %oids); - -my @admin_conditions = ( - ['^(reset|takeover|resetWithFabric|takeoverWithFabrc)$', 'WARNING'], - ['^(powerOff)$', 'CRITICAL'], - ['^(?!(powerOn|standby)$)', 'UNKNOWN'], -); - -my @oper_conditions = ( - ['^(testing)$', 'WARNING'], - ['^(unpowered|down|notpresent)$', 'CRITICAL'], - ['^(?!(up|secondary|master|idle)$)', 'UNKNOWN'], -); - -sub check { - my ($self) = @_; - - $self->{output}->output_add(long_msg => "Checking sensor"); - $self->{components}->{sensor} = {name => 'sensors', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'sensor')); - - my @instances = (); - foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { - if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 8) { - next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); - push @instances, $1; - } - } - - foreach my $instance (@instances) { - next if (!defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); - - my $descr = defined($self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance} : 'unknown'; - my $name = defined($self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance} : 'unknown'; - my $admin_status = defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance} : 1; - my $oper_status = defined($self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance} : 4; - my $power = defined($self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance} : -1; - - next if ($self->check_exclude(section => 'sensor', instance => $instance)); - $self->{components}->{sensor}->{total}++; - - $self->{output}->output_add(long_msg => sprintf("sensor '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", - $name, $descr, $instance, - $phys_admin_status{$admin_status}, $phys_oper_status{$oper_status}) - ); - - my $go_forward = 1; - foreach (@admin_conditions) { - if ($phys_admin_status{$admin_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("sensor '%s/%s/%s' admin status is %s", - $name, $descr, $instance, $phys_admin_status{$admin_status})); - $go_forward = 0; - last; - } - } - - if ($power > 0) { - $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', - value => $power, - min => 0); - } - - next if ($go_forward == 0); - - foreach (@oper_conditions) { - if ($phys_oper_status{$oper_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("sensor '%s/%s/%s' oeprationnal status is %s", - $name, $descr, $instance, $phys_oper_status{$oper_status})); - last; - } - } - } -} - -1; \ No newline at end of file diff --git a/network/alcatel/common/mode/components/stack.pm b/network/alcatel/common/mode/components/stack.pm deleted file mode 100644 index dee4bafc3..000000000 --- a/network/alcatel/common/mode/components/stack.pm +++ /dev/null @@ -1,106 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package network::alcatel::common::mode::components::stack; - -use strict; -use warnings; -use network::alcatel::common::mode::components::resources qw(%physical_class %phys_oper_status %phys_admin_status %oids); - -my @admin_conditions = ( - ['^(reset|takeover|resetWithFabric|takeoverWithFabrc)$', 'WARNING'], - ['^(powerOff)$', 'CRITICAL'], - ['^(?!(powerOn|standby)$)', 'UNKNOWN'], -); - -my @oper_conditions = ( - ['^(testing)$', 'WARNING'], - ['^(unpowered|down|notpresent)$', 'CRITICAL'], - ['^(?!(up|secondary|master|idle)$)', 'UNKNOWN'], -); - -sub check { - my ($self) = @_; - - $self->{output}->output_add(long_msg => "Checking stack"); - $self->{components}->{stack} = {name => 'stacks', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'stack')); - - my @instances = (); - foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { - if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 11) { - next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); - push @instances, $1; - } - } - - foreach my $instance (@instances) { - next if (!defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); - - my $descr = defined($self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance} : 'unknown'; - my $name = defined($self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance} : 'unknown'; - my $admin_status = defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance} : 1; - my $oper_status = defined($self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance} : 4; - my $power = defined($self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance} : -1; - - next if ($self->check_exclude(section => 'stack', instance => $instance)); - $self->{components}->{stack}->{total}++; - - $self->{output}->output_add(long_msg => sprintf("stack '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", - $name, $descr, $instance, - $phys_admin_status{$admin_status}, $phys_oper_status{$oper_status}) - ); - - my $go_forward = 1; - foreach (@admin_conditions) { - if ($phys_admin_status{$admin_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("stack '%s/%s/%s' admin status is %s", - $name, $descr, $instance, $phys_admin_status{$admin_status})); - $go_forward = 0; - last; - } - } - - if ($power > 0) { - $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', - value => $power, - min => 0); - } - - next if ($go_forward == 0); - - foreach (@oper_conditions) { - if ($phys_oper_status{$oper_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("stack '%s/%s/%s' oeprationnal status is %s", - $name, $descr, $instance, $phys_oper_status{$oper_status})); - last; - } - } - } -} - -1; \ No newline at end of file diff --git a/network/alcatel/common/mode/components/unknown.pm b/network/alcatel/common/mode/components/unknown.pm deleted file mode 100644 index ed4fc7637..000000000 --- a/network/alcatel/common/mode/components/unknown.pm +++ /dev/null @@ -1,106 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package network::alcatel::common::mode::components::unknown; - -use strict; -use warnings; -use network::alcatel::common::mode::components::resources qw(%physical_class %phys_oper_status %phys_admin_status %oids); - -my @admin_conditions = ( - ['^(reset|takeover|resetWithFabric|takeoverWithFabrc)$', 'WARNING'], - ['^(powerOff)$', 'CRITICAL'], - ['^(?!(powerOn|standby)$)', 'UNKNOWN'], -); - -my @oper_conditions = ( - ['^(testing)$', 'WARNING'], - ['^(unpowered|down|notpresent)$', 'CRITICAL'], - ['^(?!(up|secondary|master|idle)$)', 'UNKNOWN'], -); - -sub check { - my ($self) = @_; - - $self->{output}->output_add(long_msg => "Checking unknown"); - $self->{components}->{unknown} = {name => 'unknowns', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'unknown')); - - my @instances = (); - foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { - if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 2) { - next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); - push @instances, $1; - } - } - - foreach my $instance (@instances) { - next if (!defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); - - my $descr = defined($self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $instance} : 'unknown'; - my $name = defined($self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance}) ? - $self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $instance} : 'unknown'; - my $admin_status = defined($self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysAdminStatus}}->{$oids{chasEntPhysAdminStatus} . '.' . $instance} : 1; - my $oper_status = defined($self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysOperStatus}}->{$oids{chasEntPhysOperStatus} . '.' . $instance} : 4; - my $power = defined($self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance}) ? - $self->{results}->{$oids{chasEntPhysPower}}->{$oids{chasEntPhysPower} . '.' . $instance} : -1; - - next if ($self->check_exclude(section => 'unknown', instance => $instance)); - $self->{components}->{unknown}->{total}++; - - $self->{output}->output_add(long_msg => sprintf("unknown '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", - $name, $descr, $instance, - $phys_admin_status{$admin_status}, $phys_oper_status{$oper_status}) - ); - - my $go_forward = 1; - foreach (@admin_conditions) { - if ($phys_admin_status{$admin_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("unknown '%s/%s/%s' admin status is %s", - $name, $descr, $instance, $phys_admin_status{$admin_status})); - $go_forward = 0; - last; - } - } - - if ($power > 0) { - $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', - value => $power, - min => 0); - } - - next if ($go_forward == 0); - - foreach (@oper_conditions) { - if ($phys_oper_status{$oper_status} =~ /$$_[0]/i) { - $self->{output}->output_add(severity => $$_[1], - short_msg => sprintf("unknown '%s/%s/%s' oeprationnal status is %s", - $name, $descr, $instance, $phys_oper_status{$oper_status})); - last; - } - } - } -} - -1; \ No newline at end of file diff --git a/network/alcatel/common/mode/hardware.pm b/network/alcatel/common/mode/hardware.pm deleted file mode 100644 index d531c11e5..000000000 --- a/network/alcatel/common/mode/hardware.pm +++ /dev/null @@ -1,202 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package network::alcatel::common::mode::hardware; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; -use network::alcatel::common::mode::components::resources qw(%oids); -use network::alcatel::common::mode::components::backplane; -use network::alcatel::common::mode::components::chassis; -use network::alcatel::common::mode::components::container; -use network::alcatel::common::mode::components::fan; -use network::alcatel::common::mode::components::module; -use network::alcatel::common::mode::components::other; -use network::alcatel::common::mode::components::port; -use network::alcatel::common::mode::components::powersupply; -use network::alcatel::common::mode::components::sensor; -use network::alcatel::common::mode::components::stack; -use network::alcatel::common::mode::components::unknown; - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $self->{version} = '1.0'; - $options{options}->add_options(arguments => - { - "exclude:s" => { name => 'exclude' }, - "component:s" => { name => 'component', default => 'all' }, - "no-component:s" => { name => 'no_component' }, - }); - - $self->{components} = {}; - $self->{no_components} = undef; - - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - if (defined($self->{option_results}->{no_component})) { - if ($self->{option_results}->{no_component} ne '') { - $self->{no_components} = $self->{option_results}->{no_component}; - } else { - $self->{no_components} = 'critical'; - } - } -} - -sub component { - my ($self, %options) = @_; - - if ($self->{option_results}->{component} eq 'all') { - network::alcatel::common::mode::components::backplane::check($self); - network::alcatel::common::mode::components::chassis::check($self); - network::alcatel::common::mode::components::container::check($self); - network::alcatel::common::mode::components::fan::check($self); - network::alcatel::common::mode::components::module::check($self); - network::alcatel::common::mode::components::other::check($self); - network::alcatel::common::mode::components::port::check($self); - network::alcatel::common::mode::components::powersupply::check($self); - network::alcatel::common::mode::components::sensor::check($self); - network::alcatel::common::mode::components::stack::check($self); - network::alcatel::common::mode::components::unknown::check($self); - } elsif ($self->{option_results}->{component} eq 'backplane') { - network::alcatel::common::mode::components::backplane::check($self); - } elsif ($self->{option_results}->{component} eq 'chassis') { - network::alcatel::common::mode::components::chassis::check($self); - } elsif ($self->{option_results}->{component} eq 'container') { - network::alcatel::common::mode::components::container::check($self); - } elsif ($self->{option_results}->{component} eq 'fan') { - network::alcatel::common::mode::components::fan::check($self); - } elsif ($self->{option_results}->{component} eq 'module') { - network::alcatel::common::mode::components::module::check($self); - } elsif ($self->{option_results}->{component} eq 'other') { - network::alcatel::common::mode::components::other::check($self); - } elsif ($self->{option_results}->{component} eq 'port') { - network::alcatel::common::mode::components::port::check($self); - } elsif ($self->{option_results}->{component} eq 'psu') { - network::alcatel::common::mode::components::powersupply::check($self); - } elsif ($self->{option_results}->{component} eq 'sensor') { - network::alcatel::common::mode::components::sensor::check($self); - } elsif ($self->{option_results}->{component} eq 'stack') { - network::alcatel::common::mode::components::stack::check($self); - } elsif ($self->{option_results}->{component} eq 'unknown') { - network::alcatel::common::mode::components::unknown::check($self); - } else { - $self->{output}->add_option_msg(short_msg => "Wrong option. Cannot find component '" . $self->{option_results}->{component} . "'."); - $self->{output}->option_exit(); - } - - my $total_components = 0; - my $display_by_component = ''; - my $display_by_component_append = ''; - foreach my $comp (sort(keys %{$self->{components}})) { - # Skipping short msg when no components - next if ($self->{components}->{$comp}->{total} == 0 && $self->{components}->{$comp}->{skip} == 0); - $total_components += $self->{components}->{$comp}->{total} + $self->{components}->{$comp}->{skip}; - my $count_by_components = $self->{components}->{$comp}->{total} + $self->{components}->{$comp}->{skip}; - $display_by_component .= $display_by_component_append . $self->{components}->{$comp}->{total} . '/' . $count_by_components . ' ' . $self->{components}->{$comp}->{name}; - $display_by_component_append = ', '; - } - - $self->{output}->output_add(severity => 'OK', - short_msg => sprintf("All %s components [%s] are ok.", - $total_components, - $display_by_component) - ); - - if (defined($self->{option_results}->{no_component}) && $total_components == 0) { - $self->{output}->output_add(severity => $self->{no_components}, - short_msg => 'No components are checked.'); - } -} - -sub run { - my ($self, %options) = @_; - $self->{snmp} = $options{snmp}; - - $self->{results} = $self->{snmp}->get_multiple_table(oids => [ - { oid => $oids{entPhysicalDescr} }, - { oid => $oids{entPhysicalClass} }, - { oid => $oids{entPhysicalName} }, - { oid => $oids{chasEntPhysAdminStatus} }, - { oid => $oids{chasEntPhysOperStatus} }, - { oid => $oids{chasEntPhysPower} }, - { oid => $oids{alaChasEntPhysFanStatus} }, - ]); - $self->component(); - - $self->{output}->display(); - $self->{output}->exit(); -} - -sub check_exclude { - my ($self, %options) = @_; - - if (defined($options{instance})) { - if (defined($self->{option_results}->{exclude}) && $self->{option_results}->{exclude} =~ /(^|\s|,)${options{section}}[^,]*#\Q$options{instance}\E#/) { - $self->{components}->{$options{section}}->{skip}++; - $self->{output}->output_add(long_msg => sprintf("Skipping $options{section} section $options{instance} instance.")); - return 1; - } - } elsif (defined($self->{option_results}->{exclude}) && $self->{option_results}->{exclude} =~ /(^|\s|,)$options{section}(\s|,|$)/) { - $self->{output}->output_add(long_msg => sprintf("Skipping $options{section} section.")); - return 1; - } - return 0; -} - -1; - -__END__ - -=head1 MODE - -Check status of alcatel hardware (AlcatelIND1Chassis.mib). - -=over 8 - -=item B<--component> - -Which component to check (Default: 'all'). -Can be: 'other', 'unknown', 'chassis', 'backplane', 'container', 'psu', 'fan', -'sensor', 'module', 'port, 'stack'. -Some not exists ;) - -=item B<--exclude> - -Exclude some parts (comma seperated list) (Example: --exclude=fan) -Can also exclude specific instance: --exclude=fan#1.2#,module - -=item B<--no-component> - -Return an error if no compenents are checked. -If total (with skipped) is 0. (Default: 'critical' returns). - -=back - -=cut diff --git a/network/alcatel/isam/snmp/mode/components/cardtemperature.pm b/network/alcatel/isam/snmp/mode/components/cardtemperature.pm new file mode 100644 index 000000000..feda91d07 --- /dev/null +++ b/network/alcatel/isam/snmp/mode/components/cardtemperature.pm @@ -0,0 +1,71 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::isam::snmp::mode::components::cardtemperature; + +use strict; +use warnings; +use network::alcatel::isam::snmp::mode::components::resources qw($mapping_slot); + +my $oid_eqptBoardThermalSensorActualTemperature = '.1.3.6.1.4.1.637.61.1.23.10.1.2'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_eqptBoardThermalSensorActualTemperature }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking card temperatures"); + $self->{components}->{cardtemperature} = {name => 'card temperatures', total => 0, skip => 0}; + return if ($self->check_filter(section => 'cardtemperature')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_eqptBoardThermalSensorActualTemperature}})) { + $oid =~ /^$oid_eqptBoardThermalSensorActualTemperature\.(.*?)\.(.*?)$/; + my ($slot_id, $thermal_id) = ($1, $2); + + my $temperature = $self->{results}->{$oid_eqptBoardThermalSensorActualTemperature}->{$oid}; + my $result = $self->{snmp}->map_instance(mapping => $mapping_slot, results => + { %{$self->{results}->{$mapping_slot->{eqptSlotActualType}->{oid}}}, %{$self->{results}->{$mapping_slot->{eqptBoardInventorySerialNumber}->{oid}}} }, instance => $slot_id); + + next if ($self->check_filter(section => 'cardtemperature', instance => $slot_id . '.' . $thermal_id)); + + my $name = $result->{eqptSlotActualType} . '/' . $result->{eqptBoardInventorySerialNumber} . '/' . $thermal_id; + $self->{components}->{cardtemperature}->{total}++; + $self->{output}->output_add(long_msg => sprintf("card '%s' temperature is %s C [instance = %s]", + $name, $temperature, $slot_id . '.' . $thermal_id)); + + my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'cardtemperature', instance => $slot_id . '.' . $thermal_id, value => $temperature); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Card '%s' temperature is %s C", $name, $temperature)); + } + $self->{output}->perfdata_add(label => 'cardtemperature_' . $name, + unit => 'C', + value => $temperature, + warning => $warn, + critical => $crit + ); + } +} + +1; \ No newline at end of file diff --git a/network/alcatel/isam/snmp/mode/components/resources.pm b/network/alcatel/isam/snmp/mode/components/resources.pm new file mode 100644 index 000000000..bcf5b478c --- /dev/null +++ b/network/alcatel/isam/snmp/mode/components/resources.pm @@ -0,0 +1,37 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::isam::snmp::mode::components::resources; + +use strict; +use warnings; +use Exporter; + +our $mapping_slot; + +our @ISA = qw(Exporter); +our @EXPORT_OK = qw($mapping_slot); + +$mapping_slot = { + eqptSlotActualType => { oid => '.1.3.6.1.4.1.637.61.1.23.3.1.3' }, + eqptBoardInventorySerialNumber => { oid => '.1.3.6.1.4.1.637.61.1.23.3.1.19' }, +}; + +1; \ No newline at end of file diff --git a/network/alcatel/isam/snmp/mode/components/sfp.pm b/network/alcatel/isam/snmp/mode/components/sfp.pm new file mode 100644 index 000000000..d73020bb9 --- /dev/null +++ b/network/alcatel/isam/snmp/mode/components/sfp.pm @@ -0,0 +1,157 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::isam::snmp::mode::components::sfp; + +use strict; +use warnings; +use network::alcatel::isam::snmp::mode::components::resources qw($mapping_slot); + +my %map_los = (1 => 'los', 2 => 'noLos', 3 => 'notAvailable'); + +my $mapping = { + sfpDiagLOS => { oid => '.1.3.6.1.4.1.637.61.1.56.5.1.4', map => \%map_los }, + sfpDiagTxPower => { oid => '.1.3.6.1.4.1.637.61.1.56.5.1.6' }, + sfpDiagRxPower => { oid => '.1.3.6.1.4.1.637.61.1.56.5.1.7' }, + sfpDiagTxBiasCurrent => { oid => '.1.3.6.1.4.1.637.61.1.56.5.1.8' }, + sfpDiagSupplyVoltage => { oid => '.1.3.6.1.4.1.637.61.1.56.5.1.9' }, + sfpDiagTemperature => { oid => '.1.3.6.1.4.1.637.61.1.56.5.1.10' }, +}; +my $oid_sfpDiagEntry = '.1.3.6.1.4.1.637.61.1.56.5.1'; + +sub load { + my ($self) = @_; + + foreach (keys %$mapping) { + push @{$self->{request}}, { oid => $mapping->{$_}->{oid} }; + } +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking sfp"); + $self->{components}->{sfp} = {name => 'sfp', total => 0, skip => 0}; + return if ($self->check_filter(section => 'sfp')); + + my $results = {}; + foreach (keys %$mapping) { + $results = { %$results, %{$self->{results}->{$mapping->{$_}->{oid}}} }; + } + + my ($exit, $warn, $crit, $checked); + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{sfpDiagLOS}->{oid}}})) { + $oid =~ /^$mapping->{sfpDiagLOS}->{oid}\.(.*?)\.(.*?)$/; + my ($slot_id, $sfp_faceplate_num) = ($1, $2); + + my $result = $self->{snmp}->map_instance(mapping => $mapping_slot, results => + { %{$self->{results}->{$mapping_slot->{eqptSlotActualType}->{oid}}}, %{$self->{results}->{$mapping_slot->{eqptBoardInventorySerialNumber}->{oid}}} }, instance => $slot_id); + my $result2 = $self->{snmp}->map_instance(mapping => $mapping, results => $results, instance => $slot_id . '.' . $sfp_faceplate_num); + + next if ($self->check_filter(section => 'sfp', instance => $slot_id . '.' . $sfp_faceplate_num)); + + my $name = $result->{eqptSlotActualType} . '/' . $result->{eqptBoardInventorySerialNumber} . '/' . $sfp_faceplate_num; + $self->{components}->{sfp}->{total}++; + $self->{output}->output_add(long_msg => sprintf("sfp '%s' signal status is '%s' [instance = %s]", + $name, $result2->{sfpDiagLOS}, $slot_id . '.' . $sfp_faceplate_num)); + $exit = $self->get_severity(section => 'sfp', value => $result2->{sfpDiagLOS}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("sfp '%s' signal status is '%s'", $name, $result2->{sfpDiagLOS})); + } + + if ($result2->{sfpDiagSupplyVoltage} =~ /(\S+)\s+VDC/i) { + my $value = $1; + ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'sfp.voltage', instance => $slot_id . '.' . $sfp_faceplate_num, value => $value); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Sfp '%s' voltage is %s VDC", $name, $value)); + } + $self->{output}->perfdata_add(label => 'sfp_voltage_' . $name, + unit => 'VDC', + value => $value, + warning => $warn, + critical => $crit + ); + } + + if ($result2->{sfpDiagTemperature} =~ /(\S+)\s+degrees Celsius/i) { + my $value = $1; + ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'sfp.temperature', instance => $slot_id . '.' . $sfp_faceplate_num, value => $value); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Sfp '%s' temperature is %s C", $name, $value)); + } + $self->{output}->perfdata_add(label => 'sfp_temperature_' . $name, + unit => 'C', + value => $value, + warning => $warn, + critical => $crit + ); + } + + if ($result2->{sfpDiagTxPower} =~ /(\S+)\s+dBm/i) { + my $value = $1; + ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'sfp.txpower', instance => $slot_id . '.' . $sfp_faceplate_num, value => $value); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Sfp '%s' tx power is %s dBm", $name, $value)); + } + $self->{output}->perfdata_add(label => 'sfp_txpower_' . $name, + unit => 'dBm', + value => $value, + warning => $warn, + critical => $crit + ); + } + + if ($result2->{sfpDiagRxPower} =~ /(\S+)\s+dBm/i) { + my $value = $1; + ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'sfp.rxpower', instance => $slot_id . '.' . $sfp_faceplate_num, value => $value); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Sfp '%s' rx power is %s dBm", $name, $value)); + } + $self->{output}->perfdata_add(label => 'sfp_rxpower_' . $name, + unit => 'dBm', + value => $value, + warning => $warn, + critical => $crit + ); + } + + if ($result2->{sfpDiagTxBiasCurrent} =~ /(\S+)\s+mA/i) { + my $value = $1; + ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'sfp.current', instance => $slot_id . '.' . $sfp_faceplate_num, value => $value); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Sfp '%s' current is %s mA", $name, $value)); + } + $self->{output}->perfdata_add(label => 'sfp_current_' . $name, + unit => 'mA', + value => $value, + warning => $warn, + critical => $crit + ); + } + } +} + +1; \ No newline at end of file diff --git a/network/alcatel/isam/snmp/mode/cpu.pm b/network/alcatel/isam/snmp/mode/cpu.pm new file mode 100644 index 000000000..4dbd8962c --- /dev/null +++ b/network/alcatel/isam/snmp/mode/cpu.pm @@ -0,0 +1,113 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::isam::snmp::mode::cpu; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'cpu', type => 1, cb_prefix_output => 'prefix_cpu_output', message_multiple => 'All CPU usages are ok' } + ]; + + $self->{maps_counters}->{cpu} = [ + { label => 'usage', set => { + key_values => [ { name => 'usage' }, { name => 'display' }, ], + output_template => 'Usage : %.2f %%', + perfdatas => [ + { label => 'cpu', value => 'usage_absolute', template => '%.2f', + min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub prefix_cpu_output { + my ($self, %options) = @_; + + return "CPU '" . $options{instance_value}->{display} . "' "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +my $mapping = { + cpuLoadAverage => { oid => '.1.3.6.1.4.1.637.61.1.9.29.1.1.4' }, + eqptSlotActualType => { oid => '.1.3.6.1.4.1.637.61.1.23.3.1.3' }, + eqptBoardInventorySerialNumber => { oid => '.1.3.6.1.4.1.637.61.1.23.3.1.19' }, +}; + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $options{snmp}->get_multiple_table(oids => [ + { oid => $mapping->{cpuLoadAverage}->{oid} }, + { oid => $mapping->{eqptSlotActualType}->{oid} }, + { oid => $mapping->{eqptBoardInventorySerialNumber}->{oid} }, + ], return_type => 1, nothing_quit => 1); + + $self->{cpu} = {}; + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{cpuLoadAverage}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + my $name = $result->{eqptBoardInventorySerialNumber} . '_' . $result->{eqptSlotActualType}; + $self->{cpu}->{$instance} = { display => $name, usage => $result->{cpuLoadAverage} }; + } +} + +1; + +__END__ + +=head1 MODE + +Check CPU usages. + +=over 8 + +=item B<--warning-usage> + +Threshold warning. + +=item B<--critical-usage> + +Threshold critical. + +=back + +=cut diff --git a/network/alcatel/isam/snmp/mode/hardware.pm b/network/alcatel/isam/snmp/mode/hardware.pm new file mode 100644 index 000000000..0d13abdf0 --- /dev/null +++ b/network/alcatel/isam/snmp/mode/hardware.pm @@ -0,0 +1,114 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::isam::snmp::mode::hardware; + +use base qw(centreon::plugins::templates::hardware); + +use strict; +use warnings; + +sub set_system { + my ($self, %options) = @_; + + $self->{regexp_threshold_overload_check_section_option} = '^(cardtemperature|sfp)$'; + $self->{regexp_threshold_numeric_check_section_option} = '^(cardtemperature|sfp\.(temperature|voltage|current|txpower|rxpower))$'; + + $self->{cb_hook2} = 'snmp_execute'; + + $self->{thresholds} = { + sfp => [ + ['noLos', 'OK'], + ['notAvailable', 'OK'], + ['los', 'WARNING'], + ], + }; + + $self->{components_path} = 'network::alcatel::isam::snmp::mode::components'; + $self->{components_module} = ['cardtemperature', 'sfp']; +} + +sub snmp_execute { + my ($self, %options) = @_; + + $self->{snmp} = $options{snmp}; + my $oid_eqptSlotActualType = '.1.3.6.1.4.1.637.61.1.23.3.1.3'; + my $oid_eqptBoardInventorySerialNumber = '.1.3.6.1.4.1.637.61.1.23.3.1.19'; + push @{$self->{request}}, { oid => $oid_eqptSlotActualType }, { oid => $oid_eqptBoardInventorySerialNumber }; + $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +1; + +__END__ + +=head1 MODE + +Check Hardware. + +=over 8 + +=item B<--component> + +Which component to check (Default: '.*'). +Can be: 'cardtemperature', 'sfp'. + +=item B<--filter> + +Exclude some parts (comma seperated list) (Example: --filter=cardtemperature) +Can also exclude specific instance: --filter=cardtemperature,1080.1 + +=item B<--no-component> + +Return an error if no compenents are checked. +If total (with skipped) is 0. (Default: 'critical' returns). + +=item B<--threshold-overload> + +Set to overload default threshold values (syntax: section,[instance,]status,regexp) +It used before default thresholds (order stays). +Example: --threshold-overload='psu,CRITICAL,^(?!(presentOK)$)' + +=item B<--warning> + +Set warning threshold for 'sfp.temperature', 'cardtemperature' (syntax: type,regexp,threshold) +Example: --warning='sfp.temperature,1.1,30' + +=item B<--critical> + +Set critical threshold for 'sfp.temperature', 'cardtemperature' (syntax: type,regexp,threshold) +Example: --warning='sfp.temperature,1.1,40' + +=back + +=cut \ No newline at end of file diff --git a/network/alcatel/isam/snmp/mode/memory.pm b/network/alcatel/isam/snmp/mode/memory.pm new file mode 100644 index 000000000..33fc94aac --- /dev/null +++ b/network/alcatel/isam/snmp/mode/memory.pm @@ -0,0 +1,230 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::isam::snmp::mode::memory; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $instance_mode; + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $label = 'used'; + my $value_perf = $self->{result_values}->{used}; + if (defined($instance_mode->{option_results}->{free})) { + $label = 'free'; + $value_perf = $self->{result_values}->{free}; + } + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + my %total_options = (); + if ($instance_mode->{option_results}->{units} eq '%') { + $total_options{total} = $self->{result_values}->{total}; + $total_options{cast_int} = 1; + } + + $self->{output}->perfdata_add(label => $label . $extra_label, unit => 'B', + value => $value_perf, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_usage_threshold { + my ($self, %options) = @_; + + my ($exit, $threshold_value); + $threshold_value = $self->{result_values}->{used}; + $threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free})); + if ($instance_mode->{option_results}->{units} eq '%') { + $threshold_value = $self->{result_values}->{prct_used}; + $threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free})); + } + $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + my $msg = sprintf("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}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'memory', type => 1, cb_prefix_output => 'prefix_memory_output', message_multiple => 'All memories are ok' }, + ]; + + $self->{maps_counters}->{memory} = [ + { label => 'usage', set => { + key_values => [ { name => 'display' }, { name => 'used' }, { name => 'total' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "units:s" => { name => 'units', default => '%' }, + "free" => { name => 'free' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +sub prefix_memory_output { + my ($self, %options) = @_; + + return "Memory '" . $options{instance_value}->{display} . "' "; +} + +my $mapping = { + totalMemSize => { oid => '.1.3.6.1.4.1.637.61.1.9.29.2.1.1' }, + memAbsoluteUsage => { oid => '.1.3.6.1.4.1.637.61.1.9.29.2.1.2' }, + eqptSlotActualType => { oid => '.1.3.6.1.4.1.637.61.1.23.3.1.3' }, + eqptBoardInventorySerialNumber => { oid => '.1.3.6.1.4.1.637.61.1.23.3.1.19' }, +}; + +my $oid_asamSwmTotalSpaceOnFileDisk = '.1.3.6.1.4.1.637.61.1.24.1.6.0'; +my $oid_asamSwmFreeSpaceOnFileDisk = '.1.3.6.1.4.1.637.61.1.24.1.7.0'; + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $options{snmp}->get_multiple_table(oids => [ + { oid => $mapping->{totalMemSize}->{oid} }, + { oid => $mapping->{memAbsoluteUsage}->{oid} }, + { oid => $mapping->{eqptSlotActualType}->{oid} }, + { oid => $mapping->{eqptBoardInventorySerialNumber}->{oid} }, + ], return_type => 1, nothing_quit => 1); + + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{memAbsoluteUsage}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + my $name = $result->{eqptBoardInventorySerialNumber} . '_' . $result->{eqptSlotActualType}; + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $name !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); + next; + } + $self->{memory}->{$name} = { display => $name, total => $result->{totalMemSize} * 1024 * 1024, used => $result->{memAbsoluteUsage} * 1024 * 1024 }; + } + + $snmp_result = $options{snmp}->get_leef(oids => [$oid_asamSwmTotalSpaceOnFileDisk, $oid_asamSwmFreeSpaceOnFileDisk]); + if (defined($snmp_result->{$oid_asamSwmFreeSpaceOnFileDisk})) { + my $name = 'SD Card'; + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $name !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); + } else { + $self->{memory}->{$name} = { display => $name, total => $snmp_result->{$oid_asamSwmTotalSpaceOnFileDisk}, + used => $snmp_result->{$oid_asamSwmTotalSpaceOnFileDisk} - $snmp_result->{$oid_asamSwmFreeSpaceOnFileDisk} }; + } + } + + if (scalar(keys %{$self->{memory}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No memory found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check memory usages. + +=over 8 + +=item B<--filter-name> + +Filter memory name (can be a regexp). + +=item B<--filter-project> + +Filter project name (can be a regexp). + +=item B<--warning-usage> + +Threshold warning. + +=item B<--critical-usage> + +Threshold critical. + +=item B<--units> + +Units of thresholds (Default: '%') ('%', 'B'). + +=item B<--free> + +Thresholds are on free space left. + +=back + +=cut diff --git a/network/alcatel/isam/snmp/plugin.pm b/network/alcatel/isam/snmp/plugin.pm index 08d469401..c066bb53e 100644 --- a/network/alcatel/isam/snmp/plugin.pm +++ b/network/alcatel/isam/snmp/plugin.pm @@ -31,7 +31,12 @@ sub new { $self->{version} = '1.0'; %{$self->{modes}} = ( - 'vlan-traffic' => 'network::alcatel::isam::snmp::mode::vlantraffic', + 'cpu' => 'network::alcatel::isam::snmp::mode::cpu', + 'hardware' => 'network::alcatel::isam::snmp::mode::hardware', + 'interfaces' => 'snmp_standard::mode::interfaces', + 'list-interfaces' => 'snmp_standard::mode::listinterfaces', + 'memory' => 'network::alcatel::isam::snmp::mode::memory', + 'vlan-traffic' => 'network::alcatel::isam::snmp::mode::vlantraffic', ); return $self; diff --git a/network/alcatel/omniswitch/snmp/mode/components/backplane.pm b/network/alcatel/omniswitch/snmp/mode/components/backplane.pm new file mode 100644 index 000000000..4d167a861 --- /dev/null +++ b/network/alcatel/omniswitch/snmp/mode/components/backplane.pm @@ -0,0 +1,82 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::omniswitch::snmp::mode::components::backplane; + +use strict; +use warnings; +use network::alcatel::omniswitch::snmp::mode::components::resources qw(%oids $mapping); + +sub load {} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking backplane"); + $self->{components}->{backplane} = {name => 'backplanes', total => 0, skip => 0}; + return if ($self->check_filter(section => 'backplane')); + + my @instances = (); + foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { + if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 4) { + next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); + push @instances, $1; + } + } + + foreach my $instance (@instances) { + next if (!defined($self->{results}->{entity}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); + + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{entity}, instance => $instance); + + next if ($self->check_filter(section => 'backplane', instance => $instance)); + $self->{components}->{backplane}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("backplane '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus}, $result->{chasEntPhysOperStatus}) + ); + + if ($result->{chasEntPhysPower} > 0) { + $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', + value => $result->{chasEntPhysPower}, + min => 0); + } + + my $exit = $self->get_severity(label => 'admin', section => 'backplane.admin', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("backplane '%s/%s/%s' admin status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus})); + next; + } + + $exit = $self->get_severity(label => 'oper', section => 'backplane.oper', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("backplane '%s/%s/%s' operational status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysOperStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/network/alcatel/omniswitch/snmp/mode/components/chassis.pm b/network/alcatel/omniswitch/snmp/mode/components/chassis.pm new file mode 100644 index 000000000..2918e5867 --- /dev/null +++ b/network/alcatel/omniswitch/snmp/mode/components/chassis.pm @@ -0,0 +1,82 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::omniswitch::snmp::mode::components::chassis; + +use strict; +use warnings; +use network::alcatel::omniswitch::snmp::mode::components::resources qw(%oids $mapping); + +sub load {} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking chassis"); + $self->{components}->{chassis} = {name => 'chassis', total => 0, skip => 0}; + return if ($self->check_filter(section => 'chassis')); + + my @instances = (); + foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { + if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 3) { + next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); + push @instances, $1; + } + } + + foreach my $instance (@instances) { + next if (!defined($self->{results}->{entity}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); + + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{entity}, instance => $instance); + + next if ($self->check_filter(section => 'chassis', instance => $instance)); + $self->{components}->{chassis}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("chassis '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus}, $result->{chasEntPhysOperStatus}) + ); + + if ($result->{chasEntPhysPower} > 0) { + $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', + value => $result->{chasEntPhysPower}, + min => 0); + } + + my $exit = $self->get_severity(label => 'admin', section => 'chassis.admin', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("chassis '%s/%s/%s' admin status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus})); + next; + } + + $exit = $self->get_severity(label => 'oper', section => 'chassis.oper', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("chassis '%s/%s/%s' operational status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysOperStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/network/alcatel/omniswitch/snmp/mode/components/container.pm b/network/alcatel/omniswitch/snmp/mode/components/container.pm new file mode 100644 index 000000000..883b6a749 --- /dev/null +++ b/network/alcatel/omniswitch/snmp/mode/components/container.pm @@ -0,0 +1,82 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::omniswitch::snmp::mode::components::container; + +use strict; +use warnings; +use network::alcatel::omniswitch::snmp::mode::components::resources qw(%oids $mapping); + +sub load {} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking container"); + $self->{components}->{container} = {name => 'containers', total => 0, skip => 0}; + return if ($self->check_filter(section => 'container')); + + my @instances = (); + foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { + if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 5) { + next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); + push @instances, $1; + } + } + + foreach my $instance (@instances) { + next if (!defined($self->{results}->{entity}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); + + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{entity}, instance => $instance); + + next if ($self->check_filter(section => 'container', instance => $instance)); + $self->{components}->{container}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("container '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus}, $result->{chasEntPhysOperStatus}) + ); + + if ($result->{chasEntPhysPower} > 0) { + $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', + value => $result->{chasEntPhysPower}, + min => 0); + } + + my $exit = $self->get_severity(label => 'admin', section => 'container.admin', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("container '%s/%s/%s' admin status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus})); + next; + } + + $exit = $self->get_severity(label => 'oper', section => 'container.oper', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("container '%s/%s/%s' operational status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysOperStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/network/alcatel/omniswitch/snmp/mode/components/fan.pm b/network/alcatel/omniswitch/snmp/mode/components/fan.pm new file mode 100644 index 000000000..e575a5668 --- /dev/null +++ b/network/alcatel/omniswitch/snmp/mode/components/fan.pm @@ -0,0 +1,113 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::omniswitch::snmp::mode::components::fan; + +use strict; +use warnings; +use network::alcatel::omniswitch::snmp::mode::components::resources qw(%oids $mapping); + +my %fan_status = ( + 0 => 'noStatus', + 1 => 'notRunning', + 2 => 'running', +); + +sub load {} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking fan"); + $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; + return if ($self->check_filter(section => 'fan')); + + my @instances = (); + foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { + if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 7) { + next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); + push @instances, $1; + } + } + + foreach my $instance (@instances) { + next if (!defined($self->{results}->{entity}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); + + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{entity}, instance => $instance); + + next if ($self->check_filter(section => 'fan', instance => $instance)); + $self->{components}->{fan}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("fan '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus}, $result->{chasEntPhysOperStatus}) + ); + + if ($result->{chasEntPhysPower} > 0) { + $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', + value => $result->{chasEntPhysPower}, + min => 0); + } + + my $exit = $self->get_severity(label => 'admin', section => 'fan.admin', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("fan '%s/%s/%s' admin status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus})); + next; + } + + $exit = $self->get_severity(label => 'oper', section => 'fan.oper', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("fan '%s/%s/%s' operational status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysOperStatus})); + } + } + + foreach my $key (keys %{$self->{results}->{$oids{alaChasEntPhysFanStatus}}}) { + next if ($key !~ /^$oids{alaChasEntPhysFanStatus}\.(.*?)\.(.*?)$/); + my ($phys_index, $loc_index) = ($1, $2); + my $status = $self->{results}->{$oids{alaChasEntPhysFanStatus}}->{$key}; + my $descr = defined($self->{results}->{entity}->{$oids{entPhysicalDescr} . '.' . $phys_index}) ? + $self->{results}->{$oids{entPhysicalDescr}}->{$oids{entPhysicalDescr} . '.' . $phys_index} : 'unknown'; + my $name = defined($self->{results}->{entity}->{$oids{entPhysicalName} . '.' . $phys_index}) ? + $self->{results}->{$oids{entPhysicalName}}->{$oids{entPhysicalName} . '.' . $phys_index} : 'unknown'; + + next if ($self->check_filter(section => 'fan', instance => $phys_index . '.' . $loc_index)); + $self->{components}->{fan}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("fan '%s/%s' [instance: %s] status is %s", + $name, $descr, $phys_index . '.' . $loc_index, + $fan_status{$status}) + ); + my $exit = $self->get_severity(label => 'fan', section => 'fan.status', value => $fan_status{$status}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("fan '%s/%s/%s' status is %s", + $name, $descr, $phys_index . '.' . $loc_index, + $fan_status{$status})); + } + } +} + +1; \ No newline at end of file diff --git a/network/alcatel/omniswitch/snmp/mode/components/module.pm b/network/alcatel/omniswitch/snmp/mode/components/module.pm new file mode 100644 index 000000000..ff631571c --- /dev/null +++ b/network/alcatel/omniswitch/snmp/mode/components/module.pm @@ -0,0 +1,82 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::omniswitch::snmp::mode::components::module; + +use strict; +use warnings; +use network::alcatel::omniswitch::snmp::mode::components::resources qw(%oids $mapping); + +sub load {} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking module"); + $self->{components}->{module} = {name => 'modules', total => 0, skip => 0}; + return if ($self->check_filter(section => 'module')); + + my @instances = (); + foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { + if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 9) { + next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); + push @instances, $1; + } + } + + foreach my $instance (@instances) { + next if (!defined($self->{results}->{entity}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); + + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{entity}, instance => $instance); + + next if ($self->check_filter(section => 'module', instance => $instance)); + $self->{components}->{module}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("module '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus}, $result->{chasEntPhysOperStatus}) + ); + + if ($result->{chasEntPhysPower} > 0) { + $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', + value => $result->{chasEntPhysPower}, + min => 0); + } + + my $exit = $self->get_severity(label => 'admin', section => 'module.admin', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("module '%s/%s/%s' admin status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus})); + next; + } + + $exit = $self->get_severity(label => 'oper', section => 'module.oper', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("module '%s/%s/%s' operational status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysOperStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/network/alcatel/omniswitch/snmp/mode/components/other.pm b/network/alcatel/omniswitch/snmp/mode/components/other.pm new file mode 100644 index 000000000..cdb704a9d --- /dev/null +++ b/network/alcatel/omniswitch/snmp/mode/components/other.pm @@ -0,0 +1,82 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::omniswitch::snmp::mode::components::other; + +use strict; +use warnings; +use network::alcatel::omniswitch::snmp::mode::components::resources qw(%oids $mapping); + +sub load {} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking other"); + $self->{components}->{other} = {name => 'others', total => 0, skip => 0}; + return if ($self->check_filter(section => 'other')); + + my @instances = (); + foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { + if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 1) { + next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); + push @instances, $1; + } + } + + foreach my $instance (@instances) { + next if (!defined($self->{results}->{entity}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); + + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{entity}, instance => $instance); + + next if ($self->check_filter(section => 'other', instance => $instance)); + $self->{components}->{other}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("other '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus}, $result->{chasEntPhysOperStatus}) + ); + + if ($result->{chasEntPhysPower} > 0) { + $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', + value => $result->{chasEntPhysPower}, + min => 0); + } + + my $exit = $self->get_severity(label => 'admin', section => 'other.admin', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("other '%s/%s/%s' admin status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus})); + next; + } + + $exit = $self->get_severity(label => 'oper', section => 'other.oper', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("other '%s/%s/%s' operational status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysOperStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/network/alcatel/omniswitch/snmp/mode/components/port.pm b/network/alcatel/omniswitch/snmp/mode/components/port.pm new file mode 100644 index 000000000..d8ad20bc3 --- /dev/null +++ b/network/alcatel/omniswitch/snmp/mode/components/port.pm @@ -0,0 +1,82 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::omniswitch::snmp::mode::components::port; + +use strict; +use warnings; +use network::alcatel::omniswitch::snmp::mode::components::resources qw(%oids $mapping); + +sub load {} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking port"); + $self->{components}->{port} = {name => 'ports', total => 0, skip => 0}; + return if ($self->check_filter(section => 'port')); + + my @instances = (); + foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { + if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 10) { + next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); + push @instances, $1; + } + } + + foreach my $instance (@instances) { + next if (!defined($self->{results}->{entity}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); + + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{entity}, instance => $instance); + + next if ($self->check_filter(section => 'port', instance => $instance)); + $self->{components}->{port}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("port '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus}, $result->{chasEntPhysOperStatus}) + ); + + if ($result->{chasEntPhysPower} > 0) { + $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', + value => $result->{chasEntPhysPower}, + min => 0); + } + + my $exit = $self->get_severity(label => 'admin', section => 'port.admin', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("port '%s/%s/%s' admin status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus})); + next; + } + + $exit = $self->get_severity(label => 'oper', section => 'port.oper', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("port '%s/%s/%s' operational status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysOperStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/network/alcatel/omniswitch/snmp/mode/components/psu.pm b/network/alcatel/omniswitch/snmp/mode/components/psu.pm new file mode 100644 index 000000000..04921e1fa --- /dev/null +++ b/network/alcatel/omniswitch/snmp/mode/components/psu.pm @@ -0,0 +1,82 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::omniswitch::snmp::mode::components::psu; + +use strict; +use warnings; +use network::alcatel::omniswitch::snmp::mode::components::resources qw(%oids $mapping); + +sub load {} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking power supplies"); + $self->{components}->{psu} = {name => 'psus', total => 0, skip => 0}; + return if ($self->check_filter(section => 'psu')); + + my @instances = (); + foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { + if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 6) { + next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); + push @instances, $1; + } + } + + foreach my $instance (@instances) { + next if (!defined($self->{results}->{entity}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); + + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{entity}, instance => $instance); + + next if ($self->check_filter(section => 'psu', instance => $instance)); + $self->{components}->{psu}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("power supply '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus}, $result->{chasEntPhysOperStatus}) + ); + + if ($result->{chasEntPhysPower} > 0) { + $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', + value => $result->{chasEntPhysPower}, + min => 0); + } + + my $exit = $self->get_severity(label => 'admin', section => 'psu.admin', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("power supply '%s/%s/%s' admin status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus})); + next; + } + + $exit = $self->get_severity(label => 'oper', section => 'psu.oper', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("power supply '%s/%s/%s' operational status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysOperStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/network/alcatel/common/mode/components/resources.pm b/network/alcatel/omniswitch/snmp/mode/components/resources.pm similarity index 80% rename from network/alcatel/common/mode/components/resources.pm rename to network/alcatel/omniswitch/snmp/mode/components/resources.pm index 58b41aaea..cbd15b15a 100644 --- a/network/alcatel/common/mode/components/resources.pm +++ b/network/alcatel/omniswitch/snmp/mode/components/resources.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::alcatel::common::mode::components::resources; +package network::alcatel::omniswitch::snmp::mode::components::resources; use strict; use warnings; @@ -28,9 +28,10 @@ our %physical_class; our %phys_oper_status; our %phys_admin_status; our %oids; +our $mapping; our @ISA = qw(Exporter); -our @EXPORT_OK = qw(%physical_class %phys_oper_status %phys_admin_status %oids); +our @EXPORT_OK = qw(%physical_class %phys_oper_status %phys_admin_status %oids $mapping); %physical_class = ( 1 => 'other', @@ -86,4 +87,12 @@ our @EXPORT_OK = qw(%physical_class %phys_oper_status %phys_admin_status %oids); alaChasEntPhysFanStatus => '.1.3.6.1.4.1.6486.800.1.1.1.3.1.1.11.1.2', ); +$mapping = { + entPhysicalDescr => { oid => $oids{entPhysicalDescr} }, + entPhysicalName => { oid => $oids{entPhysicalName} }, + chasEntPhysAdminStatus => { oid => $oids{chasEntPhysAdminStatus}, map => \%phys_admin_status, default => 'unknown' }, + chasEntPhysOperStatus => { oid => $oids{chasEntPhysOperStatus}, map => \%phys_oper_status, default => 'unknown' }, + chasEntPhysPower => { oid => $oids{chasEntPhysPower}, default => -1 }, +}; + 1; \ No newline at end of file diff --git a/network/alcatel/omniswitch/snmp/mode/components/sensor.pm b/network/alcatel/omniswitch/snmp/mode/components/sensor.pm new file mode 100644 index 000000000..5a6a1f5f2 --- /dev/null +++ b/network/alcatel/omniswitch/snmp/mode/components/sensor.pm @@ -0,0 +1,82 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::omniswitch::snmp::mode::components::sensor; + +use strict; +use warnings; +use network::alcatel::omniswitch::snmp::mode::components::resources qw(%oids $mapping); + +sub load {} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking sensors"); + $self->{components}->{sensor} = {name => 'sensors', total => 0, skip => 0}; + return if ($self->check_filter(section => 'sensor')); + + my @instances = (); + foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { + if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 8) { + next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); + push @instances, $1; + } + } + + foreach my $instance (@instances) { + next if (!defined($self->{results}->{entity}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); + + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{entity}, instance => $instance); + + next if ($self->check_filter(section => 'sensor', instance => $instance)); + $self->{components}->{sensor}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("sensor '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus}, $result->{chasEntPhysOperStatus}) + ); + + if ($result->{chasEntPhysPower} > 0) { + $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', + value => $result->{chasEntPhysPower}, + min => 0); + } + + my $exit = $self->get_severity(label => 'admin', section => 'sensor.admin', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("sensor '%s/%s/%s' admin status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus})); + next; + } + + $exit = $self->get_severity(label => 'oper', section => 'sensor.oper', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("sensor '%s/%s/%s' operational status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysOperStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/network/alcatel/omniswitch/snmp/mode/components/stack.pm b/network/alcatel/omniswitch/snmp/mode/components/stack.pm new file mode 100644 index 000000000..5b24ec8d6 --- /dev/null +++ b/network/alcatel/omniswitch/snmp/mode/components/stack.pm @@ -0,0 +1,82 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::omniswitch::snmp::mode::components::stack; + +use strict; +use warnings; +use network::alcatel::omniswitch::snmp::mode::components::resources qw(%oids $mapping); + +sub load {} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking stack"); + $self->{components}->{stack} = {name => 'stacks', total => 0, skip => 0}; + return if ($self->check_filter(section => 'stack')); + + my @instances = (); + foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { + if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 11) { + next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); + push @instances, $1; + } + } + + foreach my $instance (@instances) { + next if (!defined($self->{results}->{entity}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); + + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{entity}, instance => $instance); + + next if ($self->check_filter(section => 'stack', instance => $instance)); + $self->{components}->{stack}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("stack '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus}, $result->{chasEntPhysOperStatus}) + ); + + if ($result->{chasEntPhysPower} > 0) { + $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', + value => $result->{chasEntPhysPower}, + min => 0); + } + + my $exit = $self->get_severity(label => 'admin', section => 'stack.admin', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("stack '%s/%s/%s' admin status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus})); + next; + } + + $exit = $self->get_severity(label => 'oper', section => 'stack.oper', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("stack '%s/%s/%s' operational status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysOperStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/network/alcatel/omniswitch/snmp/mode/components/unknown.pm b/network/alcatel/omniswitch/snmp/mode/components/unknown.pm new file mode 100644 index 000000000..fe18d7a17 --- /dev/null +++ b/network/alcatel/omniswitch/snmp/mode/components/unknown.pm @@ -0,0 +1,82 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::omniswitch::snmp::mode::components::unknown; + +use strict; +use warnings; +use network::alcatel::omniswitch::snmp::mode::components::resources qw(%oids $mapping); + +sub load {} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking unknown"); + $self->{components}->{unknown} = {name => 'unknowns', total => 0, skip => 0}; + return if ($self->check_filter(section => 'unknown')); + + my @instances = (); + foreach my $key (keys %{$self->{results}->{$oids{entPhysicalClass}}}) { + if ($self->{results}->{$oids{entPhysicalClass}}->{$key} == 2) { + next if ($key !~ /^$oids{entPhysicalClass}\.(.*)$/); + push @instances, $1; + } + } + + foreach my $instance (@instances) { + next if (!defined($self->{results}->{entity}->{$oids{chasEntPhysAdminStatus} . '.' . $instance})); + + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{entity}, instance => $instance); + + next if ($self->check_filter(section => 'unknown', instance => $instance)); + $self->{components}->{unknown}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("unknown '%s/%s' [instance: %s, admin status: %s] operationnal status is %s.", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus}, $result->{chasEntPhysOperStatus}) + ); + + if ($result->{chasEntPhysPower} > 0) { + $self->{output}->perfdata_add(label => "power_" . $instance, unit => 'W', + value => $result->{chasEntPhysPower}, + min => 0); + } + + my $exit = $self->get_severity(label => 'admin', section => 'unknown.admin', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("unknown '%s/%s/%s' admin status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysAdminStatus})); + next; + } + + $exit = $self->get_severity(label => 'oper', section => 'unknown.oper', value => $result->{chasEntPhysAdminStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("unknown '%s/%s/%s' operational status is %s", + $result->{entPhysicalName}, $result->{entPhysicalDescr}, $instance, + $result->{chasEntPhysOperStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/network/alcatel/common/mode/cpu.pm b/network/alcatel/omniswitch/snmp/mode/cpu.pm similarity index 99% rename from network/alcatel/common/mode/cpu.pm rename to network/alcatel/omniswitch/snmp/mode/cpu.pm index 0c738ce1c..720a59003 100644 --- a/network/alcatel/common/mode/cpu.pm +++ b/network/alcatel/omniswitch/snmp/mode/cpu.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::alcatel::common::mode::cpu; +package network::alcatel::omniswitch::snmp::mode::cpu; use base qw(centreon::plugins::mode); diff --git a/network/alcatel/common/mode/flashmemory.pm b/network/alcatel/omniswitch/snmp/mode/flashmemory.pm similarity index 98% rename from network/alcatel/common/mode/flashmemory.pm rename to network/alcatel/omniswitch/snmp/mode/flashmemory.pm index 9d8a7349d..c16bce2a5 100644 --- a/network/alcatel/common/mode/flashmemory.pm +++ b/network/alcatel/omniswitch/snmp/mode/flashmemory.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::alcatel::common::mode::flashmemory; +package network::alcatel::omniswitch::snmp::mode::flashmemory; use base qw(centreon::plugins::mode); diff --git a/network/alcatel/omniswitch/snmp/mode/hardware.pm b/network/alcatel/omniswitch/snmp/mode/hardware.pm new file mode 100644 index 000000000..0d5dfe540 --- /dev/null +++ b/network/alcatel/omniswitch/snmp/mode/hardware.pm @@ -0,0 +1,124 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::omniswitch::snmp::mode::hardware; + +use base qw(centreon::plugins::templates::hardware); +use network::alcatel::omniswitch::snmp::mode::components::resources qw(%oids); + +sub set_system { + my ($self, %options) = @_; + + $self->{regexp_threshold_overload_check_section_option} = '^(backplane|chassis|container|fan|module|other|port|psu|sensor|stack|unknown)$'; + + $self->{cb_hook2} = 'snmp_execute'; + + $self->{thresholds} = { + admin => [ + ['^(reset|takeover|resetWithFabric|takeoverWithFabrc)$', 'WARNING'], + ['^(powerOff)$', 'CRITICAL'], + ['powerOn', 'OK'], + ['standby', 'OK'], + ], + oper => [ + ['^(testing)$', 'WARNING'], + ['^(unpowered|down|notpresent)$', 'CRITICAL'], + ['up', 'OK'], + ['secondary', 'OK'], + ['master', 'OK'], + ['idle', 'OK'], + ], + fan => [ + ['^noStatus$', 'UNKNOWN'], + ['^notRunning$', 'CRITICAL'], + ['running', 'OK'], + ], + }; + + $self->{components_path} = 'network::alcatel::omniswitch::snmp::mode::components'; + $self->{components_module} = ['backplane', 'chassis', 'container', 'fan', 'module', 'other', 'port', 'psu', 'sensor', 'stack', 'unknown']; +} + +sub snmp_execute { + my ($self, %options) = @_; + + $self->{snmp} = $options{snmp}; + $self->{results} = $self->{snmp}->get_multiple_table(oids => [ + { oid => $oids{entPhysicalClass} }, + { oid => $oids{alaChasEntPhysFanStatus} }, + ]); + $self->{results}->{entity} = $self->{snmp}->get_multiple_table(oids => [ + { oid => $oids{entPhysicalDescr} }, + { oid => $oids{entPhysicalName} }, + { oid => $oids{chasEntPhysAdminStatus} }, + { oid => $oids{chasEntPhysOperStatus} }, + { oid => $oids{chasEntPhysPower} }, + ], return_type => 1); +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +1; + +__END__ + +=head1 MODE + +Check status of alcatel hardware (AlcatelIND1Chassis.mib). + +=over 8 + +=item B<--component> + +Which component to check (Default: '.*'). +Can be: 'other', 'unknown', 'chassis', 'backplane', 'container', 'psu', 'fan', +'sensor', 'module', 'port, 'stack'. +Some not exists ;) + +=item B<--filter> + +Exclude some parts (comma seperated list) (Example: --filter=fan) +Can also exclude specific instance: --filter=fan,1.2 + +=item B<--no-component> + +Return an error if no compenents are checked. +If total (with skipped) is 0. (Default: 'critical' returns). + +=item B<--threshold-overload> + +Set to overload default threshold values (syntax: section,[instance,]status,regexp) +It used before default thresholds (order stays). +Example: --threshold-overload='psu.oper,CRITICAL,standby' + +=back + +=cut diff --git a/network/alcatel/common/mode/memory.pm b/network/alcatel/omniswitch/snmp/mode/memory.pm similarity index 99% rename from network/alcatel/common/mode/memory.pm rename to network/alcatel/omniswitch/snmp/mode/memory.pm index 7426eb43d..9176f3c18 100644 --- a/network/alcatel/common/mode/memory.pm +++ b/network/alcatel/omniswitch/snmp/mode/memory.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::alcatel::common::mode::memory; +package network::alcatel::omniswitch::snmp::mode::memory; use base qw(centreon::plugins::mode); diff --git a/network/alcatel/omniswitch/6850/plugin.pm b/network/alcatel/omniswitch/snmp/plugin.pm similarity index 86% rename from network/alcatel/omniswitch/6850/plugin.pm rename to network/alcatel/omniswitch/snmp/plugin.pm index 1c5cefc60..aa3fbbbe5 100644 --- a/network/alcatel/omniswitch/6850/plugin.pm +++ b/network/alcatel/omniswitch/snmp/plugin.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::alcatel::omniswitch::6850::plugin; +package network::alcatel::omniswitch::snmp::plugin; use strict; use warnings; @@ -29,14 +29,14 @@ sub new { my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; - $self->{version} = '0.5'; + $self->{version} = '0.1'; %{$self->{modes}} = ( - 'cpu' => 'network::alcatel::common::mode::cpu', - 'hardware' => 'network::alcatel::common::mode::hardware', + 'cpu' => 'network::alcatel::omniswitch::snmp::mode::cpu', + 'hardware' => 'network::alcatel::omniswitch::snmp::mode::hardware', 'interfaces' => 'snmp_standard::mode::interfaces', 'list-interfaces' => 'snmp_standard::mode::listinterfaces', - 'flash-memory' => 'network::alcatel::common::mode::flashmemory', - 'memory' => 'network::alcatel::common::mode::memory', + 'flash-memory' => 'network::alcatel::omniswitch::snmp::mode::flashmemory', + 'memory' => 'network::alcatel::omniswitch::snmp::mode::memory', 'spanning-tree' => 'snmp_standard::mode::spanningtree', ); @@ -49,6 +49,6 @@ __END__ =head1 PLUGIN DESCRIPTION -Check Alcatel Omniswitch 6850 in SNMP. +Check Alcatel Omniswitch in SNMP. =cut diff --git a/network/brocade/snmp/mode/hardware.pm b/network/brocade/snmp/mode/hardware.pm index 755d2e8e6..3cb35c319 100644 --- a/network/brocade/snmp/mode/hardware.pm +++ b/network/brocade/snmp/mode/hardware.pm @@ -20,35 +20,44 @@ package network::brocade::snmp::mode::hardware; -use base qw(centreon::plugins::mode); +use base qw(centreon::plugins::templates::hardware); use strict; use warnings; -use centreon::plugins::misc; -my %operational_status = ( - 1 => ["switch operational status is online", 'OK'], - 2 => ["switch operational status is offline", 'WARNING'], - 3 => ["switch operational status is testing", 'WARNING'], - 4 => ["switch operational status is faulty", 'CRITICAL'], -); -my %sensor_type_map = ( - 1 => {name => 'temperature', unit => 'C' }, - 2 => {name => 'fan', unit => 'rpm' }, - 3 => {name => 'power-supply', unit => undef }, # No voltage value available -); -my %sensor_status = ( - 1 => ["%s sensor '%s' is unknown", 'UNKNOWN'], - 2 => ["%s sensor '%s' is faulty", 'CRITICAL'], - 3 => ["%s sensor '%s' is below-min", 'WARNING'], - 4 => ["%s sensor '%s' is nominal", 'OK'], - 5 => ["%s sensor '%s' is above-max", 'WARNING'], - 6 => ["%s sensor '%s' is absent", 'WARNING'], -); +sub set_system { + my ($self, %options) = @_; + + $self->{regexp_threshold_overload_check_section_option} = '^(switch|sensor)$'; + $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|fan)$'; + + $self->{cb_hook2} = 'snmp_execute'; + + $self->{thresholds} = { + sensor => [ + ['unknown', 'UNKNOWN'], + ['faulty', 'CRITICAL'], + ['below-min', 'WARNING'], + ['nominal', 'OK'], + ['above-max', 'CRITICAL'], + ['absent', 'OK'], + ], + switch => [ + ['online', 'OK'], + ['offline', 'WARNING'], + ['testing', 'WARNING'], + ['faulty', 'CRITICAL'], + ['absent', 'OK'], + ], + }; + + $self->{components_path} = 'network::brocade::snmp::mode::components'; + $self->{components_module} = ['switch', 'sensor']; +} sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_load_components => 1); bless $self, $class; $self->{version} = '1.0'; @@ -59,68 +68,169 @@ sub new { return $self; } -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); -} - -sub run { +sub snmp_execute { my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; - - my $oid_swFirmwareVersion = '.1.3.6.1.4.1.1588.2.1.1.1.1.6.0'; - my $oid_swOperStatus = '.1.3.6.1.4.1.1588.2.1.1.1.1.7.0'; - my $result = $self->{snmp}->get_leef(oids => [$oid_swFirmwareVersion, $oid_swOperStatus], nothing_quit => 1); - - $self->{output}->output_add(severity => ${$operational_status{$result->{$oid_swOperStatus}}}[1], - short_msg => sprintf(${$operational_status{$result->{$oid_swOperStatus}}}[0] . " [firmware: %s]", - $result->{$oid_swFirmwareVersion})); - - $self->{output}->output_add(severity => 'OK', - short_msg => "All sensors are ok."); - - my $oid_swSensorEntry = '.1.3.6.1.4.1.1588.2.1.1.1.1.22.1'; - my $oid_swSensorIndex = '.1.3.6.1.4.1.1588.2.1.1.1.1.22.1.1'; - my $oid_swSensorType = '.1.3.6.1.4.1.1588.2.1.1.1.1.22.1.2'; - my $oid_swSensorStatus = '.1.3.6.1.4.1.1588.2.1.1.1.1.22.1.3'; - my $oid_swSensorValue = '.1.3.6.1.4.1.1588.2.1.1.1.1.22.1.4'; - my $oid_swSensorInfo = '.1.3.6.1.4.1.1588.2.1.1.1.1.22.1.5'; - $result = $self->{snmp}->get_table(oid => $oid_swSensorEntry); - - foreach my $key ($self->{snmp}->oid_lex_sort(keys %$result)) { - next if ($key !~ /^$oid_swSensorIndex\.(\d+)/); - my $index = $1; - my $status = $result->{$oid_swSensorStatus . '.' . $index}; - my $type = $result->{$oid_swSensorType . '.' . $index}; - my $info = centreon::plugins::misc::trim($result->{$oid_swSensorInfo . '.' . $index}); - my $value = $result->{$oid_swSensorValue . '.' . $index}; - - $self->{output}->output_add(long_msg => sprintf(${$sensor_status{$status}}[0], $sensor_type_map{$type}->{name}, $info)); - if (${$sensor_status{$status}}[1] ne 'OK') { - $self->{output}->output_add(severity => ${$sensor_status{$status}}[1], - short_msg => sprintf(${$sensor_status{$status}}[0], $sensor_type_map{$type}->{name}, $info)); - } - - if ($value > 0 && $sensor_type_map{$type}->{name} ne 'power-supply') { - $self->{output}->perfdata_add(label => $info, unit => $sensor_type_map{$type}->{unit}, - value => $value); - } - } - - $self->{output}->display(); - $self->{output}->exit(); + $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); } 1; -__END__ - =head1 MODE Check brocade operational status and hardware sensors (SW.mib). =over 8 +=item B<--component> + +Which component to check (Default: '.*'). +Can be: 'switch', 'sensor'. + +=item B<--filter> + +Exclude some parts (comma seperated list) +Can also exclude specific instance: --filter=sensor,1.1 + +=item B<--absent-problem> + +Return an error if an entity is not 'present' (default is skipping) +Can be specific or global: --absent-problem=sensor,1.2 + +=item B<--no-component> + +Return an error if no compenents are checked. +If total (with skipped) is 0. (Default: 'critical' returns). + +=item B<--threshold-overload> + +Set to overload default threshold values (syntax: section,[instance,]status,regexp) +It used before default thresholds (order stays). +Example: --threshold-overload='sensor,OK,unknown' + +=item B<--warning> + +Set warning threshold for 'temperature', 'fan' (syntax: type,regexp,threshold) +Example: --warning='temperature,.*,40' + +=item B<--critical> + +Set critical threshold for 'temperature', 'fan' (syntax: type,regexp,threshold) +Example: --critical='temperature,.*,50' + =back =cut + +package network::brocade::snmp::mode::components::sensor; + +use strict; +use warnings; +use centreon::plugins::misc; + +my %map_status = (1 => 'unknown', 2 => 'faulty', 3 => 'below-min', 4 => 'nominal', 5 => 'above-max', 6 => 'absent'); +my %map_type = (1 => 'temperature', 2 => 'fan', 3 => 'power-supply'); +my %map_unit = (temperature => 'C', fan => 'rpm'); # No voltage value available + +my $mapping = { + swSensorType => { oid => '.1.3.6.1.4.1.1588.2.1.1.1.1.22.1.2', map => \%map_type }, + swSensorStatus => { oid => '.1.3.6.1.4.1.1588.2.1.1.1.1.22.1.3', map => \%map_status }, + swSensorValue => { oid => '.1.3.6.1.4.1.1588.2.1.1.1.1.22.1.4' }, + swSensorInfo => { oid => '.1.3.6.1.4.1.1588.2.1.1.1.1.22.1.5' }, +}; +my $oid_swSensorEntry = '.1.3.6.1.4.1.1588.2.1.1.1.1.22.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_swSensorEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking sensors"); + $self->{components}->{sensor} = {name => 'sensors', total => 0, skip => 0}; + return if ($self->check_filter(section => 'sensor')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_swSensorEntry}})) { + next if ($oid !~ /^$mapping->{swSensorStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_swSensorEntry}, instance => $instance); + + next if ($self->check_filter(section => 'sensor', instance => $instance)); + next if ($result->{swSensorStatus} =~ /absent/i && + $self->absent_problem(section => 'sensor', instance => $instance)); + + $result->{swSensorInfo} = centreon::plugins::misc::trim($result->{swSensorInfo}); + $self->{components}->{sensor}->{total}++; + $self->{output}->output_add(long_msg => sprintf("%s sensor '%s' status is '%s' [instance = %s]", + $result->{swSensorType}, $result->{swSensorInfo}, $result->{swSensorStatus}, $instance)); + my $exit = $self->get_severity(section => 'sensor', value => $result->{swSensorStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("%s sensor '%s' status is '%s'", $result->{swSensorType}, $result->{swSensorInfo})); + } + + if ($result->{swSensorValue} > 0 && $result->{swSensorType} ne 'power-supply') { + my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => $result->{swSensorType}, instance => $instance, value => $result->{swSensorValue}); + if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit2, + short_msg => sprintf("%s sensor '%s' is %s %s", $result->{swSensorType}, $result->{swSensorInfo}, $result->{swSensorValue}, + $map_unit{$result->{swSensorType}})); + } + $self->{output}->perfdata_add(label => $result->{swSensorInfo}, unit => $map_unit{$result->{swSensorType}}, + value => $result->{swSensorValue}, + warning => $warn, + critical => $crit + ); + } + } +} + +1; + +package network::brocade::snmp::mode::components::switch; + +use strict; +use warnings; + +my %map_oper_status = (1 => 'online', 2 => 'offline', 3 => 'testing', 4 => 'faulty'); + +my $mapping_global = { + swFirmwareVersion => { oid => '.1.3.6.1.4.1.1588.2.1.1.1.1.6' }, + swOperStatus => { oid => '.1.3.6.1.4.1.1588.2.1.1.1.1.7', map => \%map_oper_status }, +}; +my $oid_swSystem = '.1.3.6.1.4.1.1588.2.1.1.1.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_swSystem, start => $mapping_global->{swFirmwareVersion}->{oid}, end => $mapping_global->{swOperStatus}->{oid} }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking switch"); + $self->{components}->{switch} = {name => 'switch', total => 0, skip => 0}; + return if ($self->check_filter(section => 'switch')); + + my $result = $self->{snmp}->map_instance(mapping => $mapping_global, results => $self->{results}->{$oid_swSystem}, instance => '0'); + return if (!defined($result->{swOperStatus})); + + $self->{components}->{switch}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("switch operational status is '%s' [firmware: %s].", + $result->{swOperStatus}, $result->{swFirmwareVersion} + )); + my $exit = $self->get_severity(section => 'switch', value => $result->{swOperStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("switch operational status is '%s'", + $result->{swOperStatus})); + } +} + +1; diff --git a/network/checkpoint/snmp/mode/components/raiddisk.pm b/network/checkpoint/snmp/mode/components/raiddisk.pm new file mode 100644 index 000000000..5762c7b74 --- /dev/null +++ b/network/checkpoint/snmp/mode/components/raiddisk.pm @@ -0,0 +1,77 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::checkpoint::snmp::mode::components::raiddisk; + +use strict; +use warnings; +use centreon::plugins::misc; + +my %map_states_disk = ( + 0 => 'online', + 1 => 'missing', + 2 => 'not_compatible', + 3 => 'failed', + 4 => 'initializing', + 5 => 'offline_requested', + 6 => 'failed_requested', + 255 => 'other_offline', +); + +my $mapping = { + raidDiskProductID => { oid => '.1.3.6.1.4.1.2620.1.6.7.7.2.1.6' }, + raidDiskSyncState => { oid => '.1.3.6.1.4.1.2620.1.6.7.7.2.1.11', map => \%map_states_disk }, +}; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $mapping->{raidDiskProductID}->{oid} }, + { oid => $mapping->{raidDiskSyncState}->{oid} }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking raid disks"); + $self->{components}->{raiddisk} = {name => 'raiddisk', total => 0, skip => 0}; + return if ($self->check_filter(section => 'raiddisk')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{raidDiskProductID}->{oid}}})) { + $oid =~ /^$mapping->{raidDiskProductID}->{oid}\.(.*)$/; + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{raidDiskSyncState}->{oid}}, instance => $instance); + + next if ($self->check_filter(section => 'raiddisk', instance => $instance)); + + my $name = centreon::plugins::misc::trim($self->{results}->{$mapping->{raidDiskProductID}->{oid}}->{$oid}); + $self->{components}->{raiddisk}->{total}++; + $self->{output}->output_add(long_msg => sprintf("raid disk '%s' status is '%s'", + $name, $result->{raidDiskSyncState})); + my $exit = $self->get_severity(section => 'raiddisk', value => $result->{raidDiskSyncState}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Raid disk '%s' status is '%s'", + $name, $result->{raidDiskSyncState})); + } + } +} + +1; diff --git a/network/checkpoint/snmp/mode/connections.pm b/network/checkpoint/snmp/mode/connections.pm index 7ec8b3765..e8b82a840 100644 --- a/network/checkpoint/snmp/mode/connections.pm +++ b/network/checkpoint/snmp/mode/connections.pm @@ -35,6 +35,7 @@ sub new { { "warning:s" => { name => 'warning' }, "critical:s" => { name => 'critical' }, + "units:s" => { name => 'units', default => 'absolute' }, }); return $self; @@ -45,12 +46,17 @@ sub check_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(); + $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->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'."); + $self->{output}->option_exit(); + } + + if ($self->{option_results}->{units} !~ /^(absolute|%)$/i) { + $self->{output}->add_option_msg(short_msg => "Wrong units option: absolute or %"); + $self->{output}->option_exit(); } } @@ -59,16 +65,30 @@ sub run { $self->{snmp} = $options{snmp}; my $oid_fwNumCom = '.1.3.6.1.4.1.2620.1.1.25.3.0'; - my $result = $self->{snmp}->get_leef(oids => [$oid_fwNumCom], nothing_quit => 1); + my $oid_fwConnTableLimit = '.1.3.6.1.4.1.2620.1.1.25.10.0'; + my $result = $self->{snmp}->get_leef(oids => [$oid_fwNumCom, $oid_fwConnTableLimit], nothing_quit => 1); - my $exit = $self->{perfdata}->threshold_check(value => $result->{$oid_fwNumCom}, - threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); + my $value = $result->{$oid_fwNumCom}; + my $extra = ''; + my %total_options = (); + if (defined($result->{$oid_fwConnTableLimit}) && $result->{$oid_fwConnTableLimit} > 0) { + my $prct_used = sprintf("%.2f", $result->{$oid_fwNumCom} * 100 / $result->{$oid_fwConnTableLimit}); + $extra = " (" . $prct_used . '% used on ' . $result->{$oid_fwConnTableLimit} . ")"; + if ($self->{option_results}->{units} eq '%') { + $value = $prct_used; + %total_options = ( total => $result->{$oid_fwConnTableLimit}, cast_int => 1); + } + } + + + my $exit = $self->{perfdata}->threshold_check(value => $value, + threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Connections: %d", $result->{$oid_fwNumCom})); + short_msg => sprintf("Connections: %d%s", $result->{$oid_fwNumCom}, $extra)); $self->{output}->perfdata_add(label => "connections", unit => 'con', value => $result->{$oid_fwNumCom}, - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', %total_options), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', %total_options), min => 0 ); @@ -94,6 +114,10 @@ Number of connections trigerring a warning state Number of connections trigerring a criticalstate +=item B<--units> + +Units of thresholds (Default: 'absolute') ('%', 'absolute'). + =back =cut diff --git a/network/checkpoint/snmp/mode/hardware.pm b/network/checkpoint/snmp/mode/hardware.pm index ee7efa1c5..575a49779 100644 --- a/network/checkpoint/snmp/mode/hardware.pm +++ b/network/checkpoint/snmp/mode/hardware.pm @@ -28,7 +28,7 @@ use warnings; sub set_system { my ($self, %options) = @_; - $self->{regexp_threshold_overload_check_section_option} = '^(temperature|voltage|fan|psu)$'; + $self->{regexp_threshold_overload_check_section_option} = '^(temperature|voltage|fan|psu|raiddisk)$'; $self->{cb_hook2} = 'snmp_execute'; @@ -52,11 +52,22 @@ sub set_system { ['up', 'OK'], ['down', 'CRITICAL'], ['.*', 'UNKNOWN'], + ], + raiddisk => [ + ['online', 'OK'], + ['missing', 'OK'], + ['not_compatible', 'CRITICAL'], + ['failed', 'CRITICAL'], + ['initializing', 'OK'], + ['offline_requested', 'OK'], + ['failed_requested', 'OK'], + ['other_offline', 'WARNING'], + ['.*', 'UNKNOWN'], ], }; $self->{components_path} = 'network::checkpoint::snmp::mode::components'; - $self->{components_module} = ['voltage', 'fan', 'temperature', 'psu']; + $self->{components_module} = ['voltage', 'fan', 'temperature', 'psu', 'raiddisk']; } sub snmp_execute { @@ -92,7 +103,7 @@ Check hardware (fans, power supplies, temperatures, voltages). =item B<--component> Which component to check (Default: '.*'). -Can be: 'psu', 'fan', 'temperature', 'voltage'. +Can be: 'psu', 'fan', 'temperature', 'voltage', 'raiddisk'. =item B<--filter> diff --git a/network/citrix/appacceleration/snmp/mode/cpu.pm b/network/citrix/appacceleration/snmp/mode/cpu.pm new file mode 100644 index 000000000..c359055bb --- /dev/null +++ b/network/citrix/appacceleration/snmp/mode/cpu.pm @@ -0,0 +1,109 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::citrix::appacceleration::snmp::mode::cpu; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, message_separator => ' - ' } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'cpu', set => { + key_values => [ { name => 'cpu' } ], + output_template => 'CPU Usage : %.2f%% (1min)', + perfdatas => [ + { label => 'cpu', value => 'cpu_absolute', template => '%.2f', + min => 0, max => 100, unit => '%' }, + ], + } + }, + { label => 'load', set => { + key_values => [ { name => 'load' } ], + output_template => 'Load : %s', + perfdatas => [ + { label => 'load', value => 'load_absolute', template => '%s', + min => 0 }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_wsCpuUsage = '.1.3.6.1.4.1.3845.30.4.1.1.1.24.0'; + my $oid_wsSystemLoad = '.1.3.6.1.4.1.3845.30.4.1.1.1.34.0'; + my $snmp_result = $options{snmp}->get_leef(oids => [ + $oid_wsCpuUsage, $oid_wsSystemLoad], nothing_quit => 1); + + $self->{global} = { 'cpu' => $snmp_result->{$oid_wsCpuUsage}, 'load' => $snmp_result->{$oid_wsSystemLoad} }; +} + +1; + +__END__ + +=head1 MODE + +Check cpu usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='cpu' + +=item B<--warning-*> + +Threshold warning. +Can be: 'cpu', 'load'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'cpu', 'load'. + +=back + +=cut + diff --git a/network/citrix/appacceleration/snmp/mode/listserviceclass.pm b/network/citrix/appacceleration/snmp/mode/listserviceclass.pm new file mode 100644 index 000000000..32398267d --- /dev/null +++ b/network/citrix/appacceleration/snmp/mode/listserviceclass.pm @@ -0,0 +1,112 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::citrix::appacceleration::snmp::mode::listserviceclass; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; + +my $oid_wsServiceClassName = '.1.3.6.1.4.1.3845.30.4.1.1.2.2.1.2'; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $self->{snmp}->get_table(oid => $oid_wsServiceClassName, nothing_quit => 1); + $self->{sc} = {}; + foreach my $oid (keys %{$snmp_result}) { + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $snmp_result->{$oid} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping service class '" . $snmp_result->{$oid} . "'.", debug => 1); + next; + } + + $self->{sc}->{$snmp_result->{$oid}} = { name => $snmp_result->{$oid} }; + } +} + +sub run { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{sc}}) { + $self->{output}->output_add(long_msg => "'" . $name . "'"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List Service Class:'); + $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 => ['name']); +} + +sub disco_show { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{sc}}) { + $self->{output}->add_disco_entry(name => $name); + } +} + +1; + +__END__ + +=head1 MODE + +List Service Class. + +=over 8 + +=item B<--filter-name> + +Filter by service class name. + +=back + +=cut + diff --git a/network/citrix/appacceleration/snmp/mode/serviceclassusage.pm b/network/citrix/appacceleration/snmp/mode/serviceclassusage.pm new file mode 100644 index 000000000..a9d5aa97b --- /dev/null +++ b/network/citrix/appacceleration/snmp/mode/serviceclassusage.pm @@ -0,0 +1,220 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::citrix::appacceleration::snmp::mode::serviceclassusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'sc', type => 1, cb_prefix_output => 'prefix_sc_output', message_multiple => 'All Service Class are ok' } + ]; + + $self->{maps_counters}->{sc} = [ + { label => 'current-acc-con', set => { + key_values => [ { name => 'wsScsCurrentAcceleratedConnections' }, { name => 'display' } ], + output_template => 'Current Accelerated Connections : %s', + perfdatas => [ + { label => 'current_accelerated_connections', value => 'wsScsCurrentAcceleratedConnections_absolute', template => '%s', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'total-acc-con', set => { + key_values => [ { name => 'wsScsTotalAcceleratedConnections', diff => 1 }, { name => 'display' } ], + output_template => 'Total Accelerated Connections : %s', + perfdatas => [ + { label => 'total_accelerated_connections', value => 'wsScsTotalAcceleratedConnections_absolute', template => '%s', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'total-nonacc-con', set => { + key_values => [ { name => 'wsScsTotalNonAcceleratedConnections', diff => 1 }, { name => 'display' } ], + output_template => 'Total Non Accelerated Connections : %s', + perfdatas => [ + { label => 'total_nonaccelerated_connections', value => 'wsScsTotalNonAcceleratedConnections_absolute', template => '%s', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'traffic-in', set => { + key_values => [ { name => 'wsScsPreCompressReceivedOctets', diff => 1 }, { name => 'display' } ], + per_second => 1, output_change_bytes => 2, + output_template => 'Traffic In : %s %s/s', + perfdatas => [ + { label => 'traffic_in', value => 'wsScsPreCompressReceivedOctets_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'traffic-in-compressed', set => { + key_values => [ { name => 'wsScsCompressReceivedOctets', diff => 1 }, { name => 'display' } ], + per_second => 1, output_change_bytes => 2, + output_template => 'Traffic In Compressed : %s %s/s', + perfdatas => [ + { label => 'traffic_in_compressed', value => 'wsScsCompressReceivedOctets_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'traffic-out', set => { + key_values => [ { name => 'wsScsPreCompressSentOctets', diff => 1 }, { name => 'display' } ], + per_second => 1, output_change_bytes => 2, + output_template => 'Traffic Out : %s %s/s', + perfdatas => [ + { label => 'traffic_out', value => 'wsScsPreCompressSentOctets_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'traffic-out-compressed', set => { + key_values => [ { name => 'wsScsCompressSentOctets', diff => 1 }, { name => 'display' } ], + per_second => 1, output_change_bytes => 2, + output_template => 'Traffic Out Compressed : %s %s/s', + perfdatas => [ + { label => 'traffic_out_compressed', value => 'wsScsCompressSentOctets_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub prefix_sc_output { + my ($self, %options) = @_; + + return "Service Class '" . $options{instance_value}->{display} . "' "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + + return $self; +} + +my $oid_wsServiceClassName = '.1.3.6.1.4.1.3845.30.4.1.1.2.2.1.2'; +my $mapping = { + wsScsCurrentAcceleratedConnections => { oid => '.1.3.6.1.4.1.3845.30.4.1.1.2.2.1.3' }, + wsScsTotalAcceleratedConnections => { oid => '.1.3.6.1.4.1.3845.30.4.1.1.2.2.1.4' }, + wsScsTotalNonAcceleratedConnections => { oid => '.1.3.6.1.4.1.3845.30.4.1.1.2.2.1.6' }, + wsScsCompressSentOctets => { oid => '.1.3.6.1.4.1.3845.30.4.1.1.2.2.1.9' }, + wsScsCompressReceivedOctets => { oid => '.1.3.6.1.4.1.3845.30.4.1.1.2.2.1.10' }, + wsScsPreCompressSentOctets => { oid => '.1.3.6.1.4.1.3845.30.4.1.1.2.2.1.11' }, + wsScsPreCompressReceivedOctets => { oid => '.1.3.6.1.4.1.3845.30.4.1.1.2.2.1.12' }, +}; + +sub manage_selection { + my ($self, %options) = @_; + + if ($options{snmp}->is_snmpv1()) { + $self->{output}->add_option_msg(short_msg => "Need to use SNMP v2c or v3."); + $self->{output}->option_exit(); + } + + my $snmp_result = $options{snmp}->get_table(oid => $oid_wsServiceClassName, nothing_quit => 1); + $self->{sc} = {}; + foreach my $oid (keys %{$snmp_result}) { + $oid =~ /\.(\d+)$/; + my $instance = $1; + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $snmp_result->{$oid} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping service class '" . $snmp_result->{$oid} . "'.", debug => 1); + next; + } + + $self->{sc}->{$instance} = { display => $snmp_result->{$oid} }; + } + + $options{snmp}->load(oids => [$mapping->{wsScsCurrentAcceleratedConnections}->{oid}, $mapping->{wsScsTotalAcceleratedConnections}->{oid}, + $mapping->{wsScsTotalNonAcceleratedConnections}->{oid}, $mapping->{wsScsCompressSentOctets}->{oid}, + $mapping->{wsScsCompressReceivedOctets}->{oid}, $mapping->{wsScsPreCompressSentOctets}->{oid}, + $mapping->{wsScsPreCompressReceivedOctets}->{oid} + ], + instances => [keys %{$self->{sc}}], instance_regexp => '^(.*)$'); + $snmp_result = $options{snmp}->get_leef(nothing_quit => 1); + + foreach (keys %{$self->{sc}}) { + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $_); + + foreach my $name (('wsScsCompressSentOctets', 'wsScsCompressReceivedOctets', 'wsScsPreCompressSentOctets', 'wsScsPreCompressReceivedOctets')) { + $result->{$name} *= 8; + } + + foreach my $name (keys %$mapping) { + $self->{sc}->{$_}->{$name} = $result->{$name}; + } + } + + if (scalar(keys %{$self->{sc}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No service class found."); + $self->{output}->option_exit(); + } + + $self->{cache_name} = "citrix_appacceleration_" . $self->{mode} . '_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . + (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); +} + +1; + +__END__ + +=head1 MODE + +Check service class usage. + +=over 8 + +=item B<--warning-*> + +Threshold warning. +Can be: 'current-acc-con', 'total-acc-con', 'total-nonacc-con', +'traffic-in-compressed', 'traffic-out-compressed', +'traffic-in', 'traffic-out'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'current-acc-con', 'total-acc-con', 'total-nonacc-con', +'traffic-in-compressed', 'traffic-out-compressed', +'traffic-in', 'traffic-out'. + +=item B<--filter-name> + +Filter by service class name (can be a regexp). + +=back + +=cut diff --git a/network/citrix/appacceleration/snmp/plugin.pm b/network/citrix/appacceleration/snmp/plugin.pm new file mode 100644 index 000000000..0dfacf9b1 --- /dev/null +++ b/network/citrix/appacceleration/snmp/plugin.pm @@ -0,0 +1,50 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::citrix::appacceleration::snmp::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_snmp); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '0.1'; + %{$self->{modes}} = ( + 'cpu' => 'network::citrix::appacceleration::snmp::mode::cpu', + 'list-serviceclass' => 'network::citrix::appacceleration::snmp::mode::listserviceclass', + 'serviceclass-usage' => 'network::citrix::appacceleration::snmp::mode::serviceclassusage', + ); + + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Citrix Application Acceleration Module in SNMP (CloudBridge, Orbital, Repeater). + +=cut diff --git a/network/citrix/netscaler/snmp/mode/listvservers.pm b/network/citrix/netscaler/snmp/mode/listvservers.pm index 32e00a915..fbeeeeedb 100644 --- a/network/citrix/netscaler/snmp/mode/listvservers.pm +++ b/network/citrix/netscaler/snmp/mode/listvservers.pm @@ -25,7 +25,7 @@ use base qw(centreon::plugins::mode); use strict; use warnings; -my $oid_vsvrName = '.1.3.6.1.4.1.5951.4.1.3.1.1.1'; +my $oid_vsvrFullName = '.1.3.6.1.4.1.5951.4.1.3.1.1.59'; my $oid_vsvrEntityType = '.1.3.6.1.4.1.5951.4.1.3.1.1.64'; my %map_vs_type = ( @@ -62,11 +62,11 @@ sub check_options { sub manage_selection { my ($self, %options) = @_; - $self->{results} = $self->{snmp}->get_multiple_table(oids => [ { oid => $oid_vsvrName}, { oid => $oid_vsvrEntityType } ], nothing_quit => 1); - foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_vsvrName}})) { - next if ($oid !~ /^$oid_vsvrName\.(.*)$/); + $self->{results} = $self->{snmp}->get_multiple_table(oids => [ { oid => $oid_vsvrFullName}, { oid => $oid_vsvrEntityType } ], nothing_quit => 1); + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_vsvrFullName}})) { + next if ($oid !~ /^$oid_vsvrFullName\.(.*)$/); my $instance = $1; - my $name = $self->{results}->{$oid_vsvrName}->{$oid}; + my $name = $self->{results}->{$oid_vsvrFullName}->{$oid}; my $type = $self->{results}->{$oid_vsvrEntityType}->{$oid_vsvrEntityType . '.' . $instance}; next if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && @@ -98,7 +98,7 @@ sub run { $self->manage_selection(); foreach my $instance (sort @{$self->{vs_id_selected}}) { - my $name = $self->{results}->{$oid_vsvrName}->{$oid_vsvrName . '.' . $instance}; + my $name = $self->{results}->{$oid_vsvrFullName}->{$oid_vsvrFullName . '.' . $instance}; my $type = $self->{results}->{$oid_vsvrEntityType}->{$oid_vsvrEntityType . '.' . $instance}; $self->{output}->output_add(long_msg => "'" . $name . "' [type = '" . $map_vs_type{$type} . "']"); @@ -122,7 +122,7 @@ sub disco_show { $self->manage_selection(); foreach my $instance (sort @{$self->{vs_id_selected}}) { - my $name = $self->{results}->{$oid_vsvrName}->{$oid_vsvrName . '.' . $instance}; + my $name = $self->{results}->{$oid_vsvrFullName}->{$oid_vsvrFullName . '.' . $instance}; my $type = $self->{results}->{$oid_vsvrEntityType}->{$oid_vsvrEntityType . '.' . $instance}; $self->{output}->add_disco_entry(name => $name, type => $map_vs_type{$type}); @@ -154,4 +154,4 @@ Filter which type of vserver (can be a regexp). =back =cut - \ No newline at end of file + diff --git a/network/citrix/netscaler/snmp/mode/vserverstatus.pm b/network/citrix/netscaler/snmp/mode/vserverstatus.pm index 16be3b63c..95c88e03c 100644 --- a/network/citrix/netscaler/snmp/mode/vserverstatus.pm +++ b/network/citrix/netscaler/snmp/mode/vserverstatus.pm @@ -207,8 +207,8 @@ my %map_vs_status = ( ); my $mapping = { - vsvrName => { oid => '.1.3.6.1.4.1.5951.4.1.3.1.1.1' }, vsvrState => { oid => '.1.3.6.1.4.1.5951.4.1.3.1.1.5', map => \%map_vs_status }, + vsvrFullName => { oid => '.1.3.6.1.4.1.5951.4.1.3.1.1.59' }, vsvrEntityType => { oid => '.1.3.6.1.4.1.5951.4.1.3.1.1.64', map => \%map_vs_type }, }; my $mapping2 = { @@ -227,28 +227,28 @@ sub manage_selection { my ($self, %options) = @_; my $snmp_result = $options{snmp}->get_multiple_table(oids => [ - { oid => $mapping->{vsvrName}->{oid} }, + { oid => $mapping->{vsvrFullName}->{oid} }, { oid => $mapping->{vsvrState}->{oid} }, { oid => $mapping->{vsvrEntityType}->{oid} }, ], return_type => 1, nothing_quit => 1); $self->{vservers} = {}; foreach my $oid (keys %{$snmp_result}) { - next if ($oid !~ /^$mapping->{vsvrName}->{oid}\.(.*)$/); + next if ($oid !~ /^$mapping->{vsvrFullName}->{oid}\.(.*)$/); my $instance = $1; my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' && $result->{vsvrEntityType} !~ /$self->{option_results}->{filter_type}/) { - $self->{output}->output_add(long_msg => "skipping Virtual Server '" . $result->{vsvrName} . "'.", debug => 1); + $self->{output}->output_add(long_msg => "skipping Virtual Server '" . $result->{vsvrFullName} . "'.", debug => 1); next; } if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && - $result->{vsvrName} !~ /$self->{option_results}->{filter_name}/) { - $self->{output}->output_add(long_msg => "skipping Virtual Server '" . $result->{vsvrName} . "'.", debug => 1); + $result->{vsvrFullName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping Virtual Server '" . $result->{vsvrFullName} . "'.", debug => 1); next; } - $self->{vservers}->{$instance} = { display => $result->{vsvrName}, state => $result->{vsvrState} }; + $self->{vservers}->{$instance} = { display => $result->{vsvrFullName}, state => $result->{vsvrState} }; } $options{snmp}->load(oids => [$mapping2->{vsvrTotalRequestBytesLow}->{oid}, $mapping2->{vsvrTotalRequestBytesHigh}->{oid}, @@ -262,9 +262,9 @@ sub manage_selection { foreach (keys %{$self->{vservers}}) { my $result = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result, instance => $_); - $self->{vservers}->{$_}->{in} = (defined($result->{vsvrTotalResponseBytes}) ? $result->{vsvrTotalResponseBytes} : + $self->{vservers}->{$_}->{in} = (defined($result->{vsvrTotalResponseBytes}) ? $result->{vsvrTotalResponseBytes} * 8 : (($result->{vsvrTotalResponseBytesHigh} << 32) + $result->{vsvrTotalResponseBytesLow})) * 8; - $self->{vservers}->{$_}->{out} = (defined($result->{vsvrTotalRequestBytes}) ? $result->{vsvrTotalRequestBytes} : + $self->{vservers}->{$_}->{out} = (defined($result->{vsvrTotalRequestBytes}) ? $result->{vsvrTotalRequestBytes} * 8 : (($result->{vsvrTotalRequestBytesHigh} << 32) + $result->{vsvrTotalRequestBytesLow})) * 8; $self->{vservers}->{$_}->{health} = $result->{vsvrHealth}; $self->{vservers}->{$_}->{clients} = $result->{vsvrTotalClients}; diff --git a/network/radware/alteon/snmp/mode/listvservers.pm b/network/radware/alteon/snmp/mode/listvservers.pm new file mode 100644 index 000000000..4bd3e5a1d --- /dev/null +++ b/network/radware/alteon/snmp/mode/listvservers.pm @@ -0,0 +1,131 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::radware::alteon::snmp::mode::listvservers; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; + +my %map_state = ( + 2 => 'enabled', + 3 => 'disabled', +); + +my $mapping = { + slbCurCfgVirtServerState => { oid => '.1.3.6.1.4.1.1872.2.5.4.1.1.4.2.1.4', map => \%map_state }, + slbCurCfgVirtServerVname => { oid => '.1.3.6.1.4.1.1872.2.5.4.1.1.4.2.1.10' }, +}; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $self->{snmp}->get_multiple_table(oids => [ + { oid => $mapping->{slbCurCfgVirtServerState}->{oid} }, + { oid => $mapping->{slbCurCfgVirtServerVname}->{oid} }, + ], return_type => 1, nothing_quit => 1); + $self->{vservers} = {}; + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{slbCurCfgVirtServerVname}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + if (!defined($result->{slbCurCfgVirtServerVname}) || $result->{slbCurCfgVirtServerVname} eq '') { + $self->{output}->output_add(long_msg => "skipping Virtual Server '$instance': cannot get a name. please set it.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{slbCurCfgVirtServerVname} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping Virtual Server '" . $result->{slbCurCfgVirtServerVname} . "'.", debug => 1); + next; + } + + $self->{vservers}->{$instance} = { name => $result->{slbCurCfgVirtServerVname}, state => $result->{slbCurCfgVirtServerState} }; + } +} + +sub run { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $instance (sort keys %{$self->{vservers}}) { + $self->{output}->output_add(long_msg => "'" . $self->{vservers}->{$instance}->{name} . "' [state = '" . $self->{vservers}->{$instance}->{state} . "']"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List Virtual Servers:'); + $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 => ['name', 'state']); +} + +sub disco_show { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $instance (sort keys %{$self->{vservers}}) { + $self->{output}->add_disco_entry(name => $self->{vservers}->{$instance}->{name}, state => $self->{vservers}->{$instance}->{state}); + } +} + +1; + +__END__ + +=head1 MODE + +List Virtual Servers. + +=over 8 + +=item B<--filter-name> + +Filter by virtual server name. + +=back + +=cut + diff --git a/network/radware/alteon/snmp/mode/vserverstatus.pm b/network/radware/alteon/snmp/mode/vserverstatus.pm new file mode 100644 index 000000000..2d58f7770 --- /dev/null +++ b/network/radware/alteon/snmp/mode/vserverstatus.pm @@ -0,0 +1,263 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::radware::alteon::snmp::mode::vserverstatus; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = 'state : ' . $self->{result_values}->{state}; + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_state'}; + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'vservers', type => 1, cb_prefix_output => 'prefix_vservers_output', message_multiple => 'All Virtual Servers are ok' } + ]; + + $self->{maps_counters}->{vservers} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'state' }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_threshold_output'), + } + }, + { label => 'traffic', set => { + key_values => [ { name => 'traffic', diff => 1 }, { name => 'display' } ], + per_second => 1, output_change_bytes => 2, + output_template => 'Traffic : %s %s/s', + perfdatas => [ + { label => 'traffic', value => 'traffic_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'current-sessions', set => { + key_values => [ { name => 'current_sessions' }, { name => 'display' } ], + output_template => 'Current Sessions : %s', + perfdatas => [ + { label => 'current_sessions', value => 'current_sessions_absolute', template => '%s', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'total-sessions', set => { + key_values => [ { name => 'total_sessions', diff => 1 }, { name => 'display' } ], + output_template => 'Total Sessions : %s', + perfdatas => [ + { label => 'total_sessions', value => 'total_sessions_absolute', template => '%s', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub prefix_vservers_output { + my ($self, %options) = @_; + + return "Virtual Server '" . $options{instance_value}->{display} . "' "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "warning-status:s" => { name => 'warning_status', default => '' }, + "critical-status:s" => { name => 'critical_status', default => '' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +my %map_state = ( + 2 => 'enabled', + 3 => 'disabled', +); + +my $mapping = { + slbCurCfgVirtServerState => { oid => '.1.3.6.1.4.1.1872.2.5.4.1.1.4.2.1.4', map => \%map_state }, + slbCurCfgVirtServerVname => { oid => '.1.3.6.1.4.1.1872.2.5.4.1.1.4.2.1.10' }, + slbCurCfgVirtServerAvail => { oid => '.1.3.6.1.4.1.1872.2.5.4.1.1.4.2.1.8' }, # can't get mapping for that. If someones has it, i'm interested :) +}; +my $mapping2 = { + slbStatVServerCurrSessions => { oid => '.1.3.6.1.4.1.1872.2.5.4.2.4.1.2' }, + slbStatVServerTotalSessions => { oid => '.1.3.6.1.4.1.1872.2.5.4.2.4.1.3' }, + slbStatVServerHCOctetsLow32 => { oid => '.1.3.6.1.4.1.1872.2.5.4.2.4.1.5' }, + slbStatVServerHCOctetsHigh32 => { oid => '.1.3.6.1.4.1.1872.2.5.4.2.4.1.6' }, + slbStatVServerHCOctets => { oid => '.1.3.6.1.4.1.1872.2.5.4.2.4.1.13' }, +}; + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $options{snmp}->get_multiple_table(oids => [ + { oid => $mapping->{slbCurCfgVirtServerState}->{oid} }, + { oid => $mapping->{slbCurCfgVirtServerVname}->{oid} }, + ], return_type => 1, nothing_quit => 1); + $self->{vservers} = {}; + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{slbCurCfgVirtServerVname}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + if (!defined($result->{slbCurCfgVirtServerVname}) || $result->{slbCurCfgVirtServerVname} eq '') { + $self->{output}->output_add(long_msg => "skipping Virtual Server '$instance': cannot get a name. please set it.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{slbCurCfgVirtServerVname} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping Virtual Server '" . $result->{slbCurCfgVirtServerVname} . "'.", debug => 1); + next; + } + + $self->{vservers}->{$instance} = { display => $result->{slbCurCfgVirtServerVname}, state => $result->{slbCurCfgVirtServerState} }; + } + + $options{snmp}->load(oids => [$mapping2->{slbStatVServerCurrSessions}->{oid}, $mapping2->{slbStatVServerTotalSessions}->{oid}, + $mapping2->{slbStatVServerHCOctetsLow32}->{oid}, $mapping2->{slbStatVServerHCOctetsHigh32}->{oid}, + $mapping2->{slbStatVServerHCOctets}->{oid} + ], + instances => [keys %{$self->{vservers}}], instance_regexp => '^(.*)$'); + $snmp_result = $options{snmp}->get_leef(nothing_quit => 1); + + foreach (keys %{$self->{vservers}}) { + my $result = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result, instance => $_); + + $self->{vservers}->{$_}->{traffic} = (defined($result->{slbStatVServerHCOctets}) ? $result->{slbStatVServerHCOctets} * 8 : + (($result->{slbStatVServerHCOctetsHigh32} << 32) + $result->{slbStatVServerHCOctetsLow32})) * 8; + $self->{vservers}->{$_}->{current_sessions} = $result->{slbStatVServerCurrSessions}; + $self->{vservers}->{$_}->{total_sessions} = $result->{slbStatVServerTotalSessions}; + } + + if (scalar(keys %{$self->{vservers}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No virtual server found."); + $self->{output}->option_exit(); + } + + $self->{cache_name} = "alteon_" . $self->{mode} . '_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . + (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); +} + +1; + +__END__ + +=head1 MODE + +Check vservers status. + +=over 8 + +=item B<--warning-*> + +Threshold warning. +Can be: 'traffic', 'total-sessions', 'current-sessions'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'traffic', 'total-sessions', 'current-sessions'. + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{state}, %{display} + +=item B<--critical-status> + +Set critical threshold for status. +Can used special variables like: %{state}, %{display} + +=item B<--filter-name> + +Filter by virtual server name (can be a regexp). + +=back + +=cut diff --git a/network/radware/alteon/snmp/plugin.pm b/network/radware/alteon/snmp/plugin.pm index e2da10efe..fafb8bea0 100644 --- a/network/radware/alteon/snmp/plugin.pm +++ b/network/radware/alteon/snmp/plugin.pm @@ -31,9 +31,11 @@ sub new { $self->{version} = '1.0'; %{$self->{modes}} = ( - 'cpu' => 'network::radware::alteon::snmp::mode::cpu', - 'hardware' => 'network::radware::alteon::snmp::mode::hardware', - 'memory' => 'network::radware::alteon::snmp::mode::memory', + 'cpu' => 'network::radware::alteon::snmp::mode::cpu', + 'hardware' => 'network::radware::alteon::snmp::mode::hardware', + 'list-vservers' => 'network::radware::alteon::snmp::mode::listvservers', + 'memory' => 'network::radware::alteon::snmp::mode::memory', + 'vserver-status' => 'network::radware::alteon::snmp::mode::vserverstatus', ); return $self; diff --git a/network/watchguard/snmp/mode/policyusage.pm b/network/watchguard/snmp/mode/policyusage.pm index 8876f555a..4ffd00007 100644 --- a/network/watchguard/snmp/mode/policyusage.pm +++ b/network/watchguard/snmp/mode/policyusage.pm @@ -141,7 +141,7 @@ sub manage_selection { $self->{cache_name} = "watchguard_" . $self->{mode} . '_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . - (defined($self->{option_results}->{wgPolicyName}) ? md5_hex($self->{option_results}->{wgPolicyName}) : md5_hex('all')); + (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); } 1; diff --git a/os/linux/local/mode/process.pm b/os/linux/local/mode/process.pm index f5508195a..fabd7e91c 100644 --- a/os/linux/local/mode/process.pm +++ b/os/linux/local/mode/process.pm @@ -31,7 +31,7 @@ my %state_map = ( X => 'dead', W => 'paging', T => 'stopped', - S => 'InterrupibleSleep', + S => 'InterruptibleSleep', R => 'running', D => 'UninterrupibleSleep' ); @@ -61,6 +61,7 @@ sub new { "filter-command:s" => { name => 'filter_command' }, "filter-arg:s" => { name => 'filter_arg' }, "filter-state:s" => { name => 'filter_state' }, + "filter-ppid:s" => { name => 'filter_ppid' }, }); $self->{result} = {}; return $self; @@ -154,7 +155,9 @@ sub run { $self->{result}->{$pid}->{args} !~ /$self->{option_results}->{filter_arg}/); next if (defined($self->{option_results}->{filter_state}) && $self->{option_results}->{filter_state} ne '' && $state_map{$self->{result}->{$pid}->{state}} !~ /$self->{option_results}->{filter_state}/i); - + next if (defined($self->{option_results}->{filter_ppid}) && $self->{option_results}->{filter_ppid} ne '' && + $self->{result}->{$pid}->{ppid} !~ /$self->{option_results}->{filter_ppid}/); + $self->{output}->output_add(long_msg => 'Process: [command => ' . $self->{result}->{$pid}->{cmd} . '] [arg => ' . $self->{result}->{$pid}->{args} . '] [state => ' . $state_map{$self->{result}->{$pid}->{state}} . ']'); @@ -253,6 +256,10 @@ Filter process commands (regexp can be used). Filter process arguments (regexp can be used). +=item B<--filter-ppid> + +Filter process ppid (regexp can be used). + =item B<--filter-state> Filter process states (regexp can be used). @@ -261,4 +268,4 @@ You can use: 'zombie', 'dead', 'paging', 'stopped', =back -=cut \ No newline at end of file +=cut diff --git a/os/linux/local/mode/systemdscstatus.pm b/os/linux/local/mode/systemdscstatus.pm new file mode 100644 index 000000000..6ee618dbf --- /dev/null +++ b/os/linux/local/mode/systemdscstatus.pm @@ -0,0 +1,295 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package os::linux::local::mode::systemdscstatus; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $instance_mode; + +sub custom_threshold_output { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + my $msg = 'status : ' . $self->{result_values}->{load} . '/' . $self->{result_values}->{active} . '/' . $self->{result_values}->{sub}; + + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{load} = $options{new_datas}->{$self->{instance} . '_load'}; + $self->{result_values}->{active} = $options{new_datas}->{$self->{instance} . '_active'}; + $self->{result_values}->{sub} = $options{new_datas}->{$self->{instance} . '_sub'}; + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 }, + { name => 'sc', type => 1, cb_prefix_output => 'prefix_sc_output', message_multiple => 'All services are ok' } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'total-running', set => { + key_values => [ { name => 'running' }, { name => 'total' } ], + output_template => 'Total Running: %s', + perfdatas => [ + { label => 'total_running', value => 'running_absolute', template => '%s', + min => 0, max => 'total_absolute' }, + ], + } + }, + { label => 'total-failed', set => { + key_values => [ { name => 'failed' }, { name => 'total' } ], + output_template => 'Total Failed: %s', + perfdatas => [ + { label => 'total_failed', value => 'failed_absolute', template => '%s', + min => 0, max => 'total_absolute' }, + ], + } + }, + { label => 'total-dead', set => { + key_values => [ { name => 'dead' }, { name => 'total' } ], + output_template => 'Total Dead: %s', + perfdatas => [ + { label => 'total_dead', value => 'dead_absolute', template => '%s', + min => 0, max => 'total_absolute' }, + ], + } + }, + { label => 'total-exited', set => { + key_values => [ { name => 'exited' }, { name => 'total' } ], + output_template => 'Total Exited: %s', + perfdatas => [ + { label => 'total_exited', value => 'exited_absolute', template => '%s', + min => 0, max => 'total_absolute' }, + ], + } + }, + ]; + $self->{maps_counters}->{sc} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'load' }, { name => 'active' }, { name => 'sub' }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_threshold_output'), + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "hostname:s" => { name => 'hostname' }, + "remote" => { name => 'remote' }, + "ssh-option:s@" => { name => 'ssh_option' }, + "ssh-path:s" => { name => 'ssh_path' }, + "ssh-command:s" => { name => 'ssh_command', default => 'ssh' }, + "timeout:s" => { name => 'timeout', default => 30 }, + "sudo" => { name => 'sudo' }, + "command:s" => { name => 'command', default => 'systemctl' }, + "command-path:s" => { name => 'command_path' }, + "command-options:s" => { name => 'command_options', default => '-a --no-pager --no-legend' }, + "filter-name:s" => { name => 'filter_name' }, + "warning-status:s" => { name => 'warning_status', default => '' }, + "critical-status:s" => { name => 'critical_status', default => '%{active} =~ /failed/i' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub prefix_sc_output { + my ($self, %options) = @_; + + return "Service '" . $options{instance_value}->{display} . "' "; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub manage_selection { + my ($self, %options) = @_; + + my ($stdout) = centreon::plugins::misc::execute(output => $self->{output}, + options => $self->{option_results}, + sudo => $self->{option_results}->{sudo}, + command => $self->{option_results}->{command}, + command_path => $self->{option_results}->{command_path}, + command_options => $self->{option_results}->{command_options}); + + $self->{global} = { running => 0, exited => 0, failed => 0, dead => 0, total => 0 }; + $self->{sc} = {}; + #auditd.service loaded active running Security Auditing Service + #avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack + #brandbot.service loaded inactive dead Flexible Branding Service + while ($stdout =~ /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/msig) { + my ($name, $load, $active, $sub) = ($1, $2, $3, lc($4)); + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $name !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); + next; + } + + $self->{sc}->{$name} = { display => $name, load => $load, active => $active, sub => $sub }; + $self->{global}->{$sub} += 1 if (defined($self->{global}->{$sub})); + $self->{global}->{total} += 1; + } + + if (scalar(keys %{$self->{sc}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No service found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check systemd services status. + +=over 8 + +=item B<--remote> + +Execute command remotely in 'ssh'. + +=item B<--hostname> + +Hostname to query (need --remote). + +=item B<--ssh-option> + +Specify multiple options like the user (example: --ssh-option='-l=centreon-engine' --ssh-option='-p=52'). + +=item B<--ssh-path> + +Specify ssh command path (default: none) + +=item B<--ssh-command> + +Specify ssh command (default: 'ssh'). Useful to use 'plink'. + +=item B<--timeout> + +Timeout in seconds for the command (Default: 30). + +=item B<--sudo> + +Use 'sudo' to execute the command. + +=item B<--command> + +Command to get information (Default: 'systemctl'). +Can be changed if you have output in a file. + +=item B<--command-path> + +Command path (Default: none). + +=item B<--command-options> + +Command options (Default: '-a --no-pager --no-legend'). + +=item B<--filter-name> + +Filter service name (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'total-running', 'total-dead', 'total-exited', +'total-failed'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'total-running', 'total-dead', 'total-exited', +'total-failed'. + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{display}, %{active}, %{sub}, %{load} + + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{active} =~ /failed/i'). +Can used special variables like: %{display}, %{active}, %{sub}, %{load} + +=back + +=cut diff --git a/os/linux/local/plugin.pm b/os/linux/local/plugin.pm index 6735bc985..cdf655a1b 100644 --- a/os/linux/local/plugin.pm +++ b/os/linux/local/plugin.pm @@ -49,8 +49,9 @@ sub new { 'process' => 'os::linux::local::mode::process', 'storage' => 'os::linux::local::mode::storage', 'swap' => 'os::linux::local::mode::swap', - 'traffic' => 'os::linux::local::mode::traffic', - 'uptime' => 'os::linux::local::mode::uptime', + 'systemd-sc-status' => 'os::linux::local::mode::systemdscstatus', + 'traffic' => 'os::linux::local::mode::traffic', + 'uptime' => 'os::linux::local::mode::uptime', ); return $self; diff --git a/storage/dell/equallogic/snmp/mode/components/disk.pm b/storage/dell/equallogic/snmp/mode/components/disk.pm index ed9f3562d..375d347d5 100644 --- a/storage/dell/equallogic/snmp/mode/components/disk.pm +++ b/storage/dell/equallogic/snmp/mode/components/disk.pm @@ -43,9 +43,9 @@ my $mapping = { my $oid_eqlDiskStatus = '.1.3.6.1.4.1.12740.3.1.1.1.8'; sub load { - my (%options) = @_; + my ($self) = @_; - push @{$options{request}}, { oid => $oid_eqlDiskStatus }; + push @{$self->{request}}, { oid => $oid_eqlDiskStatus }; } sub check { @@ -53,7 +53,7 @@ sub check { $self->{output}->output_add(long_msg => "Checking disks"); $self->{components}->{disk} = {name => 'disks', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'disk')); + return if ($self->check_filter(section => 'disk')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_eqlDiskStatus}})) { next if ($oid !~ /^$mapping->{eqlDiskStatus}->{oid}\.(\d+\.\d+)\.(.*)$/); @@ -61,11 +61,11 @@ sub check { my $member_name = $self->get_member_name(instance => $member_instance); my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_eqlDiskStatus}, instance => $member_instance . '.' . $instance); - next if ($self->check_exclude(section => 'disk', instance => $instance)); + next if ($self->check_filter(section => 'disk', instance => $member_instance . '.' . $instance)); $self->{components}->{disk}->{total}++; $self->{output}->output_add(long_msg => sprintf("Disk '%s/%s' status is %s [instance: %s].", - $member_name, $instance, $result->{eqlDiskStatus}, $instance + $member_name, $instance, $result->{eqlDiskStatus}, $member_instance . '.' . $instance )); my $exit = $self->get_severity(section => 'disk', value => $result->{eqlDiskStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { diff --git a/storage/dell/equallogic/snmp/mode/components/fan.pm b/storage/dell/equallogic/snmp/mode/components/fan.pm index bc0431eeb..031d15e85 100644 --- a/storage/dell/equallogic/snmp/mode/components/fan.pm +++ b/storage/dell/equallogic/snmp/mode/components/fan.pm @@ -43,9 +43,9 @@ my $mapping = { my $oid_eqlMemberHealthDetailsFanEntry = '.1.3.6.1.4.1.12740.2.1.7.1'; sub load { - my (%options) = @_; + my ($self) = @_; - push @{$options{request}}, { oid => $oid_eqlMemberHealthDetailsFanEntry }; + push @{$self->{request}}, { oid => $oid_eqlMemberHealthDetailsFanEntry }; } sub check { @@ -53,7 +53,7 @@ sub check { $self->{output}->output_add(long_msg => "Checking fans"); $self->{components}->{fan} = {name => 'fans', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'fan')); + return if ($self->check_filter(section => 'fan')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_eqlMemberHealthDetailsFanEntry}})) { next if ($oid !~ /^$mapping->{eqlMemberHealthDetailsFanCurrentState}->{oid}\.(\d+\.\d+)\.(.*)$/); @@ -61,12 +61,12 @@ sub check { my $member_name = $self->get_member_name(instance => $member_instance); my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_eqlMemberHealthDetailsFanEntry}, instance => $member_instance . '.' . $instance); - next if ($self->check_exclude(section => 'fan', instance => $instance)); + next if ($self->check_filter(section => 'fan', instance => $member_instance . '.' . $instance)); $self->{components}->{fan}->{total}++; $self->{output}->output_add(long_msg => sprintf("Fan '%s/%s' status is %s [instance: %s].", $member_name, $result->{eqlMemberHealthDetailsFanName}, $result->{eqlMemberHealthDetailsFanCurrentState}, - $instance + $member_instance . '.' . $instance )); my $exit = $self->get_severity(section => 'fan', value => $result->{eqlMemberHealthDetailsFanCurrentState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { diff --git a/storage/dell/equallogic/snmp/mode/components/health.pm b/storage/dell/equallogic/snmp/mode/components/health.pm index d25dff84a..b3af94754 100644 --- a/storage/dell/equallogic/snmp/mode/components/health.pm +++ b/storage/dell/equallogic/snmp/mode/components/health.pm @@ -37,9 +37,9 @@ my $mapping = { my $oid_eqlMemberHealthStatus = '.1.3.6.1.4.1.12740.2.1.5.1.1'; sub load { - my (%options) = @_; + my ($self) = @_; - push @{$options{request}}, { oid => $oid_eqlMemberHealthStatus }; + push @{$self->{request}}, { oid => $oid_eqlMemberHealthStatus }; } sub check { @@ -47,7 +47,7 @@ sub check { $self->{output}->output_add(long_msg => "Checking health"); $self->{components}->{health} = {name => 'health', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'health')); + return if ($self->check_filter(section => 'health')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_eqlMemberHealthStatus}})) { next if ($oid !~ /^$mapping->{eqlMemberHealthStatus}->{oid}\.(\d+\.\d+)$/); @@ -55,12 +55,12 @@ sub check { my $member_name = $self->get_member_name(instance => $member_instance); my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_eqlMemberHealthStatus}, instance => $member_instance); - next if ($self->check_exclude(section => 'health', instance => $member_instance)); + next if ($self->check_filter(section => 'health', instance => $member_instance)); $self->{components}->{health}->{total}++; $self->{output}->output_add(long_msg => sprintf("Health '%s' status is %s [instance: %s].", $member_name, $result->{eqlMemberHealthStatus}, - $member_name + $member_instance )); my $exit = $self->get_severity(section => 'health', value => $result->{eqlMemberHealthStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { diff --git a/storage/dell/equallogic/snmp/mode/components/psu.pm b/storage/dell/equallogic/snmp/mode/components/psu.pm index 2460f3eaf..363f9f41b 100644 --- a/storage/dell/equallogic/snmp/mode/components/psu.pm +++ b/storage/dell/equallogic/snmp/mode/components/psu.pm @@ -43,9 +43,9 @@ my $mapping = { my $oid_eqlMemberHealthDetailsPowerSupplyEntry = '.1.3.6.1.4.1.12740.2.1.8.1'; sub load { - my (%options) = @_; + my ($self) = @_; - push @{$options{request}}, { oid => $oid_eqlMemberHealthDetailsPowerSupplyEntry }; + push @{$self->{request}}, { oid => $oid_eqlMemberHealthDetailsPowerSupplyEntry }; } sub check { @@ -53,7 +53,7 @@ sub check { $self->{output}->output_add(long_msg => "Checking power supplies"); $self->{components}->{psu} = {name => 'power supplies', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'psu')); + return if ($self->check_filter(section => 'psu')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_eqlMemberHealthDetailsPowerSupplyEntry}})) { next if ($oid !~ /^$mapping->{eqlMemberHealthDetailsPowerSupplyCurrentState}->{oid}\.(\d+\.\d+)\.(.*)$/); @@ -61,12 +61,12 @@ sub check { my $member_name = $self->get_member_name(instance => $member_instance); my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_eqlMemberHealthDetailsPowerSupplyEntry}, instance => $member_instance . '.' . $instance); - next if ($self->check_exclude(section => 'psu', instance => $instance)); + next if ($self->check_filter(section => 'psu', instance => $member_instance . '.' . $instance)); $self->{components}->{psu}->{total}++; $self->{output}->output_add(long_msg => sprintf("Power supply '%s/%s' status is %s [instance: %s] [fan status: %s].", $member_name, $result->{eqlMemberHealthDetailsPowerSupplyName}, $result->{eqlMemberHealthDetailsPowerSupplyCurrentState}, - $instance, $result->{eqlMemberHealthDetailsPowerSupplyFanStatus} + $member_instance . '.' . $instance, $result->{eqlMemberHealthDetailsPowerSupplyFanStatus} )); my $exit = $self->get_severity(section => 'psu', value => $result->{eqlMemberHealthDetailsPowerSupplyCurrentState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { @@ -75,7 +75,7 @@ sub check { $member_name, $result->{eqlMemberHealthDetailsPowerSupplyName}, $result->{eqlMemberHealthDetailsPowerSupplyCurrentState})); } - next if ($self->check_exclude(section => 'psu.fan', instance => $instance)); + next if ($self->check_filter(section => 'psu.fan', instance => $member_instance . '.' . $instance)); $exit = $self->get_severity(section => 'psu.fan', value => $result->{eqlMemberHealthDetailsPowerSupplyFanStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, diff --git a/storage/dell/equallogic/snmp/mode/components/raid.pm b/storage/dell/equallogic/snmp/mode/components/raid.pm index 60fe49c68..a80404f59 100644 --- a/storage/dell/equallogic/snmp/mode/components/raid.pm +++ b/storage/dell/equallogic/snmp/mode/components/raid.pm @@ -41,9 +41,9 @@ my $mapping = { my $oid_eqlMemberRAIDEntry = '.1.3.6.1.4.1.12740.2.1.13.1'; sub load { - my (%options) = @_; + my ($self) = @_; - push @{$options{request}}, { oid => $oid_eqlMemberRAIDEntry }; + push @{$self->{request}}, { oid => $oid_eqlMemberRAIDEntry }; } sub check { @@ -51,7 +51,7 @@ sub check { $self->{output}->output_add(long_msg => "Checking raids"); $self->{components}->{raid} = {name => 'raids', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'raid')); + return if ($self->check_filter(section => 'raid')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_eqlMemberRAIDEntry}})) { next if ($oid !~ /^$mapping->{eqlMemberRaidStatus}->{oid}\.(\d+\.\d+)$/); @@ -59,11 +59,11 @@ sub check { my $member_name = $self->get_member_name(instance => $member_instance); my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_eqlMemberRAIDEntry}, instance => $member_instance); - next if ($self->check_exclude(section => 'raid', instance => $member_instance)); + next if ($self->check_filter(section => 'raid', instance => $member_instance)); $self->{components}->{raid}->{total}++; $self->{output}->output_add(long_msg => sprintf("Raid '%s' status is %s [instance: %s].", - $member_name, $result->{eqlMemberRaidStatus}, $member_name + $member_name, $result->{eqlMemberRaidStatus}, $member_instance )); my $exit = $self->get_severity(section => 'raid', value => $result->{eqlMemberRaidStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { diff --git a/storage/dell/equallogic/snmp/mode/components/temperature.pm b/storage/dell/equallogic/snmp/mode/components/temperature.pm index 9f835c8b0..028a711b2 100644 --- a/storage/dell/equallogic/snmp/mode/components/temperature.pm +++ b/storage/dell/equallogic/snmp/mode/components/temperature.pm @@ -43,9 +43,9 @@ my $mapping = { my $oid_eqlMemberHealthDetailsTemperatureEntry = '.1.3.6.1.4.1.12740.2.1.6.1'; sub load { - my (%options) = @_; + my ($self) = @_; - push @{$options{request}}, { oid => $oid_eqlMemberHealthDetailsTemperatureEntry }; + push @{$self->{request}}, { oid => $oid_eqlMemberHealthDetailsTemperatureEntry }; } sub check { @@ -53,7 +53,7 @@ sub check { $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'temperature')); + return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_eqlMemberHealthDetailsTemperatureEntry}})) { next if ($oid !~ /^$mapping->{eqlMemberHealthDetailsTemperatureCurrentState}->{oid}\.(\d+\.\d+)\.(.*)$/); @@ -61,12 +61,12 @@ sub check { my $member_name = $self->get_member_name(instance => $member_instance); my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_eqlMemberHealthDetailsTemperatureEntry}, instance => $member_instance . '.' . $instance); - next if ($self->check_exclude(section => 'temperature', instance => $instance)); + next if ($self->check_filter(section => 'temperature', instance => $member_instance . '.' . $instance)); $self->{components}->{temperature}->{total}++; $self->{output}->output_add(long_msg => sprintf("Temperature '%s/%s' status is %s [instance: %s].", $member_name, $result->{eqlMemberHealthDetailsTemperatureName}, $result->{eqlMemberHealthDetailsTemperatureCurrentState}, - $instance + $member_instance . '.' . $instance )); my $exit = $self->get_severity(section => 'temperature', value => $result->{eqlMemberHealthDetailsTemperatureCurrentState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { diff --git a/storage/dell/equallogic/snmp/mode/hardware.pm b/storage/dell/equallogic/snmp/mode/hardware.pm index 9c74ba3d4..455140e8d 100644 --- a/storage/dell/equallogic/snmp/mode/hardware.pm +++ b/storage/dell/equallogic/snmp/mode/hardware.pm @@ -20,141 +20,99 @@ package storage::dell::equallogic::snmp::mode::hardware; -use base qw(centreon::plugins::mode); +use base qw(centreon::plugins::templates::hardware); use strict; use warnings; -my $thresholds = { - fan => [ - ['unknown', 'UNKNOWN'], - ['normal', 'OK'], - ['warning', 'WARNING'], - ['critical', 'CRITICAL'], - ], - temperature => [ - ['unknown', 'UNKNOWN'], - ['normal', 'OK'], - ['warning', 'WARNING'], - ['critical', 'CRITICAL'], - ], - health => [ - ['unknown', 'UNKNOWN'], - ['normal', 'OK'], - ['warning', 'WARNING'], - ['critical', 'CRITICAL'], - ], - psu => [ - ['on-and-operating', 'OK'], - ['no-ac-power', 'CRITICAL'], - ['failed-or-no-data', 'CRITICAL'], - ], - 'psu.fan' => [ - ['not-applicable', 'OK'], - ['fan-is-operational', 'OK'], - ['fan-not-operational', 'CRITICAL'], - ], - raid => [ - ['ok', 'OK'], - ['degraded', 'WARNING'], - ['verifying', 'OK'], - ['reconstructing', 'WARNING'], - ['failed', 'CRITICAL'], - ['catastrophicLoss', 'CRITICAL'], - ['expanding', 'OK'], - ['mirroring', 'OK'], - ], - disk => [ - ['on-line', 'OK'], - ['spare', 'OK'], - ['failed', 'CRITICAL'], - ['off-line', 'WARNING'], - ['alt-sig', 'WARNING'], - ['too-small', 'WARNING'], - ['history-of-failures', 'WARNING'], - ['unsupported-version', 'CRITICAL'], - ['unhealthy', 'CRITICAL'], - ['replacement', 'CRITICAL'], - ], -}; +sub set_system { + my ($self, %options) = @_; + + $self->{regexp_threshold_overload_check_section_option} = '^(fan|psu|temperature|raid|disk|health)$'; + $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|fan)$'; + + $self->{cb_hook2} = 'snmp_execute'; + + $self->{thresholds} = { + fan => [ + ['unknown', 'UNKNOWN'], + ['normal', 'OK'], + ['warning', 'WARNING'], + ['critical', 'CRITICAL'], + ], + temperature => [ + ['unknown', 'UNKNOWN'], + ['normal', 'OK'], + ['warning', 'WARNING'], + ['critical', 'CRITICAL'], + ], + health => [ + ['unknown', 'UNKNOWN'], + ['normal', 'OK'], + ['warning', 'WARNING'], + ['critical', 'CRITICAL'], + ], + psu => [ + ['on-and-operating', 'OK'], + ['no-ac-power', 'CRITICAL'], + ['failed-or-no-data', 'CRITICAL'], + ], + 'psu.fan' => [ + ['not-applicable', 'OK'], + ['fan-is-operational', 'OK'], + ['fan-not-operational', 'CRITICAL'], + ], + raid => [ + ['ok', 'OK'], + ['degraded', 'WARNING'], + ['verifying', 'OK'], + ['reconstructing', 'WARNING'], + ['failed', 'CRITICAL'], + ['catastrophicLoss', 'CRITICAL'], + ['expanding', 'OK'], + ['mirroring', 'OK'], + ], + disk => [ + ['on-line', 'OK'], + ['spare', 'OK'], + ['failed', 'CRITICAL'], + ['off-line', 'WARNING'], + ['alt-sig', 'WARNING'], + ['too-small', 'WARNING'], + ['history-of-failures', 'WARNING'], + ['unsupported-version', 'CRITICAL'], + ['unhealthy', 'CRITICAL'], + ['replacement', 'CRITICAL'], + ], + }; + + $self->{components_path} = 'storage::dell::equallogic::snmp::mode::components'; + $self->{components_module} = ['fan', 'psu', 'temperature', 'raid', 'disk', 'health']; +} sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { - "exclude:s" => { name => 'exclude' }, - "component:s" => { name => 'component', default => '.*' }, - "no-component:s" => { name => 'no_component' }, - "threshold-overload:s@" => { name => 'threshold_overload' }, - "warning:s@" => { name => 'warning' }, - "critical:s@" => { name => 'critical' }, }); - - $self->{components} = {}; - $self->{no_components} = undef; return $self; } -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - if (defined($self->{option_results}->{no_component})) { - if ($self->{option_results}->{no_component} ne '') { - $self->{no_components} = $self->{option_results}->{no_component}; - } else { - $self->{no_components} = 'critical'; - } - } - - $self->{overload_th} = {}; - foreach my $val (@{$self->{option_results}->{threshold_overload}}) { - if ($val !~ /^(.*?),(.*?),(.*)$/) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'."); - $self->{output}->option_exit(); - } - my ($section, $status, $filter) = ($1, $2, $3); - if ($self->{output}->is_litteral_status(status => $status) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'."); - $self->{output}->option_exit(); - } - $self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section})); - push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status}; - } - - $self->{numeric_threshold} = {}; - foreach my $option (('warning', 'critical')) { - foreach my $val (@{$self->{option_results}->{$option}}) { - if ($val !~ /^(.*?),(.*?),(.*)$/) { - $self->{output}->add_option_msg(short_msg => "Wrong $option option '" . $val . "'."); - $self->{output}->option_exit(); - } - my ($section, $regexp, $value) = ($1, $2, $3); - if ($section !~ /(temperature|fan)/) { - $self->{output}->add_option_msg(short_msg => "Wrong $option option '" . $val . "' (type must be: temperature or fan)."); - $self->{output}->option_exit(); - } - my $position = 0; - if (defined($self->{numeric_threshold}->{$section})) { - $position = scalar(@{$self->{numeric_threshold}->{$section}}); - } - if (($self->{perfdata}->threshold_validate(label => $option . '-' . $section . '-' . $position, value => $value)) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong $option threshold '" . $value . "'."); - $self->{output}->option_exit(); - } - $self->{numeric_threshold}->{$section} = [] if (!defined($self->{numeric_threshold}->{$section})); - push @{$self->{numeric_threshold}->{$section}}, { label => $option . '-' . $section . '-' . $position, threshold => $option, regexp => $regexp }; - } - } -} - my $oid_eqlMemberName = '.1.3.6.1.4.1.12740.2.1.1.1.9'; +sub snmp_execute { + my ($self, %options) = @_; + + $self->{snmp} = $options{snmp}; + push @{$self->{request}}, { oid => $oid_eqlMemberName }; + $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); +} + sub get_member_name { my ($self, %options) = @_; @@ -163,122 +121,6 @@ sub get_member_name { return $name; } -sub run { - my ($self, %options) = @_; - $self->{snmp} = $options{snmp}; - - my $snmp_request = [ { oid => $oid_eqlMemberName } ]; - my @components = ('fan', 'psu', 'temperature', 'raid', 'disk', 'health'); - foreach (@components) { - if (/$self->{option_results}->{component}/) { - my $mod_name = "storage::dell::equallogic::snmp::mode::components::$_"; - centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $mod_name, - error_msg => "Cannot load module '$mod_name'."); - my $func = $mod_name->can('load'); - $func->(request => $snmp_request); - } - } - - if (scalar(@{$snmp_request}) == 1) { - $self->{output}->add_option_msg(short_msg => "Wrong option. Cannot find component '" . $self->{option_results}->{component} . "'."); - $self->{output}->option_exit(); - } - $self->{results} = $self->{snmp}->get_multiple_table(oids => $snmp_request); - - foreach (@components) { - if (/$self->{option_results}->{component}/) { - my $mod_name = "storage::dell::equallogic::snmp::mode::components::$_"; - my $func = $mod_name->can('check'); - $func->($self); - } - } - - my $total_components = 0; - my $display_by_component = ''; - my $display_by_component_append = ''; - foreach my $comp (sort(keys %{$self->{components}})) { - # Skipping short msg when no components - next if ($self->{components}->{$comp}->{total} == 0 && $self->{components}->{$comp}->{skip} == 0); - $total_components += $self->{components}->{$comp}->{total} + $self->{components}->{$comp}->{skip}; - my $count_by_components = $self->{components}->{$comp}->{total} + $self->{components}->{$comp}->{skip}; - $display_by_component .= $display_by_component_append . $self->{components}->{$comp}->{total} . '/' . $count_by_components . ' ' . $self->{components}->{$comp}->{name}; - $display_by_component_append = ', '; - } - - $self->{output}->output_add(severity => 'OK', - short_msg => sprintf("All %s components are ok [%s].", - $total_components, - $display_by_component) - ); - - if (defined($self->{option_results}->{no_component}) && $total_components == 0) { - $self->{output}->output_add(severity => $self->{no_components}, - short_msg => 'No components are checked.'); - } - - $self->{output}->display(); - $self->{output}->exit(); -} - -sub check_exclude { - my ($self, %options) = @_; - - if (defined($options{instance})) { - if (defined($self->{option_results}->{exclude}) && $self->{option_results}->{exclude} =~ /(^|\s|,)${options{section}}[^,]*#\Q$options{instance}\E#/) { - $self->{components}->{$options{section}}->{skip}++; - $self->{output}->output_add(long_msg => sprintf("Skipping $options{section} section $options{instance} instance.")); - return 1; - } - } elsif (defined($self->{option_results}->{exclude}) && $self->{option_results}->{exclude} =~ /(^|\s|,)$options{section}(\s|,|$)/) { - $self->{output}->output_add(long_msg => sprintf("Skipping $options{section} section.")); - return 1; - } - return 0; -} - -sub get_severity_numeric { - my ($self, %options) = @_; - my $status = 'OK'; # default - my $thresholds = { warning => undef, critical => undef }; - my $checked = 0; - - if (defined($self->{numeric_threshold}->{$options{section}})) { - my $exits = []; - foreach (@{$self->{numeric_threshold}->{$options{section}}}) { - if ($options{instance} =~ /$_->{regexp}/) { - push @{$exits}, $self->{perfdata}->threshold_check(value => $options{value}, threshold => [ { label => $_->{label}, exit_litteral => $_->{threshold} } ]); - $thresholds->{$_->{threshold}} = $self->{perfdata}->get_perfdata_for_output(label => $_->{label}); - $checked = 1; - } - } - $status = $self->{output}->get_most_critical(status => $exits) if (scalar(@{$exits}) > 0); - } - - return ($status, $thresholds->{warning}, $thresholds->{critical}, $checked); -} - -sub get_severity { - my ($self, %options) = @_; - my $status = 'UNKNOWN'; # default - - if (defined($self->{overload_th}->{$options{section}})) { - foreach (@{$self->{overload_th}->{$options{section}}}) { - if ($options{value} =~ /$_->{filter}/i) { - $status = $_->{status}; - return $status; - } - } - } - foreach (@{$thresholds->{$options{section}}}) { - if ($options{value} =~ /$$_[0]/i) { - $status = $$_[1]; - return $status; - } - } - - return $status; -} - 1; __END__ @@ -294,10 +136,10 @@ Check Hardware (Power Supplies, Fans, Temperatures, Raids, Disks, Health). Which component to check (Default: '.*'). Can be: 'fan', 'psu', 'temperature', 'raid', 'disk', 'health'. -=item B<--exclude> +=item B<--filter> -Exclude some parts (comma seperated list) (Example: --exclude=fan) -Can also exclude specific instance: --exclude=fan#1#,psu#3# +Exclude some parts (comma seperated list) (Example: --filter=fan --filter=psu) +Can also exclude specific instance: --filter=fan,1 =item B<--no-component> @@ -312,12 +154,12 @@ Example: --threshold-overload='fan,CRITICAL,^(?!(normal)$)' =item B<--warning> -Set warning threshold for temperatures (syntax: type,regexp,threshold) +Set warning threshold for 'temperature', 'fan' (syntax: type,regexp,threshold) Example: --warning='temperature,.*,30' =item B<--critical> -Set critical threshold for temperatures (syntax: type,regexp,threshold) +Set critical threshold for 'temperature', 'fan' (syntax: type,regexp,threshold) Example: --critical='temperature,.*,40' =back diff --git a/storage/dell/fluidfs/snmp/mode/hardware.pm b/storage/dell/fluidfs/snmp/mode/hardware.pm index a12d0b443..b147c8b7e 100644 --- a/storage/dell/fluidfs/snmp/mode/hardware.pm +++ b/storage/dell/fluidfs/snmp/mode/hardware.pm @@ -34,7 +34,7 @@ sub set_system { $self->{thresholds} = { ad => [ - ['Yes', 'OK'], + ['Yes|Optimal', 'OK'], ['.*', 'CRITICAL'], ], extservers => [ @@ -104,4 +104,4 @@ Example: --threshold-overload='overall,WARNING,^(?!(optimal))' =back -=cut \ No newline at end of file +=cut diff --git a/storage/hp/p2000/xmlapi/custom.pm b/storage/hp/p2000/xmlapi/custom.pm index 3aa80740f..90d523a32 100644 --- a/storage/hp/p2000/xmlapi/custom.pm +++ b/storage/hp/p2000/xmlapi/custom.pm @@ -178,7 +178,8 @@ sub DESTROY { if ($self->{logon} == 1) { $self->{http}->request(url_path => $self->{url_path} . 'exit', - header => ['dataType: api', 'sessionKey: ' . $self->{session_id}]); + header => ['Cookie: wbisessionkey=' . $self->{session_id} . '; wbiusername=' . $self->{username}, + 'dataType: api', 'sessionKey: '. $self->{session_id}]); } } @@ -189,7 +190,8 @@ sub get_infos { my $cmd = $options{cmd}; $cmd =~ s/ /\//g; my $response =$self->{http}->request(url_path => $self->{url_path} . $cmd, - header => ['dataType: api', 'sessionKey: '. $self->{session_id}]); + header => ['Cookie: wbisessionkey=' . $self->{session_id} . '; wbiusername=' . $self->{username}, + 'dataType: api', 'sessionKey: '. $self->{session_id}]); eval { $xpath = XML::XPath->new(xml => $response); @@ -200,6 +202,27 @@ sub get_infos { $self->{output}->option_exit(); } + # Check if there is an error + # + #Error + #1 + #The command is ambiguous. Please check the help for this command. + #-10028 + # + # + if (my $nodestatus = $xpath->find("//OBJECT[\@basetype='status']//PROPERTY[\@name='return-code']")) { + my @nodes = $nodestatus->get_nodelist(); + my $node = shift @nodes; + my $return_code = $node->string_value; + if ($return_code != 0) { + $nodestatus = $xpath->find("//OBJECT[\@basetype='status']//PROPERTY[\@name='response']"); + @nodes = $nodestatus->get_nodelist(); + $node = shift @nodes; + $self->{output}->add_option_msg(short_msg => $node->string_value); + $self->{output}->option_exit(); + } + } + my $results = {}; foreach my $node ($nodeset->get_nodelist()) { my $properties = {}; diff --git a/storage/hp/p2000/xmlapi/mode/components/sensors.pm b/storage/hp/p2000/xmlapi/mode/components/sensors.pm index 142aca58b..42520f6ce 100644 --- a/storage/hp/p2000/xmlapi/mode/components/sensors.pm +++ b/storage/hp/p2000/xmlapi/mode/components/sensors.pm @@ -49,20 +49,30 @@ sub check { key => 'sensor-name', properties_name => '^(value|sensor-type|status)$'); + # + # Capacitor Charge-Ctlr B + # 100% + # OK + # + # + # Overall Unit Status + # Warning + # Warning + # foreach my $sensor_id (keys %$results) { next if ($self->check_exclude(section => 'sensor', instance => $sensor_id)); $self->{components}->{sensor}->{total}++; my $state = $results->{$sensor_id}->{status}; - $results->{$sensor_id}->{value} =~ /\s*([0-9\.,]+)\s*(\S*)\s*/; - my ($value, $unit) = ($1, $2); - if (defined($sensor_type{$results->{$sensor_id}->{'sensor-type'}})) { + my ($value, $unit); + ($value, $unit) = ($1, $2) if ($results->{$sensor_id}->{value} =~ /\s*([0-9\.,]+)\s*(\S*)\s*/); + if (defined($results->{$sensor_id}->{'sensor-type'}) && defined($sensor_type{$results->{$sensor_id}->{'sensor-type'}})) { $unit = $sensor_type{$results->{$sensor_id}->{'sensor-type'}}->{unit}; } $self->{output}->output_add(long_msg => sprintf("sensor '%s' status is %s (value: %s %s).", - $sensor_id, $state, $value, $unit) + $sensor_id, $state, defined($value) ? $value : '-', defined($unit) ? $unit : '-') ); foreach (@conditions) { if ($state =~ /$$_[0]/i) { @@ -74,7 +84,7 @@ sub check { } $self->{output}->perfdata_add(label => $sensor_id, unit => $unit, - value => $value); + value => $value) if (defined($value)); } }