From b0971fda918c1135084a828b3cfe19f5502de118 Mon Sep 17 00:00:00 2001 From: omercier <32134301+omercier@users.noreply.github.com> Date: Mon, 30 Oct 2023 11:03:14 +0100 Subject: [PATCH 01/12] fix: "other" type of marker supply was not handled (#4711) --- src/hardware/printers/standard/rfc3805/mode/markersupply.pm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hardware/printers/standard/rfc3805/mode/markersupply.pm b/src/hardware/printers/standard/rfc3805/mode/markersupply.pm index 7bef33ee1..233d88310 100644 --- a/src/hardware/printers/standard/rfc3805/mode/markersupply.pm +++ b/src/hardware/printers/standard/rfc3805/mode/markersupply.pm @@ -28,6 +28,7 @@ use centreon::plugins::misc; # 1 means: do percent calc my %unit_managed = ( + 1 => 1, # other(1), 3 => 1, # tenThousandthsOfInches(3), -- .0001 4 => 1, # micrometers(4), 7 => 1, # impressions(7), @@ -171,7 +172,7 @@ __END__ =head1 MODE -Check marker supply usages. +Check marker supplies usage. =over 8 @@ -185,7 +186,7 @@ Critical threshold in percent. =item B<--filter> -Filter maker supply instance. +Filter marker supply instances. =back From 7d6b38da36a70f454f8463d6ca4f415f3f5442a2 Mon Sep 17 00:00:00 2001 From: omercier <32134301+omercier@users.noreply.github.com> Date: Mon, 30 Oct 2023 11:23:44 +0100 Subject: [PATCH 02/12] fix: bad status (critical instead of warning) (#4712) --- src/hardware/server/hp/ilo/xmlapi/mode/hardware.pm | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/hardware/server/hp/ilo/xmlapi/mode/hardware.pm b/src/hardware/server/hp/ilo/xmlapi/mode/hardware.pm index fe34b7ae6..5b8fc1245 100644 --- a/src/hardware/server/hp/ilo/xmlapi/mode/hardware.pm +++ b/src/hardware/server/hp/ilo/xmlapi/mode/hardware.pm @@ -41,6 +41,7 @@ sub set_system { ['NOT APPLICABLE', 'OK'], ['n/a', 'OK'], ['Unknown', 'UNKNOWN'], + ['Warning', 'WARNING'], ['.*', 'CRITICAL'] ], nic => [ @@ -86,19 +87,19 @@ Check hardware. =item B<--component> -Which component to check (Default: '.*'). +Define a regular expression to select which components to check (default: '.*'). Can be: 'fan', 'temperature', 'vrm', 'psu', 'cpu', 'memory', 'nic', 'battery', 'ctrl', 'driveencl', 'pdrive', 'ldrive', 'bios'. =item B<--filter> -Exclude the items given as a comma-separated list (example: --filter=temperature --filter=fan). +Exclude the given items (example: --filter=temperature --filter=fan). You can also exclude items from specific instances: --filter="fan,Fan Block 1" =item B<--absent-problem> -Return an error if an entity is not 'present' (default is skipping) -Can be specific or global: --absent-problem="fan,Fan Block 1" +Return an error if an entity is not 'present' (default is skipping). +Can be specific or global (example: --absent-problem="fan,Fan Block 1"). =item B<--no-component> @@ -111,12 +112,12 @@ Example: --threshold-overload='fan,OK,degraded' =item B<--warning> -Set warning threshold for 'temperature', 'fan' (syntax: type,regexp,threshold) +Define the warning threshold for 'temperature', 'fan'. Syntax: type,regexp,threshold. Example: --warning='temperature,.*,30' =item B<--critical> -Set critical threshold for 'temperature', 'fan' (syntax: type,regexp,threshold) +Define the critical threshold for 'temperature', 'fan'. Syntax: type,regexp,threshold. Example: --critical='temperature,.*,50' =back From 0dbbc6414eb58f788b61479afd5dbfac03c74cea Mon Sep 17 00:00:00 2001 From: hamzabessa <148857497+hamzabessa@users.noreply.github.com> Date: Tue, 31 Oct 2023 11:58:53 +0100 Subject: [PATCH 03/12] feat(ci): add linting to worflow and actions files (#4718) Co-authored-by: Kevin Duret --- .github/workflows/actionlint.yml | 68 ++++++++++++++++++++++++++++++++ .github/workflows/nrpe.yml | 2 +- 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/actionlint.yml diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml new file mode 100644 index 000000000..c1c365d44 --- /dev/null +++ b/.github/workflows/actionlint.yml @@ -0,0 +1,68 @@ +name: actionlint + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +on: + pull_request: + branches: + - develop + - master + - hotfix-* + - release-* + paths: + - ".github/**" + +jobs: + actionlint: + runs-on: ubuntu-22.04 + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Download actionlint + id: get_actionlint + run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) + shell: bash + + - name: Check workflow files + run: | + ${{ steps.get_actionlint.outputs.executable }} \ + -ignore 'label "common" is unknown' \ + -ignore 'label "veracode" is unknown' \ + -ignore '"github.head_ref" is potentially untrusted' \ + -shellcheck= \ + -pyflakes= \ + -color + shell: bash + yaml-lint: + runs-on: ubuntu-22.04 + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Install Yaml + run: | + pip install yamllint==1.32.0 + + - name: Add Yaml Lint Rules + run: | + cat <>./yamllint_rules.yml + extends: default + + rules: + document-start: disable + line-length: disable + truthy: + check-keys: false + level: error + indentation: + spaces: 2 + indent-sequences: true + check-multi-line-strings: false + EOF + + - name: Lint YAML files + run: | + yamllint -c ./yamllint_rules.yml ./.github/actions/ ./.github/workflows/ diff --git a/.github/workflows/nrpe.yml b/.github/workflows/nrpe.yml index 64ebca44f..64fdb4687 100644 --- a/.github/workflows/nrpe.yml +++ b/.github/workflows/nrpe.yml @@ -130,7 +130,7 @@ jobs: artifactory_token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }} deliver-deb: - needs: [get-environment ,package] + needs: [get-environment, package] if: ${{ contains(fromJson('["stable", "testing", "unstable"]'), needs.get-environment.outputs.stability) }} runs-on: [self-hosted, common] From b3f4132f6ee971362cdb7b7444c44c8090e26135 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Thu, 2 Nov 2023 17:46:08 +0100 Subject: [PATCH 04/12] fix(typo): isensitive by insensitive (#4660) --- src/apps/centreon/local/mode/notsodummy.pm | 4 +- src/apps/vmware/vcsa/snmp/mode/storage.pm | 2 +- src/centreon/common/ibm/nos/snmp/mode/disk.pm | 2 +- src/network/libraesva/snmp/mode/storage.pm | 2 +- src/network/mikrotik/snmp/mode/disk.pm | 2 +- src/network/mikrotik/snmp/mode/memory.pm | 2 +- src/network/paloalto/snmp/mode/memory.pm | 2 +- src/network/sonus/sbc/snmp/mode/storage.pm | 2 +- src/network/stonesoft/snmp/mode/storage.pm | 93 +++++++++++-------- src/os/hpux/local/mode/inodes.pm | 11 ++- src/os/hpux/local/mode/storage.pm | 5 +- src/snmp_standard/mode/diskio.pm | 11 ++- src/snmp_standard/mode/diskusage.pm | 1 + src/snmp_standard/mode/inodes.pm | 5 +- src/snmp_standard/mode/listdiskspath.pm | 5 +- src/snmp_standard/mode/liststorages.pm | 5 +- src/snmp_standard/mode/storage.pm | 5 +- src/snmp_standard/mode/stringvalue.pm | 5 +- src/storage/emc/DataDomain/mode/filesystem.pm | 11 ++- 19 files changed, 102 insertions(+), 73 deletions(-) diff --git a/src/apps/centreon/local/mode/notsodummy.pm b/src/apps/centreon/local/mode/notsodummy.pm index 7f765de5c..ee8bec784 100644 --- a/src/apps/centreon/local/mode/notsodummy.pm +++ b/src/apps/centreon/local/mode/notsodummy.pm @@ -71,11 +71,11 @@ sub check_options { foreach my $status (split(',', $self->{option_results}->{status_sequence})) { if (!defined($self->{option_results}->{host}) && $status !~ /^[0-3]$/ && $status !~ /ok|warning|critical|unknown/i) { - $self->{output}->add_option_msg(short_msg => "Status should be in '0,1,2,3' or 'ok,warning,critical,unknown' (case isensitive)."); + $self->{output}->add_option_msg(short_msg => "Status should be in '0,1,2,3' or 'ok,warning,critical,unknown' (case insensitive)."); $self->{output}->option_exit(); } if (defined($self->{option_results}->{host}) && $status !~ /^[0-1]$/ && $status !~ /up|down/i) { - $self->{output}->add_option_msg(short_msg => "Status should be in '0,1' or 'up,down' (case isensitive)."); + $self->{output}->add_option_msg(short_msg => "Status should be in '0,1' or 'up,down' (case insensitive)."); $self->{output}->option_exit(); } push @{$self->{status_sequence}}, $status; diff --git a/src/apps/vmware/vcsa/snmp/mode/storage.pm b/src/apps/vmware/vcsa/snmp/mode/storage.pm index 5451c92c9..16ea6eb87 100644 --- a/src/apps/vmware/vcsa/snmp/mode/storage.pm +++ b/src/apps/vmware/vcsa/snmp/mode/storage.pm @@ -82,7 +82,7 @@ Allows to use storage name with option --storage instead of storage oid index. Allows to use regexp to filter storage (with option --name). -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive (with --regexp). diff --git a/src/centreon/common/ibm/nos/snmp/mode/disk.pm b/src/centreon/common/ibm/nos/snmp/mode/disk.pm index b051c8b64..e0fbbb14d 100644 --- a/src/centreon/common/ibm/nos/snmp/mode/disk.pm +++ b/src/centreon/common/ibm/nos/snmp/mode/disk.pm @@ -83,7 +83,7 @@ Allows to use storage name with option --storage instead of storage oid index. Allows to use regexp to filter storage (with option --name). -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive (with --regexp). diff --git a/src/network/libraesva/snmp/mode/storage.pm b/src/network/libraesva/snmp/mode/storage.pm index 858e9e2c7..e4a4d9502 100644 --- a/src/network/libraesva/snmp/mode/storage.pm +++ b/src/network/libraesva/snmp/mode/storage.pm @@ -82,7 +82,7 @@ Allows to use storage name with option --storage instead of storage oid index. Allows to use regexp to filter storage (with option --name). -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive (with --regexp). diff --git a/src/network/mikrotik/snmp/mode/disk.pm b/src/network/mikrotik/snmp/mode/disk.pm index 9402af5e2..ff9c7c565 100644 --- a/src/network/mikrotik/snmp/mode/disk.pm +++ b/src/network/mikrotik/snmp/mode/disk.pm @@ -83,7 +83,7 @@ Allows to use storage name with option --storage instead of storage oid index. Allows to use regexp to filter storage (with option --name). -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive (with --regexp). diff --git a/src/network/mikrotik/snmp/mode/memory.pm b/src/network/mikrotik/snmp/mode/memory.pm index 691ec1990..f31329f63 100644 --- a/src/network/mikrotik/snmp/mode/memory.pm +++ b/src/network/mikrotik/snmp/mode/memory.pm @@ -83,7 +83,7 @@ Allows to use storage name with option --storage instead of storage oid index. Allows to use regexp to filter storage (with option --name). -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive (with --regexp). diff --git a/src/network/paloalto/snmp/mode/memory.pm b/src/network/paloalto/snmp/mode/memory.pm index cc9262feb..7c41736c6 100644 --- a/src/network/paloalto/snmp/mode/memory.pm +++ b/src/network/paloalto/snmp/mode/memory.pm @@ -77,7 +77,7 @@ Allows to use storage name with option --storage instead of storage oid index. Allows to use regexp to filter storage (with option --name). -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive (with --regexp). diff --git a/src/network/sonus/sbc/snmp/mode/storage.pm b/src/network/sonus/sbc/snmp/mode/storage.pm index 0af99cc32..79352c2f4 100644 --- a/src/network/sonus/sbc/snmp/mode/storage.pm +++ b/src/network/sonus/sbc/snmp/mode/storage.pm @@ -82,7 +82,7 @@ Allows to use storage name with option --storage instead of storage oid index. Allows to use regexp to filter storage (with option --name). -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive (with --regexp). diff --git a/src/network/stonesoft/snmp/mode/storage.pm b/src/network/stonesoft/snmp/mode/storage.pm index e2cb5ae42..e0e4308f2 100644 --- a/src/network/stonesoft/snmp/mode/storage.pm +++ b/src/network/stonesoft/snmp/mode/storage.pm @@ -34,16 +34,16 @@ sub new { my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; - $options{options}->add_options(arguments => - { - "warning:s" => { name => 'warning' }, - "critical:s" => { name => 'critical' }, - "units:s" => { name => 'units', default => '%' }, - "free" => { name => 'free' }, - "storage:s" => { name => 'storage' }, - "regexp" => { name => 'use_regexp' }, - "regexp-isensitive" => { name => 'use_regexpi' }, - }); + $options{options}->add_options(arguments => { + 'warning:s' => { name => 'warning' }, + 'critical:s' => { name => 'critical' }, + 'units:s' => { name => 'units', default => '%' }, + 'free' => { name => 'free' }, + 'storage:s' => { name => 'storage' }, + 'regexp' => { name => 'use_regexp' }, + 'regexp-isensitive' => { name => 'use_regexpi' }, # compatibility + 'regexp-insensitive' => { name => 'use_regexpi' } + }); $self->{storage_id_selected} = []; @@ -98,17 +98,25 @@ sub run { my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $total_used); my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => ($total_size - $total_used)); - $self->{output}->output_add(long_msg => sprintf("Partition '%s' Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $name_storage, - $total_size_value . " " . $total_size_unit, - $total_used_value . " " . $total_used_unit, $prct_used, - $total_free_value . " " . $total_free_unit, $prct_free)); + $self->{output}->output_add( + long_msg => sprintf( + "Partition '%s' Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $name_storage, + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $prct_used, + $total_free_value . " " . $total_free_unit, $prct_free + ) + ); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1) || (defined($self->{option_results}->{storage}) && !defined($self->{option_results}->{use_regexp}))) { - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Partition '%s' Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $name_storage, - $total_size_value . " " . $total_size_unit, - $total_used_value . " " . $total_used_unit, $prct_used, - $total_free_value . " " . $total_free_unit, $prct_free)); - } + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "Partition '%s' Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $name_storage, + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $prct_used, + $total_free_value . " " . $total_free_unit, $prct_free + ) + ); + } my $label = 'used'; my $value_perf = $total_used; @@ -123,21 +131,29 @@ sub run { $total_options{total} = $total_size; $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', %total_options), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', %total_options), - min => 0, max => $total_size); + + $self->{output}->perfdata_add( + label => $label . $extra_label, + unit => 'B', + value => $value_perf, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', %total_options), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', %total_options), + min => 0, max => $total_size + ); } if (!defined($self->{option_results}->{storage}) || defined($self->{option_results}->{use_regexp})) { - $self->{output}->output_add(severity => 'OK', - short_msg => 'All partitions are ok.'); + $self->{output}->output_add( + severity => 'OK', + short_msg => 'All partitions are ok.' + ); } elsif ($num_disk_check == 0) { - $self->{output}->output_add(severity => 'OK', - short_msg => 'No usage for partition.'); + $self->{output}->output_add( + severity => 'OK', + short_msg => 'No usage for partition.' + ); } - + $self->{output}->display(); $self->{output}->exit(); } @@ -145,12 +161,15 @@ sub run { sub manage_selection { my ($self, %options) = @_; - $self->{results} = $self->{snmp}->get_multiple_table(oids => [ - { oid => $oid_fwMountPointName }, - { oid => $oid_fwPartitionSize }, - { oid => $oid_fwPartitionUsed } - ], - nothing_quit => 1); + $self->{results} = $self->{snmp}->get_multiple_table( + oids => [ + { oid => $oid_fwMountPointName }, + { oid => $oid_fwPartitionSize }, + { oid => $oid_fwPartitionUsed } + ], + nothing_quit => 1 + ); + foreach my $key ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_fwMountPointName}})) { $key =~ /\.([0-9]+)$/; my $instance = $1; @@ -222,7 +241,7 @@ Set the storage name (empty means 'check all storage'). Allows to use regexp to filter storage. -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive (with --regexp). diff --git a/src/os/hpux/local/mode/inodes.pm b/src/os/hpux/local/mode/inodes.pm index d5aa7b4ff..d0ff400d4 100644 --- a/src/os/hpux/local/mode/inodes.pm +++ b/src/os/hpux/local/mode/inodes.pm @@ -57,10 +57,11 @@ sub new { bless $self, $class; $options{options}->add_options(arguments => { - 'filter-fs:s' => { name => 'filter_fs', }, - 'name:s' => { name => 'name' }, - 'regexp' => { name => 'use_regexp' }, - 'regexp-isensitive' => { name => 'use_regexpi' } + 'filter-fs:s' => { name => 'filter_fs', }, + 'name:s' => { name => 'name' }, + 'regexp' => { name => 'use_regexp' }, + 'regexp-isensitive' => { name => 'use_regexpi' }, # compatibility + 'regexp-insensitive' => { name => 'use_regexpi' } }); return $self; @@ -138,7 +139,7 @@ Set the storage mount point (empty means 'check all storages') Allows to use regexp to filter storage mount point (with option --name). -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive (with --regexp). diff --git a/src/os/hpux/local/mode/storage.pm b/src/os/hpux/local/mode/storage.pm index eb9c1b396..24ae719c3 100644 --- a/src/os/hpux/local/mode/storage.pm +++ b/src/os/hpux/local/mode/storage.pm @@ -134,7 +134,8 @@ sub new { 'free' => { name => 'free' }, 'name:s' => { name => 'name' }, 'regexp' => { name => 'use_regexp' }, - 'regexp-isensitive' => { name => 'use_regexpi' }, + 'regexp-isensitive' => { name => 'use_regexpi' }, # compatibility + 'regexp-insensitive' => { name => 'use_regexpi' }, 'space-reservation:s' => { name => 'space_reservation' } }); @@ -224,7 +225,7 @@ Set the storage mount point (empty means 'check all storages') Allows to use regexp to filter storage mount point (with option --name). -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive (with --regexp). diff --git a/src/snmp_standard/mode/diskio.pm b/src/snmp_standard/mode/diskio.pm index 61cb79dbb..dd3d6cbf0 100644 --- a/src/snmp_standard/mode/diskio.pm +++ b/src/snmp_standard/mode/diskio.pm @@ -145,10 +145,11 @@ sub new { bless $self, $class; $options{options}->add_options(arguments => { - 'name' => { name => 'use_name' }, - 'device:s' => { name => 'device' }, - 'regexp' => { name => 'use_regexp' }, - 'regexp-isensitive' => { name => 'use_regexpi' } + 'name' => { name => 'use_name' }, + 'device:s' => { name => 'device' }, + 'regexp' => { name => 'use_regexp' }, + 'regexp-isensitive' => { name => 'use_regexpi' }, # compatibility + 'regexp-insensitive' => { name => 'use_regexpi' } }); return $self; @@ -333,7 +334,7 @@ Allows to use device name with option --device instead of devoce oid index. Allows to use regexp to filter devices (with option --name). -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive (with --regexp). diff --git a/src/snmp_standard/mode/diskusage.pm b/src/snmp_standard/mode/diskusage.pm index e42858ddc..92bf6f50b 100644 --- a/src/snmp_standard/mode/diskusage.pm +++ b/src/snmp_standard/mode/diskusage.pm @@ -123,6 +123,7 @@ sub new { 'diskpath:s' => { name => 'diskpath' }, # legacy 'regexp' => { name => 'use_regexp' }, # legacy 'regexp-isensitive' => { name => 'use_regexpi' }, # legacy + 'regexp-insensitive' => { name => 'use_regexpi' }, # legacy 'display-transform-src:s' => { name => 'display_transform_src' }, 'display-transform-dst:s' => { name => 'display_transform_dst' }, 'show-cache' => { name => 'show_cache' }, diff --git a/src/snmp_standard/mode/inodes.pm b/src/snmp_standard/mode/inodes.pm index 944756d89..3dc921b09 100644 --- a/src/snmp_standard/mode/inodes.pm +++ b/src/snmp_standard/mode/inodes.pm @@ -61,7 +61,8 @@ sub new { 'name' => { name => 'use_name' }, 'diskpath:s' => { name => 'diskpath' }, 'regexp' => { name => 'use_regexp' }, - 'regexp-isensitive' => { name => 'use_regexpi' }, + 'regexp-isensitive' => { name => 'use_regexpi' }, # compatibility + 'regexp-insensitive' => { name => 'use_regexpi' }, 'filter-device:s' => { name => 'filter_device' }, 'filter-path:s' => { name => 'filter_path' }, 'display-transform-src:s' => { name => 'display_transform_src' }, @@ -200,7 +201,7 @@ Allows to use disk path name with option --diskpath instead of disk path oid ind Allows to use regexp to filter diskpath (with option --name). -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive (with --regexp). diff --git a/src/snmp_standard/mode/listdiskspath.pm b/src/snmp_standard/mode/listdiskspath.pm index 590b107fe..cf13354c5 100644 --- a/src/snmp_standard/mode/listdiskspath.pm +++ b/src/snmp_standard/mode/listdiskspath.pm @@ -39,7 +39,8 @@ sub new { 'diskpath:s' => { name => 'diskpath' }, 'name' => { name => 'use_name' }, 'regexp' => { name => 'use_regexp' }, - 'regexp-isensitive' => { name => 'use_regexpi' }, + 'regexp-isensitive' => { name => 'use_regexpi' }, # compatibility + 'regexp-insensitive' => { name => 'use_regexpi' }, 'display-transform-src:s' => { name => 'display_transform_src' }, 'display-transform-dst:s' => { name => 'display_transform_dst' }, 'skip-total-size-zero' => { name => 'skip_total_size_zero' } @@ -220,7 +221,7 @@ Allows to use disk path name with option --diskpath instead of disk path oid ind Allows to use regexp to filter diskpath (with option --name). -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive (with --regexp). diff --git a/src/snmp_standard/mode/liststorages.pm b/src/snmp_standard/mode/liststorages.pm index 8e5d1f3cd..961d01fed 100644 --- a/src/snmp_standard/mode/liststorages.pm +++ b/src/snmp_standard/mode/liststorages.pm @@ -82,7 +82,8 @@ sub new { 'storage:s' => { name => 'storage' }, 'name' => { name => 'use_name' }, 'regexp' => { name => 'use_regexp' }, - 'regexp-isensitive' => { name => 'use_regexpi' }, + 'regexp-insensitive' => { name => 'use_regexpi' }, + 'regexp-isensitive' => { name => 'use_regexpi' }, # compatibility 'oid-filter:s' => { name => 'oid_filter', default => 'hrStorageDescr'}, 'oid-display:s' => { name => 'oid_display', default => 'hrStorageDescr'}, 'display-transform-src:s' => { name => 'display_transform_src' }, @@ -301,7 +302,7 @@ Allows to use storage name with option --storage instead of storage oid index. Allows to use regexp to filter storage (with option --name). -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive (with --regexp). diff --git a/src/snmp_standard/mode/storage.pm b/src/snmp_standard/mode/storage.pm index 10b8b7308..336a6b101 100644 --- a/src/snmp_standard/mode/storage.pm +++ b/src/snmp_standard/mode/storage.pm @@ -252,7 +252,8 @@ sub new { 'name' => { name => 'use_name' }, 'storage:s' => { name => 'storage' }, 'regexp' => { name => 'use_regexp' }, - 'regexp-isensitive' => { name => 'use_regexpi' }, + 'regexp-isensitive' => { name => 'use_regexpi' }, # compatibility + 'regexp-insensitive' => { name => 'use_regexpi' }, 'path-best-match' => { name => 'use_path_best_match' }, 'oid-filter:s' => { name => 'oid_filter', default => 'hrStorageDescr'}, 'oid-display:s' => { name => 'oid_display', default => 'hrStorageDescr'}, @@ -644,7 +645,7 @@ Allows to use storage name with option --storage instead of storage oid index. Allows to use regexp to filter storage (with option --name). -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive (with --regexp). diff --git a/src/snmp_standard/mode/stringvalue.pm b/src/snmp_standard/mode/stringvalue.pm index 1cfd0ed3f..6d09a8706 100644 --- a/src/snmp_standard/mode/stringvalue.pm +++ b/src/snmp_standard/mode/stringvalue.pm @@ -42,7 +42,8 @@ sub new { 'warning-regexp:s' => { name => 'warning_regexp' }, 'critical-regexp:s' => { name => 'critical_regexp' }, 'unknown-regexp:s' => { name => 'unknown_regexp' }, - 'regexp-isensitive' => { name => 'use_iregexp' }, + 'regexp-isensitive' => { name => 'use_iregexp' }, # compatibility + 'regexp-insensitive' => { name => 'use_iregexp' }, 'warning-absent:s@' => { name => 'warning_absent' }, 'critical-absent:s@' => { name => 'critical_absent' }, @@ -360,7 +361,7 @@ Return Warning if an oid value match the regexp. Return Critical if an oid value match the regexp. -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive. diff --git a/src/storage/emc/DataDomain/mode/filesystem.pm b/src/storage/emc/DataDomain/mode/filesystem.pm index b4c709139..79a6b145f 100644 --- a/src/storage/emc/DataDomain/mode/filesystem.pm +++ b/src/storage/emc/DataDomain/mode/filesystem.pm @@ -91,10 +91,11 @@ sub new { bless $self, $class; $options{options}->add_options(arguments => { - 'name' => { name => 'use_name' }, - 'filesystem:s' => { name => 'filesystem' }, - 'regexp' => { name => 'use_regexp' }, - 'regexp-isensitive' => { name => 'use_regexpi' } + 'name' => { name => 'use_name' }, + 'filesystem:s' => { name => 'filesystem' }, + 'regexp' => { name => 'use_regexp' }, + 'regexp-isensitive' => { name => 'use_regexpi' }, # compatibility + 'regexp-insensitive' => { name => 'use_regexpi' } }); return $self; @@ -229,7 +230,7 @@ Allows to use filesystem name with option --filesystem instead of devoce oid ind Allows to use regexp to filter filesystems (with option --name). -=item B<--regexp-isensitive> +=item B<--regexp-insensitive> Allows to use regexp non case-sensitive to filter filesystems (with option --name). From de039a6a5cf6230ddb6ab994a605b12d9df28342 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Thu, 2 Nov 2023 17:50:03 +0100 Subject: [PATCH 05/12] add lang DE windows sessions (#4662) --- src/os/windows/local/mode/sessions.pm | 9 +++++++++ src/os/windows/wsman/mode/sessions.pm | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/os/windows/local/mode/sessions.pm b/src/os/windows/local/mode/sessions.pm index fe473dd3a..4402de157 100644 --- a/src/os/windows/local/mode/sessions.pm +++ b/src/os/windows/local/mode/sessions.pm @@ -135,6 +135,15 @@ sub read_config { NOMESESSIONE STATO + + Erstellte Sitzungen gesamt + Getrennte Sitzungen gesamt + Erneut verbundene Sitzungen gesamt + Aktiv + Getr\. + SITZUNGSNAME + STATUS + END_FILE diff --git a/src/os/windows/wsman/mode/sessions.pm b/src/os/windows/wsman/mode/sessions.pm index 037840664..ac9a6f373 100644 --- a/src/os/windows/wsman/mode/sessions.pm +++ b/src/os/windows/wsman/mode/sessions.pm @@ -126,6 +126,24 @@ sub read_config { SESSION ^.*?TAT + + Totale sessioni create + Totale sessioni disconnesse + Totale sessioni riconnesse + Attivo + Disc + NOMESESSIONE + STATO + + + Erstellte Sitzungen gesamt + Getrennte Sitzungen gesamt + Erneut verbundene Sitzungen gesamt + Aktiv + Getr\. + SITZUNGSNAME + STATUS + END_FILE From a33b359a40f18bc536d5a9c468e669712384c643 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Thu, 2 Nov 2023 17:54:02 +0100 Subject: [PATCH 06/12] enh(centreon/sql): add execution-time mode (#4614) --- .../centreon/sql/mode/countnotifications.pm | 47 +++--- src/apps/centreon/sql/mode/countproblems.pm | 38 +++-- src/apps/centreon/sql/mode/executiontime.pm | 140 ++++++++++++++++++ src/apps/centreon/sql/mode/partitioning.pm | 39 +++-- 4 files changed, 214 insertions(+), 50 deletions(-) create mode 100644 src/apps/centreon/sql/mode/executiontime.pm diff --git a/src/apps/centreon/sql/mode/countnotifications.pm b/src/apps/centreon/sql/mode/countnotifications.pm index b1e1914c9..6fe8d02e3 100644 --- a/src/apps/centreon/sql/mode/countnotifications.pm +++ b/src/apps/centreon/sql/mode/countnotifications.pm @@ -28,15 +28,15 @@ use centreon::plugins::statefile; sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; - $options{options}->add_options(arguments => - { - "warning:s" => { name => 'warning' }, - "critical:s" => { name => 'critical' }, - "centreon-storage-database:s" => { name => 'centreon_storage_database', default => 'centreon_storage' }, - }); + $options{options}->add_options(arguments => { + 'warning:s' => { name => 'warning' }, + 'critical:s' => { name => 'critical' }, + 'centreon-storage-database:s' => { name => 'centreon_storage_database', default => 'centreon_storage' } + }); + $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; @@ -67,19 +67,26 @@ sub execute { while ((my $row = $self->{sql}->fetchrow_hashref())) { $self->{output}->output_add(long_msg => sprintf("%d sent notifications from %s", $row->{num}, $row->{name})); $total_notifications += $row->{num}; - $self->{output}->perfdata_add(label => 'notifications_' . $row->{name}, - value => $row->{num}, - min => 0); + $self->{output}->perfdata_add( + nlabel => 'notifications.sent.count', + instances => $row->{name}, + value => $row->{num}, + min => 0 + ); } my $exit_code = $self->{perfdata}->threshold_check(value => $total_notifications, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - $self->{output}->output_add(severity => $exit_code, - short_msg => sprintf("%d total sent notifications", $total_notifications)); - $self->{output}->perfdata_add(label => 'total', - value => $total_notifications, - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), - min => 0); + $self->{output}->output_add( + severity => $exit_code, + short_msg => sprintf("%d total sent notifications", $total_notifications) + ); + $self->{output}->perfdata_add( + nlabel => 'notifications.sent.count', + value => $total_notifications, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), + min => 0 + ); } sub run { @@ -93,8 +100,10 @@ sub run { $self->{statefile_cache}->write(data => $new_datas); if (!defined($old_timestamp)) { - $self->{output}->output_add(severity => 'OK', - short_msg => "Buffer creation..."); + $self->{output}->output_add( + severity => 'OK', + short_msg => "Buffer creation..." + ); } else { $self->execute(time => $old_timestamp); } diff --git a/src/apps/centreon/sql/mode/countproblems.pm b/src/apps/centreon/sql/mode/countproblems.pm index 28e0c87bb..6ab91e8e5 100644 --- a/src/apps/centreon/sql/mode/countproblems.pm +++ b/src/apps/centreon/sql/mode/countproblems.pm @@ -28,13 +28,13 @@ use centreon::plugins::statefile; sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { 'warning:s' => { name => 'warning' }, 'critical:s' => { name => 'critical' }, - 'centreon-storage-database:s' => { name => 'centreon_storage_database', default => 'centreon_storage' }, + 'centreon-storage-database:s' => { name => 'centreon_storage_database', default => 'centreon_storage' } }); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); @@ -68,10 +68,10 @@ sub execute { while ((my $row = $self->{sql}->fetchrow_hashref())) { if (!defined($total_problems_by_poller->{$row->{name}})) { $total_problems_by_poller->{$row->{name}} = { - '0_1' => { label_perf => 'host_down', label => 'host down', num => 0 }, - '1_1' => { label_perf => 'service_warning', label => 'service warning', num => 0 }, - '1_2' => { label_perf => 'service_critical', label => 'service critical', num => 0 }, - '1_3' => { label_perf => 'service_unknown', label => 'service unknown', num => 0 } + '0_1' => { label_perf => 'hosts.down.count', label => 'host down', num => 0 }, + '1_1' => { label_perf => 'services.warning.count', label => 'service warning', num => 0 }, + '1_2' => { label_perf => 'services.critical.count', label => 'service critical', num => 0 }, + '1_3' => { label_perf => 'services.unknown.count', label => 'service unknown', num => 0 } }; } @@ -98,8 +98,10 @@ sub execute { $poller ) ); + $self->{output}->perfdata_add( - label => $total_problems_by_poller->{$poller}->{$id}->{label_perf} . "_" . $poller, + label => $total_problems_by_poller->{$poller}->{$id}->{label_perf}, + instances => $poller, value => $total_problems_by_poller->{$poller}->{$id}->{num}, min => 0 ); @@ -107,21 +109,25 @@ sub execute { } my $exit_code = $self->{perfdata}->threshold_check(value => $total_problems->{total}, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - $self->{output}->output_add(severity => $exit_code, - short_msg => sprintf("%d total problems", $total_problems->{total})); + $self->{output}->output_add( + severity => $exit_code, + short_msg => sprintf("%d total problems", $total_problems->{total}) + ); + $self->{output}->perfdata_add( - label => 'total', + nlabel => 'total.outage.count', value => $total_problems->{total}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), min => 0 ); $self->{output}->perfdata_add( - label => 'total_hosts', + nlabel => 'hosts.outage.count', value => $total_problems->{hosts}, - min => 0); + min => 0 + ); $self->{output}->perfdata_add( - label => 'total_services', + nlabel => 'services.outage.count', value => $total_problems->{services}, min => 0 ); @@ -137,8 +143,10 @@ sub run { $self->{statefile_cache}->write(data => $new_datas); if (!defined($old_timestamp)) { - $self->{output}->output_add(severity => 'OK', - short_msg => "Buffer creation..."); + $self->{output}->output_add( + severity => 'OK', + short_msg => "Buffer creation..." + ); } else { $self->execute(time => $old_timestamp); } diff --git a/src/apps/centreon/sql/mode/executiontime.pm b/src/apps/centreon/sql/mode/executiontime.pm new file mode 100644 index 000000000..7a37f71fd --- /dev/null +++ b/src/apps/centreon/sql/mode/executiontime.pm @@ -0,0 +1,140 @@ +# +# Copyright 2023 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::executiontime; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub custom_value_output { + my ($self, %options) = @_; + + return sprintf( + "Service '%s' of host '%s' execution time is '%.2fs'", + $self->{result_values}->{description}, + $self->{result_values}->{name}, + $self->{result_values}->{execution_time} + ); +} + + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 }, + { name => 'services', type => 1 } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'count', nlabel => 'services.execution.exceed.count', set => { + key_values => [ { name => 'count' } ], + output_template => 'Number of services exceeding execution time: %s', + perfdatas => [ + { template => '%s', min => 0 } + ] + } + } + ]; + + $self->{maps_counters}->{services} = [ + { label => 'list', set => { + key_values => [ { name => 'description' }, { name => 'name' } , { name => 'execution_time' } ], + closure_custom_output => $self->can('custom_value_output'), + closure_custom_perfdata => sub { return 0; } + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => { + 'filter-poller:s' => { name => 'filter_poller' }, + 'centreon-storage-database:s' => { name => 'centreon_storage_database', default => 'centreon_storage' }, + 'execution-time:s' => { name => 'execution_time', default => '20' } + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + $options{sql}->connect(); + $options{sql}->query( + query => 'SELECT h.name, s.description, s.execution_time + FROM ' . $self->{option_results}->{centreon_storage_database} . '.services s, ' . $self->{option_results}->{centreon_storage_database} . '.hosts h + WHERE s.execution_time > ' . $self->{option_results}->{execution_time} . ' + AND h.enabled = 1 + AND (h.name NOT LIKE "\_Module\_%" OR h.name LIKE "\_Module\_Meta%") + AND s.enabled = 1 + AND h.host_id = s.host_id' + ); + + $self->{global}->{count} = 0; + $self->{services} = {}; + while ((my $row = $options{sql}->fetchrow_hashref())) { + if (defined($self->{option_results}->{filter_poller}) && $self->{option_results}->{filter_poller} ne '' && + $row->{poller} !~ /$self->{option_results}->{filter_poller}/) { + $self->{output}->output_add(long_msg => "skipping '" . $row->{self} . "': no matching filter.", debug => 1); + next; + } + $self->{global}->{count}++; + $self->{services}->{ $row->{name} . "-" . $row->{description} } = $row; + } +} + +1; + +__END__ + +=head1 MODE + +Check the number of services exceeding defined execution time. + +=over 8 + +=item B<--execution-time> + +Set the number of seconds which defines the +limit of execution time (default: '20'). + +=item B<--centreon-storage-database> + +Centreon storage database name (default: 'centreon_storage'). + +=item B<--filter-poller> + +Filter by poller name (regexp can be used). + +=item B<--warning-count> B<--critical-count> + +Thresholds on the number of services exceeding +defined execution time. + +=back + +=cut diff --git a/src/apps/centreon/sql/mode/partitioning.pm b/src/apps/centreon/sql/mode/partitioning.pm index 2428b7a1c..611b98074 100644 --- a/src/apps/centreon/sql/mode/partitioning.pm +++ b/src/apps/centreon/sql/mode/partitioning.pm @@ -31,13 +31,12 @@ sub new { my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; - $options{options}->add_options(arguments => - { - "tablename:s@" => { name => 'tablename' }, - "timezone:s" => { name => 'timezone' }, - "warning:s" => { name => 'warning' }, - "critical:s" => { name => 'critical' }, - }); + $options{options}->add_options(arguments => { + "tablename:s@" => { name => 'tablename' }, + "timezone:s" => { name => 'timezone' }, + "warning:s" => { name => 'warning' }, + "critical:s" => { name => 'critical' } + }); return $self; } @@ -70,24 +69,30 @@ sub run { $self->{sql}->connect(); - $self->{output}->output_add(severity => 'OK', - short_msg => sprintf("All table partitions are up to date")); + $self->{output}->output_add( + severity => 'OK', + short_msg => sprintf("All table partitions are up to date") + ); foreach my $value (@{$self->{option_results}->{tablename}}) { next if ($value eq ''); if ($value !~ /(\S+)\.(\S+)/) { - $self->{output}->output_add(severity => 'UNKNOWN', - short_msg => sprintf("Wrong table name '%s'", $value)); + $self->{output}->output_add( + severity => 'UNKNOWN', + short_msg => sprintf("Wrong table name '%s'", $value) + ); next; } my ($database, $table) = ($1, $2); $self->{sql}->query(query => "SELECT MAX(CONVERT(PARTITION_DESCRIPTION, SIGNED INTEGER)) as lastPart FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='" . $table . "' AND TABLE_SCHEMA='" . $database . "' GROUP BY TABLE_NAME;"); my ($last_time) = $self->{sql}->fetchrow_array(); if (!defined($last_time)) { - $self->{output}->output_add(severity => 'UNKNOWN', - short_msg => sprintf("Couldn't get partition infos for table '%s'", $value)); + $self->{output}->output_add( + severity => 'UNKNOWN', + short_msg => sprintf("Couldn't get partition infos for table '%s'", $value) + ); next; } - + my $retention_forward_current = 0; my ($day,$month,$year) = (localtime(time))[3,4,5]; my $current_time = mktime(0, 0, 0, $day, $month, $year); @@ -99,8 +104,10 @@ sub run { $self->{output}->output_add(long_msg => sprintf("Table '%s' last partition date is %s (current retention forward in days: %s)", $value, scalar(localtime($last_time)), $retention_forward_current)); my $exit = $self->{perfdata}->threshold_check(value => $retention_forward_current, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Partitions for table '%s' are not up to date (current retention forward in days: %s)", $value, $retention_forward_current)); + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("Partitions for table '%s' are not up to date (current retention forward in days: %s)", $value, $retention_forward_current) + ); } } From 1f85378b5c70a3b8e9b007f7e5dbeca153ff3b2c Mon Sep 17 00:00:00 2001 From: qgarnier Date: Thu, 2 Nov 2023 17:56:15 +0100 Subject: [PATCH 07/12] (plugin) storage::ibm::storwize::ssh - metric v2 (#4649) --- .../storwize/ssh/mode/components/systemstats.pm | 1 - src/storage/ibm/storwize/ssh/mode/eventlog.pm | 5 +++-- src/storage/ibm/storwize/ssh/mode/hardware.pm | 2 +- src/storage/ibm/storwize/ssh/mode/poolusage.pm | 14 ++++++++------ 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/storage/ibm/storwize/ssh/mode/components/systemstats.pm b/src/storage/ibm/storwize/ssh/mode/components/systemstats.pm index d6dc46103..a6c234996 100644 --- a/src/storage/ibm/storwize/ssh/mode/components/systemstats.pm +++ b/src/storage/ibm/storwize/ssh/mode/components/systemstats.pm @@ -66,7 +66,6 @@ sub check { ); } $self->{output}->perfdata_add( - label => "sstat", nlabel => 'hardware.systemstats.current.count', instances => $_->{stat_name}, value => $_->{stat_current}, diff --git a/src/storage/ibm/storwize/ssh/mode/eventlog.pm b/src/storage/ibm/storwize/ssh/mode/eventlog.pm index 58c4faf70..5463dcc5e 100644 --- a/src/storage/ibm/storwize/ssh/mode/eventlog.pm +++ b/src/storage/ibm/storwize/ssh/mode/eventlog.pm @@ -28,7 +28,7 @@ use DateTime; sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { @@ -101,8 +101,9 @@ sub run { severity => $exit, short_msg => sprintf("%d problem detected (use verbose for more details)", $num_errors) ); + $self->{output}->perfdata_add( - label => 'problems', + nlabel => 'eventlogs.problems.count', value => $num_errors, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), diff --git a/src/storage/ibm/storwize/ssh/mode/hardware.pm b/src/storage/ibm/storwize/ssh/mode/hardware.pm index 6ced5388c..36ccf68f9 100644 --- a/src/storage/ibm/storwize/ssh/mode/hardware.pm +++ b/src/storage/ibm/storwize/ssh/mode/hardware.pm @@ -78,7 +78,7 @@ sub ssh_execute { sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); diff --git a/src/storage/ibm/storwize/ssh/mode/poolusage.pm b/src/storage/ibm/storwize/ssh/mode/poolusage.pm index 42f8a247a..e3e61ee92 100644 --- a/src/storage/ibm/storwize/ssh/mode/poolusage.pm +++ b/src/storage/ibm/storwize/ssh/mode/poolusage.pm @@ -35,10 +35,10 @@ sub custom_status_output { sub custom_usage_perfdata { my ($self, %options) = @_; - my $label = 'used'; + my $label = 'pool.space.usage.bytes'; my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { - $label = 'free'; + $label = 'pool.space.free.bytes'; $value_perf = $self->{result_values}->{free}; } @@ -49,12 +49,14 @@ sub custom_usage_perfdata { } $self->{output}->perfdata_add( - label => $label, unit => 'B', - instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, + nlabel => $label, + unit => 'B', + instances => $self->{result_values}->{display}, value => $value_perf, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, %total_options), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, %total_options), - min => 0, max => $self->{result_values}->{total} + min => 0, + max => $self->{result_values}->{total} ); } @@ -141,7 +143,7 @@ sub set_counters { sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { From c9021513d1328ff94eb1aa20c4f74a39b810ba7b Mon Sep 17 00:00:00 2001 From: qgarnier Date: Tue, 7 Nov 2023 11:42:07 +0100 Subject: [PATCH 08/12] enh(email/alert): do not retrieve service graph if no credentials (#4663) Co-authored-by: Colin Gagnaire --- src/notification/email/mode/alert.pm | 111 +++++++++++++++------------ 1 file changed, 60 insertions(+), 51 deletions(-) diff --git a/src/notification/email/mode/alert.pm b/src/notification/email/mode/alert.pm index f54ed6ef2..1aba979c8 100644 --- a/src/notification/email/mode/alert.pm +++ b/src/notification/email/mode/alert.pm @@ -129,13 +129,12 @@ sub new { 'service-attempts:s' => { name => 'service_attempts'}, 'max-service-attempts:s' => { name => 'max_service_attempts'}, 'service-duration:s' => { name => 'service_duration' }, + 'centreon-url:s' => { name => 'centreon_url' }, 'centreon-user:s' => { name => 'centreon_user' }, - 'centreon-token:s' => { name => 'centreon_tooken' }, + 'centreon-token:s' => { name => 'centreon_token' }, 'date:s' => { name => 'date' }, 'notif-author:s' => { name => 'notif_author'}, 'notif-comment:s' => { name => 'notif_comment' }, - 'centreon-url:s' => { name => 'centreon_url' }, - 'centreon-token:s' => { name => 'centreon_token' }, 'type:s' => { name => 'type' }, 'timeout:s' => { name => 'timeout', default => 10 } }); @@ -568,23 +567,26 @@ sub service_message { } } - my $content = $self->{http}->request( - hostname => '', - full_url => $self->{option_results}->{centreon_url} . '/centreon/include/views/graphs/generateGraphs/generateImage.php?akey=' . $self->{option_results}->{centreon_token} . '&username=' . $self->{option_results}->{centreon_user} . '&hostname=' . $self->{option_results}->{host_name} . '&service='. $self->{option_results}->{service_description}, - timeout => $self->{option_results}->{timeout}, - unknown_status => '', - warning_status => '', - critical_status => '' - ); - - my $img; - if ($self->{http}->get_code() !~ /200/ || $content =~ /^OK/) { - $img = '

No graph

'; - } elsif ($content =~ /Access denied|Resource not found|Invalid token/) { - $img = '

Cannot retrieve graph: ' . $content . '

'; - } else { - $self->{payload_attachment}->{png} = $content; - $img = '\n"; + my $graph_html; + if ($self->{option_results}->{centreon_user} && $self->{option_results}->{centreon_user} ne '' + && $self->{option_results}->{centreon_token} && $self->{option_results}->{centreon_token} ne '') { + my $content = $self->{http}->request( + hostname => '', + full_url => $self->{option_results}->{centreon_url} . '/centreon/include/views/graphs/generateGraphs/generateImage.php?akey=' . $self->{option_results}->{centreon_token} . '&username=' . $self->{option_results}->{centreon_user} . '&hostname=' . $self->{option_results}->{host_name} . '&service='. $self->{option_results}->{service_description}, + timeout => $self->{option_results}->{timeout}, + unknown_status => '', + warning_status => '', + critical_status => '' + ); + + if ($self->{http}->get_code() !~ /200/ || $content =~ /^OK/) { + $graph_html = '

No graph

'; + } elsif ($content =~ /Access denied|Resource not found|Invalid token/) { + $graph_html = '

Cannot retrieve graph: ' . $content . '

'; + } else { + $self->{payload_attachment}->{graph_png} = $content; + $graph_html = '\n"; + } } my $details = { @@ -835,36 +837,42 @@ sub service_message { if (defined($author_html) && $author_html ne '') { $self->{payload_attachment}->{html_message} .= ' -   - - - '. - $author_html. ' - - - '; +   + + + '. + $author_html. ' + + + '; } + if (defined($comment_html) && $comment_html ne '') { $self->{payload_attachment}->{html_message} .= ' -   - - - '. - $comment_html. ' - - - '; - } - $self->{payload_attachment}->{html_message} .= ' +   + + + '. + $comment_html. ' + + + '; + } + + if (defined($graph_html) && $graph_html ne '') { + $self->{payload_attachment}->{html_message} .= '   - - -

Service Graph:

- '. $img . ' - - - + + +

Service Graph:

+ '. $graph_html . ' + + + '; + } + + $self->{payload_attachment}->{html_message} .= '     @@ -950,8 +958,8 @@ sub run { my $email; - if (defined($self->{payload_attachment}->{png}) && $self->{payload_attachment}->{png} ne '') { - my $img_cid = $self->{option_results}->{host_name} . '_' . $self->{option_results}->{service_description}; + if (defined($self->{payload_attachment}->{graph_png}) && $self->{payload_attachment}->{graph_png} ne '') { + my $graph_png_cid = $self->{option_results}->{host_name} . '_' . $self->{option_results}->{service_description}; $email = Email::MIME->create( header_str => [ @@ -969,7 +977,7 @@ sub run { ), Email::MIME->create( header_str => [ - 'Content-ID' => "<$img_cid>" + 'Content-ID' => "<$graph_png_cid>" ], attributes => { content_type => 'image/png', @@ -977,7 +985,7 @@ sub run { encoding => 'base64', name => $self->{option_results}->{host_name} . ' - ' . $self->{option_results}->{service_description} . '.png' }, - body => $self->{payload_attachment}->{png} + body => $self->{payload_attachment}->{graph_png} ) ] ); @@ -1139,11 +1147,12 @@ Duration of the service status. =item B<--centreon-user> -Username for the Centreon web interface. +Username for the Centreon web interface to retrieve +service's graph (leave empty to not retrieve and display graph). =item B<--centreon-token> -Token for the Centreon web interface (autologin). +Autologin token for the Centreon web interface (if --centreon-user is defined). =item B<--date> From bea1844582a1c21cc8cdeec0149ddf31297d7e23 Mon Sep 17 00:00:00 2001 From: Lucie Dubrunfaut <123162035+lucie-dubrunfaut@users.noreply.github.com> Date: Wed, 8 Nov 2023 09:32:05 +0100 Subject: [PATCH 09/12] [MON-21885] [Plugin] Bad incrementation in VMware health (#4716) --- src/apps/vmware/connector/mode/healthhost.pm | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/apps/vmware/connector/mode/healthhost.pm b/src/apps/vmware/connector/mode/healthhost.pm index 33061cda3..66bad79b9 100644 --- a/src/apps/vmware/connector/mode/healthhost.pm +++ b/src/apps/vmware/connector/mode/healthhost.pm @@ -257,9 +257,8 @@ sub manage_selection { $status = lc($1) if ($entry->{status} =~ /(yellow|red)/i); $self->{host}->{$host_name}->{global_problems}->{$status}++; $self->{host}->{$host_name}->{global_problems}->{total}++; - if ($status eq 'ok') { - $self->{host}->{$host_name}->{global_problems}->{total_problems}++ - } else { + if ($status ne 'ok') { + $self->{host}->{$host_name}->{global_problems}->{total_problems}++; $self->{host}->{$host_name}->{global_summary}->{$i} = { type => defined($entry->{type}) ? $entry->{type} : '', name => $entry->{name}, From a30702335388c83569dca7b3d9a79df283424301 Mon Sep 17 00:00:00 2001 From: Lucie Dubrunfaut <123162035+lucie-dubrunfaut@users.noreply.github.com> Date: Wed, 8 Nov 2023 09:35:30 +0100 Subject: [PATCH 10/12] [MON-22338] [Plugins] Improve the troubleshooting of HTTP Collections (#4708) Co-authored-by: omercier --- src/apps/protocols/http/mode/collection.pm | 69 ++++++++++++++++------ 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/src/apps/protocols/http/mode/collection.pm b/src/apps/protocols/http/mode/collection.pm index 3e3349612..3d1a4c51f 100644 --- a/src/apps/protocols/http/mode/collection.pm +++ b/src/apps/protocols/http/mode/collection.pm @@ -203,11 +203,11 @@ sub validate_name { my ($self, %options) = @_; if (!defined($options{name})) { - $self->{output}->add_option_msg(short_msg => "name attribute is missing $options{section}"); + $self->{output}->add_option_msg(short_msg => "name attribute is missing in your http collection (path: $options{section})"); $self->{output}->option_exit(); } if ($options{name} !~ /^[a-zA-Z0-9]+$/) { - $self->{output}->add_option_msg(short_msg => 'incorrect name attribute: ' . $options{name}); + $self->{output}->add_option_msg(short_msg => "name attribute in your http collection (path: $options{section}) is incorrect: " . $options{name}); $self->{output}->option_exit(); } } @@ -218,7 +218,7 @@ sub get_payload { return if (!defined($options{rq}->{payload}) || !defined($options{rq}->{payload}->{type})); if ($options{rq}->{payload}->{type} !~ /^(?:file|data|json)$/) { - $self->{output}->add_option_msg(short_msg => "type attribute is wrong [http > requests > $options{rq}->{name} > payload]"); + $self->{output}->add_option_msg(short_msg => "type attribute is wrong [http > requests > $options{rq}->{name} > payload] (allowed types: file / data / json)"); $self->{output}->option_exit(); } @@ -230,7 +230,7 @@ sub get_payload { my $content; if ($options{rq}->{payload}->{type} eq 'file') { if (ref($options{rq}->{payload}->{value}) ne '' || $options{rq}->{payload}->{value} eq '') { - $self->{output}->add_option_msg(short_msg => "value attribute is wrong [http > requests > $options{rq}->{name} > payload]"); + $self->{output}->add_option_msg(short_msg => "value attribute is wrong for file type [http > requests > $options{rq}->{name} > payload]"); $self->{output}->option_exit(); } @@ -243,7 +243,7 @@ sub get_payload { }; if ($@) { $self->{output}->output_add(long_msg => "json payload error: $@", debug => 1); - $self->{output}->add_option_msg(short_msg => "cannot encode json payload [http > requests > $options{rq}->{name} > payload]"); + $self->{output}->add_option_msg(short_msg => "cannot encode json type payload [http > requests > $options{rq}->{name} > payload]"); $self->{output}->option_exit(); } } @@ -337,6 +337,10 @@ sub call_http { $self->{output}->option_exit(); } + my $encoded = JSON::XS->new->utf8->pretty->encode($content); + $self->{output}->output_add(long_msg => '======> returned JSON structure:', debug => 1); + $self->{output}->output_add(long_msg => "$encoded", debug => 1); + return ($http->get_header(), $content, $http); } @@ -455,11 +459,23 @@ sub parse_structure { my $ref = ref($value); if ($ref eq 'HASH') { + if (!defined($value->{ $_->{id} })) { - $entry->{ $_->{id} } = ''; - next; + # Check and assume in case of hash reference first part is the hash ref and second the hash key + if($_->{id} =~ /^(.+?)\.(.*)$/){ + if (!defined($value->{$1}->{$2})) { + $entry->{ $_->{id} } = ''; + next; + }else{ + $entry->{ $_->{id} } = $value->{$1}->{$2}; + } + }else { + $entry->{ $_->{id} } = ''; + next; + } + }else { + $entry->{ $_->{id} } = $value->{ $_->{id} }; } - $entry->{ $_->{id} } = $value->{ $_->{id} }; } elsif (ref($value) eq 'ARRAY') { next; } elsif ($ref eq '' || $ref eq 'JSON::PP::Boolean') { @@ -764,7 +780,14 @@ sub exist_table_name { sub get_local_variable { my ($self, %options) = @_; - return $self->{expand}->{ $options{name} }; + if (defined( $self->{expand}->{ $options{name} })) { + return $self->{expand}->{ $options{name} }; + } else { + $self->{output}->add_option_msg(short_msg => "Key '" . $options{name} . "' not found in ('" . join("', '", keys(%{$self->{expand}})) . "')", debug => 1); + return undef; + } + + } sub set_local_variable { @@ -776,19 +799,24 @@ sub set_local_variable { sub get_table { my ($self, %options) = @_; - return undef if ( - !defined($self->{http_collected}->{tables}->{ $options{table} }) - ); + if (!defined($self->{http_collected}->{tables}->{ $options{table} })) { + $self->{output}->add_option_msg(short_msg => "Table '" . $options{table} . "' not found in ('" . join("', '", keys(%{$self->{http_collected}->{tables}})) . "')", debug => 1); + return undef; + } return $self->{http_collected}->{tables}->{ $options{table} }; } sub get_table_instance { my ($self, %options) = @_; - return undef if ( - !defined($self->{http_collected}->{tables}->{ $options{table} }) || - !defined($self->{http_collected}->{tables}->{ $options{table} }->{ $options{instance} }) - ); + if (!defined($self->{http_collected}->{tables}->{ $options{table} })) { + $self->{output}->add_option_msg(short_msg => "Table '" . $options{table} . "' not found in ('" . join("', '", keys(%{$self->{http_collected}->{tables}})) . "')", debug => 1); + return undef; + } + if (!defined($self->{http_collected}->{tables}->{ $options{table} }->{ $options{instance} })) { + $self->{output}->add_option_msg(short_msg => "Table '" . $options{instance} . "' not found in ('" . join("', '", keys(%{$self->{http_collected}->{tables}->{ $options{table} }})) . "')", debug => 1); + return undef; + } return $self->{http_collected}->{tables}->{ $options{table} }->{ $options{instance} }; } @@ -914,7 +942,8 @@ sub parse_http_tables { $self->{output}->option_exit(); } if (!$self->exist_table_name(name => $table_label)) { - $self->{output}->add_option_msg(short_msg => $self->{current_section} . " unknown table '$table_label'"); + my @names = keys %{$self->{http_collected}->{tables}}; + $self->{output}->add_option_msg(short_msg => $self->{current_section} . " unknown or empty table '$table_label'. Available tables are (not empty based on your conf) : @names"); $self->{output}->option_exit(); } if ($options{chars}->[$end] eq ')') { @@ -1721,8 +1750,12 @@ sub check_filter2 { sub check_filter_option { my ($self, %options) = @_; - foreach (keys %{$self->{option_results}->{filter_selection}}) { + + if(!defined($self->{expand}->{$_}) && grep {/^src\./} keys(%{$self->{expand}}) ne '') { + $self->{output}->add_option_msg(long_msg => "Wrong filter-selection - Available attributes for filtering: " . join(", ", grep {/^src\./} keys(%{$self->{expand}})), debug => 1); + } + return 1 if ( defined($self->{expand}->{$_}) && $self->{option_results}->{filter_selection}->{$_} ne '' && $self->{expand}->{$_} !~ /$self->{option_results}->{filter_selection}->{$_}/ From 61e25f641586f2f88775fb3ca840989cdc5e45d9 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Mon, 13 Nov 2023 09:36:20 +0100 Subject: [PATCH 11/12] (plugin) os::windows::snmp - mode service add total counter (#4606) --- src/os/windows/snmp/mode/service.pm | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/os/windows/snmp/mode/service.pm b/src/os/windows/snmp/mode/service.pm index 2d5d91fce..6a7151608 100644 --- a/src/os/windows/snmp/mode/service.pm +++ b/src/os/windows/snmp/mode/service.pm @@ -56,6 +56,14 @@ sub set_counters { ]; $self->{maps_counters}->{global} = [ + { label => 'total', nlabel => 'services.total.count', display_ok => 0, set => { + key_values => [ { name => 'total' } ], + output_template => 'total: %d', + perfdatas => [ + { template => '%d', min => 0 } + ] + } + }, { label => 'active', nlabel => 'services.active.count', display_ok => 0, set => { key_values => [ { name => 'active' } ], output_template => 'active: %d', @@ -123,10 +131,10 @@ sub check_options { # Compatibility for deprecated options if (defined($options{option_results}->{warning}) && $options{option_results}->{warning} ne '') { - $options{option_results}->{'warning-service-active-count'} = $options{option_results}->{warning}; + $options{option_results}->{'warning-services-active-count'} = $options{option_results}->{warning}; } if (defined($options{option_results}->{critical}) && $options{option_results}->{critical} ne '') { - $options{option_results}->{'critical-service-active-count'} = $options{option_results}->{critical}; + $options{option_results}->{'critical-services-active-count'} = $options{option_results}->{critical}; } my $delimiter = ''; @@ -190,10 +198,11 @@ sub manage_selection { ); $self->{global} = { - 'active' => 0, + total => 0, + active => 0, 'continue-pending' => 0, 'pause-pending' => 0, - 'paused' => 0 + paused => 0 }; $self->{services} = {}; @@ -218,13 +227,9 @@ sub manage_selection { operating_state => $result->{operating_state}, installed_state => $result->{installed_state} }; - - $self->{global}->{ $result->{operating_state} }++; - } - if (scalar(keys %{$self->{services}}) <= 0) { - $self->{output}->add_option_msg(short_msg => "No service found."); - $self->{output}->option_exit(); + $self->{global}->{total}++; + $self->{global}->{ $result->{operating_state} }++; } } @@ -250,7 +255,7 @@ You can use the following variables: %{operating_state}, %{installed_state}. =item B<--warning-*> B<--critical-*> Thresholds on services count. -Can be: 'active', 'continue-pending', +Can be: 'total', 'active', 'continue-pending', 'pause-pending', 'paused'. =item B<--warning> From c9831fb55c905740322e949d63e612ca5c2d9371 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Mon, 13 Nov 2023 10:16:51 +0100 Subject: [PATCH 12/12] (plugin) network::chapsvision::crossing::snmp - new (#4582) Co-authored-by: omercier <32134301+omercier@users.noreply.github.com> --- .../deb.json | 6 + .../pkg.json | 13 + .../rpm.json | 6 + .../crossing/snmp/mode/antivirus.pm | 283 ++++++++++++++++++ .../crossing/snmp/mode/interfaces.pm | 180 +++++++++++ .../chapsvision/crossing/snmp/plugin.pm | 49 +++ 6 files changed, 537 insertions(+) create mode 100644 packaging/centreon-plugin-Network-Chapsvision-Crossing-Snmp/deb.json create mode 100644 packaging/centreon-plugin-Network-Chapsvision-Crossing-Snmp/pkg.json create mode 100644 packaging/centreon-plugin-Network-Chapsvision-Crossing-Snmp/rpm.json create mode 100644 src/network/chapsvision/crossing/snmp/mode/antivirus.pm create mode 100644 src/network/chapsvision/crossing/snmp/mode/interfaces.pm create mode 100644 src/network/chapsvision/crossing/snmp/plugin.pm diff --git a/packaging/centreon-plugin-Network-Chapsvision-Crossing-Snmp/deb.json b/packaging/centreon-plugin-Network-Chapsvision-Crossing-Snmp/deb.json new file mode 100644 index 000000000..3eb4dc696 --- /dev/null +++ b/packaging/centreon-plugin-Network-Chapsvision-Crossing-Snmp/deb.json @@ -0,0 +1,6 @@ +{ + "dependencies": [ + "libsnmp-perl", + "libdatetime-format-strptime-perl" + ] +} diff --git a/packaging/centreon-plugin-Network-Chapsvision-Crossing-Snmp/pkg.json b/packaging/centreon-plugin-Network-Chapsvision-Crossing-Snmp/pkg.json new file mode 100644 index 000000000..5ad52b076 --- /dev/null +++ b/packaging/centreon-plugin-Network-Chapsvision-Crossing-Snmp/pkg.json @@ -0,0 +1,13 @@ +{ + "pkg_name": "centreon-plugin-Network-Chapsvision-Crossing-Snmp", + "pkg_summary": "Centreon Plugin ChapsVision CrossinG SNMP", + "plugin_name": "centreon_chapsvision_crossing_snmp.pl", + "files": [ + "centreon/plugins/script_snmp.pm", + "centreon/plugins/snmp.pm", + "snmp_standard/mode/listinterfaces.pm", + "snmp_standard/mode/resources/", + "snmp_standard/mode/interfaces.pm", + "network/chapsvision/crossing/snmp/" + ] +} diff --git a/packaging/centreon-plugin-Network-Chapsvision-Crossing-Snmp/rpm.json b/packaging/centreon-plugin-Network-Chapsvision-Crossing-Snmp/rpm.json new file mode 100644 index 000000000..84e108169 --- /dev/null +++ b/packaging/centreon-plugin-Network-Chapsvision-Crossing-Snmp/rpm.json @@ -0,0 +1,6 @@ +{ + "dependencies": [ + "perl(SNMP)", + "perl(DateTime::Format::Strptime)" + ] +} diff --git a/src/network/chapsvision/crossing/snmp/mode/antivirus.pm b/src/network/chapsvision/crossing/snmp/mode/antivirus.pm new file mode 100644 index 000000000..70c30c63f --- /dev/null +++ b/src/network/chapsvision/crossing/snmp/mode/antivirus.pm @@ -0,0 +1,283 @@ +# +# Copyright 2023 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::chapsvision::crossing::snmp::mode::antivirus; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; +use DateTime::Format::Strptime; +use DateTime; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); +use POSIX; + +my $unitdiv = { s => 1, w => 604800, d => 86400, h => 3600, m => 60 }; +my $unitdiv_long = { s => 'seconds', w => 'weeks', d => 'days', h => 'hours', m => 'minutes' }; + +sub custom_database_output { + my ($self, %options) = @_; + + return sprintf( + "database last update %s", + centreon::plugins::misc::change_seconds(value => $self->{result_values}->{db_lastupdate_time}) + ); +} + +sub custom_license_perfdata { + my ($self, %options) = @_; + + return if ($self->{result_values}->{expires_seconds} eq 'permanent'); + + $self->{output}->perfdata_add( + nlabel => $self->{nlabel} . '.' . $unitdiv_long->{ $self->{instance_mode}->{option_results}->{unit} }, + unit => $self->{instance_mode}->{option_results}->{unit}, + instances => $self->{result_values}->{name}, + value => floor($self->{result_values}->{expires_seconds} / $unitdiv->{ $self->{instance_mode}->{option_results}->{unit} }), + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), + min => 0 + ); +} + +sub custom_license_threshold { + my ($self, %options) = @_; + + return 'ok' if ($self->{result_values}->{expires_seconds} eq 'permanent'); + return $self->{perfdata}->threshold_check( + value => floor($self->{result_values}->{expires_seconds} / $unitdiv->{ $self->{instance_mode}->{option_results}->{unit} }), + threshold => [ + { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, + { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' }, + { label => 'unknown-'. $self->{thlabel}, exit_litteral => 'unknown' } + ] + ); +} + +sub custom_license_output { + my ($self, %options) = @_; + + my $message; + if ($self->{result_values}->{expires_seconds} eq 'permanent') { + $message = 'permanent license'; + } else { + $message = sprintf( + "license expires in %s", + $self->{result_values}->{expires_human} + ); + } + + return $message; +} + +sub custom_version_output { + my ($self, %options) = @_; + + return sprintf( + "version: %s", + $self->{result_values}->{version} + ); +} + +sub prefix_antivirus_output { + my ($self, %options) = @_; + + return "antivirus '" . $options{instance_value}->{name} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'antivirus', type => 1, cb_prefix_output => 'prefix_antivirus_output', message_multiple => 'All antivirus are ok', skipped_code => { -10 => 1 } } + ]; + + $self->{maps_counters}->{antivirus} = [ + { + label => 'version', + type => 2, + set => { + key_values => [ { name => 'name' }, { name => 'version' } ], + closure_custom_output => $self->can('custom_version_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + }, + { label => 'database-last-update', nlabel => 'antivirus.database.lastupdate.seconds', set => { + key_values => [ { name => 'db_lastupdate_time' }, { name => 'name' } ], + closure_custom_output => $self->can('custom_database_output'), + perfdatas => [ + { template => '%s', min => 0, unit => 's' } + ] + } + }, + { label => 'license-expires', nlabel => 'antivirus.license.expires', set => { + key_values => [ { name => 'expires_seconds' }, { name => 'expires_human' }, { name => 'name' } ], + closure_custom_output => $self->can('custom_license_output'), + closure_custom_perfdata => $self->can('custom_license_perfdata'), + closure_custom_threshold_check => $self->can('custom_license_threshold') + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => { + 'antivirus1-date-format:s' => { name => 'antivirus1_date_format' }, + 'antivirus2-date-format:s' => { name => 'antivirus2_date_format' }, + 'unit:s' => { name => 'unit', default => 's' } + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $self->{antivirus1_strp} = DateTime::Format::Strptime->new( + pattern => defined($self->{option_results}->{antivirus1_date_format}) && $self->{option_results}->{antivirus1_date_format} ne '' ? $self->{option_results}->{antivirus1_date_format} : '%Y/%m/%d', + on_error => 'undef' + ); + $self->{antivirus2_strp} = DateTime::Format::Strptime->new( + pattern => defined($self->{option_results}->{antivirus2_date_format}) && $self->{option_results}->{antivirus2_date_format} ne '' ? $self->{option_results}->{antivirus2_date_format} : '%Y/%m/%d', + on_error => 'undef' + ); + + if ($self->{option_results}->{unit} eq '' || !defined($unitdiv->{$self->{option_results}->{unit}})) { + $self->{option_results}->{unit} = 's'; + } +} + +my $mapping = { + antivirus1 => { + name => '.1.3.6.1.4.1.50853.1.2.6.1.1', + version => '.1.3.6.1.4.1.50853.1.2.6.1.2', + date => '.1.3.6.1.4.1.50853.1.2.6.1.3', + expiration => '.1.3.6.1.4.1.50853.1.2.6.1.4' + }, + antivirus2 => { + name => '.1.3.6.1.4.1.50853.1.2.6.2.1', + version => '.1.3.6.1.4.1.50853.1.2.6.2.2', + date => '.1.3.6.1.4.1.50853.1.2.6.2.3', + expiration => '.1.3.6.1.4.1.50853.1.2.6.2.4' + } +}; + +sub add_antivirus { + my ($self, %options) = @_; + + my $name = $options{snmp_result}->{ $mapping->{ $options{label} }->{name} }; + $self->{antivirus}->{$name} = { + name => $name, + version => $options{snmp_result}->{ $mapping->{ $options{label} }->{version} } + }; + + if ($options{snmp_result}->{ $mapping->{ $options{label} }->{expiration} } =~ /permanent/i) { + $self->{antivirus}->{$name}->{expires_seconds} = 'permanent'; + $self->{antivirus}->{$name}->{expires_human} = '-'; + } else { + my $dt = $self->{ $options{label} . '_strp' }->parse_datetime($options{snmp_result}->{ $mapping->{ $options{label} }->{expiration} }); + if (defined($dt)) { + $self->{antivirus}->{$name}->{expires_seconds} = $dt->epoch() - time(); + $self->{antivirus}->{$name}->{expires_seconds} = 0 if ($self->{antivirus}->{$name}->{expires_seconds} < 0); + $self->{antivirus}->{$name}->{expires_human} = centreon::plugins::misc::change_seconds(value => $self->{antivirus}->{$name}->{expires_seconds}); + } else { + $self->{output}->output_add(long_msg => "cannot parse date: " . $options{snmp_result}->{ $mapping->{ $options{label} }->{expiration} } . ' (please use option --' . $options{label} . '-date-format)'); + } + } + + my $dt = $self->{ $options{label} . '_strp' }->parse_datetime($options{snmp_result}->{ $mapping->{ $options{label} }->{date} }); + if (defined($dt)) { + $self->{antivirus}->{$name}->{db_lastupdate_time} = time() - $dt->epoch(); + } else { + $self->{output}->output_add(long_msg => "cannot parse date: " . $options{snmp_result}->{ $mapping->{ $options{label} }->{date} } . ' (please use option --' . $options{label} . '-date-format)'); + } +} + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $options{snmp}->get_leef( + oids => [ map($_, values(%{$mapping->{antivirus1}}), values(%{$mapping->{antivirus2}})) ], + nothing_quit => 1 + ); + + $self->{antivirus} = {}; + $self->add_antivirus(label => 'antivirus1', snmp_result => $snmp_result); + $self->add_antivirus(label => 'antivirus2', snmp_result => $snmp_result); +} + +1; + +__END__ + +=head1 MODE + +Check antivirus. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='version' + +=item B<--antivirus1-date-format> + +Define the date format for the first antivirus (default: '%Y/%m/%d'). + +=item B<--antivirus2-date-format> + +Define the date format for the second antivirus (default: '%Y/%m/%d'). + +=item B<--unknown-version> + +Define the conditions the version must match for the status to be UNKNOWN. +You can use the following variables: %{version}, %{name} + +=item B<--warning-version> + +Define the conditions the version must match for the status to be WARNING. +You can use the following variables: %{version}, %{name} + +=item B<--critical-version> + +Define the conditions the version must match for the status to be CRITICAL. +You can use the following variables: %{version}, %{name} + +=item B<--unit> + +Select the unit for the expired license threshold. May be 's' for seconds, 'm' for minutes, +'h' for hours, 'd' for days, 'w' for weeks. Default is seconds. + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'license-expires', 'database-last-update'. + +=back + +=cut diff --git a/src/network/chapsvision/crossing/snmp/mode/interfaces.pm b/src/network/chapsvision/crossing/snmp/mode/interfaces.pm new file mode 100644 index 000000000..e386ad414 --- /dev/null +++ b/src/network/chapsvision/crossing/snmp/mode/interfaces.pm @@ -0,0 +1,180 @@ +# +# Copyright 2023 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::chapsvision::crossing::snmp::mode::interfaces; + +use base qw(snmp_standard::mode::interfaces); + +use strict; +use warnings; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + return $self; +} + +1; + +__END__ + +=head1 MODE + +Check interfaces. + +=over 8 + +=item B<--add-global> + +Check global port statistics (By default if no --add-* option is set). + +=item B<--add-status> + +Check interface status. + +=item B<--add-duplex-status> + +Check duplex status (with --warning-status and --critical-status). + +=item B<--add-traffic> + +Check interface traffic. + +=item B<--add-errors> + +Check interface errors. + +=item B<--add-cast> + +Check interface cast. + +=item B<--add-speed> + +Check interface speed. + +=item B<--add-volume> + +Check interface data volume between two checks (not supposed to be graphed, useful for BI reporting). + +=item B<--check-metrics> + +If the expression is true, metrics are checked (Default: '%{opstatus} eq "up"'). + +=item B<--warning-status> + +Define the conditions to match for the status to be WARNING. +You can use the following variables: %{admstatus}, %{opstatus}, %{duplexstatus}, %{display} + +=item B<--critical-status> + +Define the conditions to match for the status to be CRITICAL (Default: '%{admstatus} eq "up" and %{opstatus} ne "up"'). +You can use the following variables: %{admstatus}, %{opstatus}, %{duplexstatus}, %{display} + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'total-port', 'total-admin-up', 'total-admin-down', 'total-oper-up', 'total-oper-down', +'in-traffic', 'out-traffic', 'in-error', 'in-discard', 'out-error', 'out-discard', +'in-ucast', 'in-bcast', 'in-mcast', 'out-ucast', 'out-bcast', 'out-mcast', +'speed' (b/s). + +=item B<--units-traffic> + +Units of thresholds for the traffic (Default: 'percent_delta') ('percent_delta', 'bps', 'counter'). + +=item B<--units-errors> + +Units of thresholds for errors/discards (Default: 'percent_delta') ('percent_delta', 'percent', 'delta', 'deltaps', 'counter'). + +=item B<--units-cast> + +Units of thresholds for communication types (Default: 'percent_delta') ('percent_delta', 'percent', 'delta', 'deltaps', 'counter'). + +=item B<--nagvis-perfdata> + +Display traffic perfdata to be compatible with nagvis widget. + +=item B<--interface> + +Set the interface (number expected) ex: 1,2,... (empty means 'check all interfaces'). + +=item B<--name> + +Allows you to define the interface (in option --interface) by name instead of OID index. The name matching mode supports regular expressions. + +=item B<--speed> + +Set interface speed for incoming/outgoing traffic (in Mb). + +=item B<--speed-in> + +Set interface speed for incoming traffic (in Mb). + +=item B<--speed-out> + +Set interface speed for outgoing traffic (in Mb). + +=item B<--map-speed-dsl> + +Get interface speed configuration for interface type 'adsl' and 'vdsl2'. + +Syntax: --map-speed-dsl=interface-src-name,interface-dsl-name + +E.g: --map-speed-dsl=Et0.835,Et0-vdsl2 + +=item B<--force-counters64> + +Force to use 64 bits counters only. Can be used to improve performance. + +=item B<--force-counters32> + +Force to use 32 bits counters (even in snmp v2c and v3). Should be used when 64 bits counters are buggy. + +=item B<--reload-cache-time> + +Time in minutes before reloading cache file (default: 180). + +=item B<--oid-filter> + +Define the OID to be used to filter interfaces (default: ifName) (values: ifDesc, ifAlias, ifName, IpAddr). + +=item B<--oid-display> + +Define the OID that will be used to name the interfaces (default: ifName) (values: ifDesc, ifAlias, ifName, IpAddr). + +=item B<--oid-extra-display> + +Add an OID to display. + +=item B<--display-transform-src> B<--display-transform-dst> + +Modify the interface name displayed by using a regular expression. + +Eg: adding --display-transform-src='eth' --display-transform-dst='ens' will replace all occurrences of 'eth' with 'ens' + +=item B<--show-cache> + +Display cache interface datas. + +=back + +=cut diff --git a/src/network/chapsvision/crossing/snmp/plugin.pm b/src/network/chapsvision/crossing/snmp/plugin.pm new file mode 100644 index 000000000..ff549e2db --- /dev/null +++ b/src/network/chapsvision/crossing/snmp/plugin.pm @@ -0,0 +1,49 @@ +# +# Copyright 2023 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::chapsvision::crossing::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->{modes} = { + 'antivirus' => 'network::chapsvision::crossing::snmp::mode::antivirus', + 'interfaces' => 'network::chapsvision::crossing::snmp::mode::interfaces', + 'list-interfaces' => 'snmp_standard::mode::listinterfaces' + }; + + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check ChapsVision CrossinG in SNMP. + +=cut